hashes: split sha256 crypto int separate files
What changed, and why it matters
This commit is a pure file reorganization: it splits the SHA-256 cryptographic implementation from one large file into several smaller files. The author explicitly states there is no logic change, and the diff shows the same code being moved into new modules with only minor module wiring adjustments. There is no security-relevant change visible.
No security action needed. Treat as routine refactoring. Standard review/CI is sufficient.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit deletes hashes/src/sha256/crypto.rs and creates hashes/src/sha256/crypto/{mod.rs,arm_sha2.rs,x86_shani.rs}, moving the existing ARM SHA2 intrinsics, x86 SHA-NI intrinsics, CPU feature detection, and software fallback code into separate files. The new mod.rs contains the shared dispatch logic, macros, and fallback implementation. No algorithmic constants, round logic, feature-gating, or unsafe blocks were modified; only module structure and visibility (pub(super)) changed. This is a code-move refactor.
Changed components
hashes/src/sha256/crypto.rshashes/src/sha256/crypto/mod.rshashes/src/sha256/crypto/arm_sha2.rshashes/src/sha256/crypto/x86_shani.rsInspect captured patch +1701 / −1683
diff --git a/hashes/src/sha256/crypto.rs b/hashes/src/sha256/crypto.rs
deleted file mode 100644
index 6742d3ce..00000000
--- a/hashes/src/sha256/crypto.rs
+++ /dev/null
@@ -1,1683 +0,0 @@
-// SPDX-License-Identifier: CC0-1.0
-
-#![allow(clippy::unreadable_literal)]
-#![allow(clippy::cast_ptr_alignment)]
-#![allow(clippy::too_many_lines)]
-#![allow(clippy::many_single_char_names)]
-
-#[cfg(target_arch = "aarch64")]
-#[cfg(any(feature = "cpufeatures", feature = "std"))]
-use core::arch::aarch64::{
- vaddq_u32, vld1q_u32, vreinterpretq_u32_u8, vreinterpretq_u8_u32, vrev32q_u8, vsha256h2q_u32,
- vsha256hq_u32, vsha256su0q_u32, vsha256su1q_u32, vst1q_u32,
-};
-#[cfg(target_arch = "x86")]
-#[cfg(any(feature = "cpufeatures", feature = "std"))]
-use core::arch::x86::{
- __m128i, _mm_add_epi32, _mm_alignr_epi8, _mm_blend_epi16, _mm_loadu_si128, _mm_set_epi64x,
- _mm_sha256msg1_epu32, _mm_sha256msg2_epu32, _mm_sha256rnds2_epu32, _mm_shuffle_epi32,
- _mm_shuffle_epi8, _mm_storeu_si128,
-};
-#[cfg(target_arch = "x86_64")]
-#[cfg(any(feature = "cpufeatures", feature = "std"))]
-use core::arch::x86_64::{
- __m128i, _mm_add_epi32, _mm_alignr_epi8, _mm_blend_epi16, _mm_loadu_si128, _mm_set_epi64x,
- _mm_sha256msg1_epu32, _mm_sha256msg2_epu32, _mm_sha256rnds2_epu32, _mm_shuffle_epi32,
- _mm_shuffle_epi8, _mm_storeu_si128,
-};
-
-use internals::slice::SliceExt;
-
-use super::{HashEngine, Midstate, BLOCK_SIZE};
-use crate::sha256d;
-
-#[cfg(feature = "cpufeatures")]
-#[cfg(target_arch = "aarch64")]
-// cpufeatures crate internally uses `u8::max_value()` which will be deprecated.
-// See: https://docs.rs/cpufeatures/0.2.17/src/cpufeatures/lib.rs.html#161
-#[allow(deprecated_in_future)]
-mod cpuid_sha256_aarch64 {
- cpufeatures::new!(inner, "sha2");
- pub fn get() -> bool { inner::get() }
-}
-#[cfg(feature = "cpufeatures")]
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-// cpufeatures crate internally uses `u8::max_value()` which will be deprecated.
-// See: https://docs.rs/cpufeatures/0.2.17/src/cpufeatures/lib.rs.html#161
-#[allow(deprecated_in_future)]
-mod cpuid_sha256_x86 {
- cpufeatures::new!(inner, "sha", "sse2", "ssse3", "sse4.1");
- pub fn get() -> bool { inner::get() }
-}
-
-#[allow(non_snake_case)]
-const fn Ch(x: u32, y: u32, z: u32) -> u32 { z ^ (x & (y ^ z)) }
-#[allow(non_snake_case)]
-const fn Maj(x: u32, y: u32, z: u32) -> u32 { (x & y) | (z & (x | y)) }
-#[allow(non_snake_case)]
-const fn Sigma0(x: u32) -> u32 { x.rotate_left(30) ^ x.rotate_left(19) ^ x.rotate_left(10) }
-#[allow(non_snake_case)]
-const fn Sigma1(x: u32) -> u32 { x.rotate_left(26) ^ x.rotate_left(21) ^ x.rotate_left(7) }
-const fn sigma0(x: u32) -> u32 { x.rotate_left(25) ^ x.rotate_left(14) ^ (x >> 3) }
-const fn sigma1(x: u32) -> u32 { x.rotate_left(15) ^ x.rotate_left(13) ^ (x >> 10) }
-
-#[cfg(feature = "small-hash")]
-#[macro_use]
-mod small_hash {
- use super::{sigma0, sigma1, Ch, Maj, Sigma0, Sigma1};
-
- #[rustfmt::skip]
- #[allow(clippy::too_many_arguments)]
- pub(super) const fn round(a: u32, b: u32, c: u32, d: u32, e: u32,
- f: u32, g: u32, h: u32, k: u32, w: u32) -> (u32, u32) {
- let t1 =
- h.wrapping_add(Sigma1(e)).wrapping_add(Ch(e, f, g)).wrapping_add(k).wrapping_add(w);
- let t2 = Sigma0(a).wrapping_add(Maj(a, b, c));
- (d.wrapping_add(t1), t1.wrapping_add(t2))
- }
- #[rustfmt::skip]
- #[allow(clippy::too_many_arguments)]
- pub(super) const fn later_round(a: u32, b: u32, c: u32, d: u32, e: u32,
- f: u32, g: u32, h: u32, k: u32, w: u32,
- w1: u32, w2: u32, w3: u32,
- ) -> (u32, u32, u32) {
- let w = w.wrapping_add(sigma1(w1)).wrapping_add(w2).wrapping_add(sigma0(w3));
- let (d, h) = round(a, b, c, d, e, f, g, h, k, w);
- (d, h, w)
- }
-
- macro_rules! round(
- // first round
- ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => (
- let updates = small_hash::round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w);
- $d = updates.0;
- $h = updates.1;
- );
- // later rounds we reassign $w before doing the first-round computation
- ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => (
- let updates = small_hash::later_round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w, $w1, $w2, $w3);
- $d = updates.0;
- $h = updates.1;
- $w = updates.2;
- )
- );
-}
-
-#[cfg(not(feature = "small-hash"))]
-#[macro_use]
-mod fast_hash {
- macro_rules! round(
- // first round
- ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => (
- let t1 = $h.wrapping_add(Sigma1($e)).wrapping_add(Ch($e, $f, $g)).wrapping_add($k).wrapping_add($w);
- let t2 = Sigma0($a).wrapping_add(Maj($a, $b, $c));
- $d = $d.wrapping_add(t1);
- $h = t1.wrapping_add(t2);
- );
- // later rounds we reassign $w before doing the first-round computation
- ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => (
- $w = $w.wrapping_add(sigma1($w1)).wrapping_add($w2).wrapping_add(sigma0($w3));
- round!($a, $b, $c, $d, $e, $f, $g, $h, $k, $w);
- )
- );
-}
-
-impl Midstate {
- #[allow(clippy::identity_op)] // more readable
- const fn read_u32(bytes: &[u8], index: usize) -> u32 {
- ((bytes[index + 0] as u32) << 24)
- | ((bytes[index + 1] as u32) << 16)
- | ((bytes[index + 2] as u32) << 8)
- | ((bytes[index + 3] as u32) << 0)
- }
-
- const fn copy_w(bytes: &[u8], index: usize) -> [u32; 16] {
- let mut w = [0u32; 16];
- let mut i = 0;
- while i < 16 {
- w[i] = Self::read_u32(bytes, index + i * 4);
- i += 1;
- }
- w
- }
-
- pub(super) const fn compute_midstate_unoptimized(bytes: &[u8], finalize: bool) -> Self {
- let mut state = [
- 0x6a09e667u32,
- 0xbb67ae85,
- 0x3c6ef372,
- 0xa54ff53a,
- 0x510e527f,
- 0x9b05688c,
- 0x1f83d9ab,
- 0x5be0cd19,
- ];
-
- let num_chunks = (bytes.len() + 9).div_ceil(64);
- let mut chunk = 0;
- #[allow(clippy::precedence)]
- while chunk < num_chunks {
- if !finalize && chunk + 1 == num_chunks {
- break;
- }
- let mut w = if chunk * 64 + 64 <= bytes.len() {
- Self::copy_w(bytes, chunk * 64)
- } else {
- let mut buf = [0; 64];
- let mut i = 0;
- let offset = chunk * 64;
- while offset + i < bytes.len() {
- buf[i] = bytes[offset + i];
- i += 1;
- }
- if (bytes.len() % 64 <= 64 - 9) || (chunk + 2 == num_chunks) {
- buf[i] = 0x80;
- }
- #[allow(clippy::identity_op)] // more readable
- #[allow(clippy::erasing_op)]
- if chunk + 1 == num_chunks {
- let bit_len = bytes.len() as u64 * 8;
- buf[64 - 8] = ((bit_len >> 8 * 7) & 0xFF) as u8;
- buf[64 - 7] = ((bit_len >> 8 * 6) & 0xFF) as u8;
- buf[64 - 6] = ((bit_len >> 8 * 5) & 0xFF) as u8;
- buf[64 - 5] = ((bit_len >> 8 * 4) & 0xFF) as u8;
- buf[64 - 4] = ((bit_len >> 8 * 3) & 0xFF) as u8;
- buf[64 - 3] = ((bit_len >> 8 * 2) & 0xFF) as u8;
- buf[64 - 2] = ((bit_len >> 8 * 1) & 0xFF) as u8;
- buf[64 - 1] = ((bit_len >> 8 * 0) & 0xFF) as u8;
- }
- Self::copy_w(&buf, 0)
- };
- chunk += 1;
-
- let mut a = state[0];
- let mut b = state[1];
- let mut c = state[2];
- let mut d = state[3];
- let mut e = state[4];
- let mut f = state[5];
- let mut g = state[6];
- let mut h = state[7];
-
- round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]);
- round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]);
- round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]);
- round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]);
- round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]);
- round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]);
- round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]);
- round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]);
- round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]);
- round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]);
- round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]);
- round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]);
- round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]);
- round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]);
- round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]);
- round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]);
-
- round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]);
- round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]);
- round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]);
- round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]);
- round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]);
- round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]);
- round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]);
- round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]);
- round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]);
- round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]);
- round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]);
- round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]);
- round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]);
- round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]);
- round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]);
- round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]);
-
- round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]);
- round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]);
- round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]);
- round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]);
- round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]);
- round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]);
- round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]);
- round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]);
- round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]);
- round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]);
- round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]);
- round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]);
- round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]);
- round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]);
- round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]);
- round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]);
-
- round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]);
- round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]);
- round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]);
- round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]);
- round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]);
- round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]);
- round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]);
- round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]);
- round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]);
- round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]);
- round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]);
- round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]);
- round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]);
- round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]);
- round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]);
- round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]);
-
- state[0] = state[0].wrapping_add(a);
- state[1] = state[1].wrapping_add(b);
- state[2] = state[2].wrapping_add(c);
- state[3] = state[3].wrapping_add(d);
- state[4] = state[4].wrapping_add(e);
- state[5] = state[5].wrapping_add(f);
- state[6] = state[6].wrapping_add(g);
- state[7] = state[7].wrapping_add(h);
- }
- let mut output = [0u8; 32];
- let mut i = 0;
- #[allow(clippy::identity_op)] // more readable
- while i < 8 {
- output[i * 4 + 0] = (state[i + 0] >> 24) as u8;
- output[i * 4 + 1] = (state[i + 0] >> 16) as u8;
- output[i * 4 + 2] = (state[i + 0] >> 8) as u8;
- output[i * 4 + 3] = (state[i + 0] >> 0) as u8;
- i += 1;
- }
- Self { bytes: output, bytes_hashed: bytes.len() as u64 }
- }
-}
-
-impl HashEngine {
- pub(super) fn process_blocks(state: &mut [u32; 8], blocks: &[u8]) {
- #[cfg(feature = "std")]
- #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
- {
- if std::is_x86_feature_detected!("sse4.1")
- && std::is_x86_feature_detected!("sha")
- && std::is_x86_feature_detected!("sse2")
- && std::is_x86_feature_detected!("ssse3")
- {
- for block in blocks.chunks_exact(BLOCK_SIZE) {
- unsafe { Self::process_block_simd_x86_intrinsics(state, block) };
- }
- return;
- }
- }
-
- #[cfg(feature = "cpufeatures")]
- #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
- {
- if cpuid_sha256_x86::get() {
- for block in blocks.chunks_exact(BLOCK_SIZE) {
- unsafe { Self::process_block_simd_x86_intrinsics(state, block) };
- }
- return;
- }
- }
-
- #[cfg(feature = "std")]
- #[cfg(target_arch = "aarch64")]
- {
- if std::arch::is_aarch64_feature_detected!("sha2") {
- for block in blocks.chunks_exact(BLOCK_SIZE) {
- unsafe { Self::process_block_simd_arm_intrinsics(state, block) };
- }
- return;
- }
- }
-
- #[cfg(feature = "cpufeatures")]
- #[cfg(target_arch = "aarch64")]
- {
- if cpuid_sha256_aarch64::get() {
- for block in blocks.chunks_exact(BLOCK_SIZE) {
- unsafe { Self::process_block_simd_arm_intrinsics(state, block) };
- }
- return;
- }
- }
-
- // fallback implementation without using any intrinsics
- Self::software_process_block(state, blocks);
- }
-
- pub(crate) fn sha256d_64(outputs: &mut [[u8; 32]], inputs: &[[u8; 64]]) {
- assert_eq!(outputs.len(), inputs.len());
- let mut i = 0;
- let count = inputs.len();
-
- // TODO: 8-way AVX2
- // TODO: 4-way SSE4.1
- // TODO: 2-way x86 SHA-NI
-
- // 2-way ARM SHA2
- #[cfg(feature = "std")]
- #[cfg(target_arch = "aarch64")]
- {
- if std::arch::is_aarch64_feature_detected!("sha2") {
- while count - i >= 2 {
- let out = <&mut [[u8; 32]; 2]>::try_from(&mut outputs[i..i + 2]).unwrap();
- let inp = <&[[u8; 64]; 2]>::try_from(&inputs[i..i + 2]).unwrap();
- unsafe { Self::sha256d_64_arm_2way(out, inp) };
- i += 2;
- }
- }
- }
-
- #[cfg(feature = "cpufeatures")]
- #[cfg(target_arch = "aarch64")]
- {
- if cpuid_sha256_aarch64::get() {
- while count - i >= 2 {
- let out = <&mut [[u8; 32]; 2]>::try_from(&mut outputs[i..i + 2]).unwrap();
- let inp = <&[[u8; 64]; 2]>::try_from(&inputs[i..i + 2]).unwrap();
- unsafe { Self::sha256d_64_arm_2way(out, inp) };
- i += 2;
- }
- }
- }
-
- // fallback
- while i < count {
- outputs[i] = sha256d::hash(&inputs[i]).to_byte_array();
- i += 1;
- }
- }
-
- #[cfg(any(feature = "cpufeatures", feature = "std"))]
- #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
- #[target_feature(enable = "sha,sse2,ssse3,sse4.1")]
- unsafe fn process_block_simd_x86_intrinsics(state: &mut [u32; 8], block: &[u8]) {
- // Code translated and based on from
- // https://github.com/noloader/SHA-Intrinsics/blob/4899efc81d1af159c1fd955936c673139f35aea9/sha256-x86.c
-
- /* sha256-x86.c - Intel SHA extensions using C intrinsics */
- /* Written and place in public domain by Jeffrey Walton */
- /* Based on code from Intel, and by Sean Gulley for */
- /* the miTLS project. */
-
- // Variable names are also kept the same as in the original C code for easier comparison.
- let (mut state0, mut state1);
- let (mut msg, mut tmp);
-
- let (mut msg0, mut msg1, mut msg2, mut msg3);
-
- let (abef_save, cdgh_save);
-
- #[allow(non_snake_case)]
- let MASK: __m128i =
- _mm_set_epi64x(0x0c0d_0e0f_0809_0a0bu64 as i64, 0x0405_0607_0001_0203u64 as i64);
-
- let block_offset = 0;
-
- // Load initial values
- // CAST SAFETY: loadu_si128 documentation states that mem_addr does not
- // need to be aligned on any particular boundary.
- tmp = _mm_loadu_si128(state.as_ptr().add(0).cast::<__m128i>());
- state1 = _mm_loadu_si128(state.as_ptr().add(4).cast::<__m128i>());
-
- tmp = _mm_shuffle_epi32(tmp, 0xB1); // CDAB
- state1 = _mm_shuffle_epi32(state1, 0x1B); // EFGH
- state0 = _mm_alignr_epi8(tmp, state1, 8); // ABEF
- state1 = _mm_blend_epi16(state1, tmp, 0xF0); // CDGH
-
- // Process a single block
- {
- // Save current state
- abef_save = state0;
- cdgh_save = state1;
-
- // Rounds 0-3
- msg = _mm_loadu_si128(block.as_ptr().add(block_offset).cast::<__m128i>());
- msg0 = _mm_shuffle_epi8(msg, MASK);
- msg = _mm_add_epi32(
- msg0,
- _mm_set_epi64x(0xE9B5DBA5B5C0FBCFu64 as i64, 0x71374491428A2F98u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
-
- // Rounds 4-7
- msg1 = _mm_loadu_si128(block.as_ptr().add(block_offset + 16).cast::<__m128i>());
- msg1 = _mm_shuffle_epi8(msg1, MASK);
- msg = _mm_add_epi32(
- msg1,
- _mm_set_epi64x(0xAB1C5ED5923F82A4u64 as i64, 0x59F111F13956C25Bu64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg0 = _mm_sha256msg1_epu32(msg0, msg1);
-
- // Rounds 8-11
- msg2 = _mm_loadu_si128(block.as_ptr().add(block_offset + 32).cast::<__m128i>());
- msg2 = _mm_shuffle_epi8(msg2, MASK);
- msg = _mm_add_epi32(
- msg2,
- _mm_set_epi64x(0x550C7DC3243185BEu64 as i64, 0x12835B01D807AA98u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg1 = _mm_sha256msg1_epu32(msg1, msg2);
-
- // Rounds 12-15
- msg3 = _mm_loadu_si128(block.as_ptr().add(block_offset + 48).cast::<__m128i>());
- msg3 = _mm_shuffle_epi8(msg3, MASK);
- msg = _mm_add_epi32(
- msg3,
- _mm_set_epi64x(0xC19BF1749BDC06A7u64 as i64, 0x80DEB1FE72BE5D74u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg3, msg2, 4);
- msg0 = _mm_add_epi32(msg0, tmp);
- msg0 = _mm_sha256msg2_epu32(msg0, msg3);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg2 = _mm_sha256msg1_epu32(msg2, msg3);
-
- // Rounds 16-19
- msg = _mm_add_epi32(
- msg0,
- _mm_set_epi64x(0x240CA1CC0FC19DC6u64 as i64, 0xEFBE4786E49B69C1u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg0, msg3, 4);
- msg1 = _mm_add_epi32(msg1, tmp);
- msg1 = _mm_sha256msg2_epu32(msg1, msg0);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg3 = _mm_sha256msg1_epu32(msg3, msg0);
-
- // Rounds 20-23
- msg = _mm_add_epi32(
- msg1,
- _mm_set_epi64x(0x76F988DA5CB0A9DCu64 as i64, 0x4A7484AA2DE92C6Fu64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg1, msg0, 4);
- msg2 = _mm_add_epi32(msg2, tmp);
- msg2 = _mm_sha256msg2_epu32(msg2, msg1);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg0 = _mm_sha256msg1_epu32(msg0, msg1);
-
- // Rounds 24-27
- msg = _mm_add_epi32(
- msg2,
- _mm_set_epi64x(0xBF597FC7B00327C8u64 as i64, 0xA831C66D983E5152u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg2, msg1, 4);
- msg3 = _mm_add_epi32(msg3, tmp);
- msg3 = _mm_sha256msg2_epu32(msg3, msg2);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg1 = _mm_sha256msg1_epu32(msg1, msg2);
-
- // Rounds 28-31
- msg = _mm_add_epi32(
- msg3,
- _mm_set_epi64x(0x1429296706CA6351u64 as i64, 0xD5A79147C6E00BF3u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg3, msg2, 4);
- msg0 = _mm_add_epi32(msg0, tmp);
- msg0 = _mm_sha256msg2_epu32(msg0, msg3);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg2 = _mm_sha256msg1_epu32(msg2, msg3);
-
- // Rounds 32-35
- msg = _mm_add_epi32(
- msg0,
- _mm_set_epi64x(0x53380D134D2C6DFCu64 as i64, 0x2E1B213827B70A85u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg0, msg3, 4);
- msg1 = _mm_add_epi32(msg1, tmp);
- msg1 = _mm_sha256msg2_epu32(msg1, msg0);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg3 = _mm_sha256msg1_epu32(msg3, msg0);
-
- // Rounds 36-39
- msg = _mm_add_epi32(
- msg1,
- _mm_set_epi64x(0x92722C8581C2C92Eu64 as i64, 0x766A0ABB650A7354u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg1, msg0, 4);
- msg2 = _mm_add_epi32(msg2, tmp);
- msg2 = _mm_sha256msg2_epu32(msg2, msg1);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg0 = _mm_sha256msg1_epu32(msg0, msg1);
-
- // Rounds 40-43
- msg = _mm_add_epi32(
- msg2,
- _mm_set_epi64x(0xC76C51A3C24B8B70u64 as i64, 0xA81A664BA2BFE8A1u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg2, msg1, 4);
- msg3 = _mm_add_epi32(msg3, tmp);
- msg3 = _mm_sha256msg2_epu32(msg3, msg2);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg1 = _mm_sha256msg1_epu32(msg1, msg2);
-
- // Rounds 44-47
- msg = _mm_add_epi32(
- msg3,
- _mm_set_epi64x(0x106AA070F40E3585u64 as i64, 0xD6990624D192E819u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg3, msg2, 4);
- msg0 = _mm_add_epi32(msg0, tmp);
- msg0 = _mm_sha256msg2_epu32(msg0, msg3);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg2 = _mm_sha256msg1_epu32(msg2, msg3);
-
- // Rounds 48-51
- msg = _mm_add_epi32(
- msg0,
- _mm_set_epi64x(0x34B0BCB52748774Cu64 as i64, 0x1E376C0819A4C116u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg0, msg3, 4);
- msg1 = _mm_add_epi32(msg1, tmp);
- msg1 = _mm_sha256msg2_epu32(msg1, msg0);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
- msg3 = _mm_sha256msg1_epu32(msg3, msg0);
-
- // Rounds 52-55
- msg = _mm_add_epi32(
- msg1,
- _mm_set_epi64x(0x682E6FF35B9CCA4Fu64 as i64, 0x4ED8AA4A391C0CB3u64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg1, msg0, 4);
- msg2 = _mm_add_epi32(msg2, tmp);
- msg2 = _mm_sha256msg2_epu32(msg2, msg1);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
-
- // Rounds 56-59
- msg = _mm_add_epi32(
- msg2,
- _mm_set_epi64x(0x8CC7020884C87814u64 as i64, 0x78A5636F748F82EEu64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- tmp = _mm_alignr_epi8(msg2, msg1, 4);
- msg3 = _mm_add_epi32(msg3, tmp);
- msg3 = _mm_sha256msg2_epu32(msg3, msg2);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
-
- // Rounds 60-63
- msg = _mm_add_epi32(
- msg3,
- _mm_set_epi64x(0xC67178F2BEF9A3F7u64 as i64, 0xA4506CEB90BEFFFAu64 as i64),
- );
- state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
- msg = _mm_shuffle_epi32(msg, 0x0E);
- state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
-
- // Combine state
- state0 = _mm_add_epi32(state0, abef_save);
- state1 = _mm_add_epi32(state1, cdgh_save);
- }
-
- tmp = _mm_shuffle_epi32(state0, 0x1B); // FEBA
- state1 = _mm_shuffle_epi32(state1, 0xB1); // DCHG
- state0 = _mm_blend_epi16(tmp, state1, 0xF0); // DCBA
- state1 = _mm_alignr_epi8(state1, tmp, 8); // ABEF
-
- // Save state
- // CAST SAFETY: storeu_si128 documentation states that mem_addr does not
- // need to be aligned on any particular boundary.
- _mm_storeu_si128(state.as_mut_ptr().add(0).cast::<__m128i>(), state0);
- _mm_storeu_si128(state.as_mut_ptr().add(4).cast::<__m128i>(), state1);
- }
-
- #[cfg(target_arch = "aarch64")]
- #[cfg(any(feature = "cpufeatures", feature = "std"))]
- #[target_feature(enable = "sha2")]
- unsafe fn process_block_simd_arm_intrinsics(state: &mut [u32; 8], block: &[u8]) {
- // Code translated and based on from
- // https://github.com/noloader/SHA-Intrinsics/blob/4e754bec921a9f281b69bd681ca0065763aa911c/sha256-arm.c
-
- /* sha256-arm.c - ARMv8 SHA extensions using C intrinsics */
- /* Written and placed in public domain by Jeffrey Walton */
- /* Based on code from ARM, and by Johannes Schneiders, Skip */
- /* Hovsmith and Barry O'Rourke for the mbedTLS project. */
-
- // SHA256 round constants
- #[rustfmt::skip]
- const K: [u32; 64] = [
- 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
- 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
- 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
- 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
- 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
- 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
- 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
- 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
- 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
- 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
- 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
- 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
- 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
- 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
- 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
- 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
- ];
-
- let (mut state0, mut state1);
- let (abcd_save, efgh_save);
-
- let (mut msg0, mut msg1, mut msg2, mut msg3);
- let (mut tmp0, mut tmp1, mut tmp2);
-
- // Load state
- state0 = vld1q_u32(state.as_ptr().add(0));
- state1 = vld1q_u32(state.as_ptr().add(4));
-
- // Save state
- abcd_save = state0;
- efgh_save = state1;
-
- // Load message
- msg0 = vld1q_u32(block.as_ptr().add(0).cast::<u32>());
- msg1 = vld1q_u32(block.as_ptr().add(16).cast::<u32>());
- msg2 = vld1q_u32(block.as_ptr().add(32).cast::<u32>());
- msg3 = vld1q_u32(block.as_ptr().add(48).cast::<u32>());
-
- // Reverse for little endian
- msg0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg0)));
- msg1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg1)));
- msg2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg2)));
- msg3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg3)));
-
- tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x00)));
-
- // Rounds 0-3
- msg0 = vsha256su0q_u32(msg0, msg1);
- tmp2 = state0;
- tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x04)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
- msg0 = vsha256su1q_u32(msg0, msg2, msg3);
-
- // Rounds 4-7
- msg1 = vsha256su0q_u32(msg1, msg2);
- tmp2 = state0;
- tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x08)));
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
- msg1 = vsha256su1q_u32(msg1, msg3, msg0);
-
- // Rounds 8-11
- msg2 = vsha256su0q_u32(msg2, msg3);
- tmp2 = state0;
- tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x0c)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
- msg2 = vsha256su1q_u32(msg2, msg0, msg1);
-
- // Rounds 12-15
- msg3 = vsha256su0q_u32(msg3, msg0);
- tmp2 = state0;
- tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x10)));
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
- msg3 = vsha256su1q_u32(msg3, msg1, msg2);
-
- // Rounds 16-19
- msg0 = vsha256su0q_u32(msg0, msg1);
- tmp2 = state0;
- tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x14)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
- msg0 = vsha256su1q_u32(msg0, msg2, msg3);
-
- // Rounds 20-23
- msg1 = vsha256su0q_u32(msg1, msg2);
- tmp2 = state0;
- tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x18)));
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
- msg1 = vsha256su1q_u32(msg1, msg3, msg0);
-
- // Rounds 24-27
- msg2 = vsha256su0q_u32(msg2, msg3);
- tmp2 = state0;
- tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x1c)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
- msg2 = vsha256su1q_u32(msg2, msg0, msg1);
-
- // Rounds 28-31
- msg3 = vsha256su0q_u32(msg3, msg0);
- tmp2 = state0;
- tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x20)));
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
- msg3 = vsha256su1q_u32(msg3, msg1, msg2);
-
- // Rounds 32-35
- msg0 = vsha256su0q_u32(msg0, msg1);
- tmp2 = state0;
- tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x24)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
- msg0 = vsha256su1q_u32(msg0, msg2, msg3);
-
- // Rounds 36-39
- msg1 = vsha256su0q_u32(msg1, msg2);
- tmp2 = state0;
- tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x28)));
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
- msg1 = vsha256su1q_u32(msg1, msg3, msg0);
-
- // Rounds 40-43
- msg2 = vsha256su0q_u32(msg2, msg3);
- tmp2 = state0;
- tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x2c)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
- msg2 = vsha256su1q_u32(msg2, msg0, msg1);
-
- // Rounds 44-47
- msg3 = vsha256su0q_u32(msg3, msg0);
- tmp2 = state0;
- tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x30)));
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
- msg3 = vsha256su1q_u32(msg3, msg1, msg2);
-
- // Rounds 48-51
- tmp2 = state0;
- tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x34)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
-
- // Rounds 52-55
- tmp2 = state0;
- tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x38)));
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
-
- // Rounds 56-59
- tmp2 = state0;
- tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x3c)));
- state0 = vsha256hq_u32(state0, state1, tmp0);
- state1 = vsha256h2q_u32(state1, tmp2, tmp0);
-
- // Rounds 60-63
- tmp2 = state0;
- state0 = vsha256hq_u32(state0, state1, tmp1);
- state1 = vsha256h2q_u32(state1, tmp2, tmp1);
-
- // Combine state
- state0 = vaddq_u32(state0, abcd_save);
- state1 = vaddq_u32(state1, efgh_save);
-
- // Save state
- vst1q_u32(state.as_mut_ptr().add(0), state0);
- vst1q_u32(state.as_mut_ptr().add(4), state1);
- }
-
- #[cfg(target_arch = "aarch64")]
- #[cfg(any(feature = "cpufeatures", feature = "std"))]
- #[target_feature(enable = "sha2")]
- unsafe fn sha256d_64_arm_2way(output: &mut [[u8; 32]; 2], input: &[[u8; 64]; 2]) {
- // Based on Bitcoin Core's sha256d64_arm_shani::Transform_2way
- // https://github.com/bitcoin/bitcoin/blob/master/src/crypto/sha256_arm_shani.cpp#L200-L895
- use core::arch::aarch64::vst1q_u8;
-
- // initial state
- #[rustfmt::skip]
- const INIT: [u32; 8] = [
- 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
- 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
- ];
-
- // SHA256 round constants
- #[rustfmt::skip]
- const K: [u32; 64] = [
- 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
- 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
- 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
- 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
- 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
- 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
- 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
- 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
- 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
- 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
- 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
- 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
- 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
- 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
- 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
- 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
- ];
-
- // Precomputed W[i] + K[i] for the 2nd transform (padding block).
- #[rustfmt::skip]
- const MIDS: [u32; 64] = [
- 0xc28a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf374,
- 0x649b69c1, 0xf0fe4786, 0x0fe1edc6, 0x240cf254,
- 0x4fe9346f, 0x6cc984be, 0x61b9411e, 0x16f988fa,
- 0xf2c65152, 0xa88e5a6d, 0xb019fc65, 0xb9d99ec7,
- 0x9a1231c3, 0xe70eeaa0, 0xfdb1232b, 0xc7353eb0,
- 0x3069bad5, 0xcb976d5f, 0x5a0f118f, 0xdc1eeefd,
- 0x0a35b689, 0xde0b7a04, 0x58f4ca9d, 0xe15d5b16,
- 0x007f3e86, 0x37088980, 0xa507ea32, 0x6fab9537,
- 0x17406110, 0x0d8cd6f1, 0xcdaa3b6d, 0xc0bbbe37,
- 0x83613bda, 0xdb48a363, 0x0b02e931, 0x6fd15ca7,
- 0x521afaca, 0x31338431, 0x6ed41a95, 0x6d437890,
- 0xc39c91f2, 0x9eccabbd, 0xb5c9a0e6, 0x532fb63c,
- 0xd2c741c6, 0x07237ea3, 0xa4954b68, 0x4c191d76
- ];
-
- // Precomputed values for Transform 3 rounds 9-16.
- // FINS[0..3]: msg2 + K[8..11]
- // FINS[4..7]: vsha256su0q_u32(msg2, msg3)
- // FINS[8..11]: msg2 + K[12..15]
- #[rustfmt::skip]
- const FINS: [u32; 12] = [
- 0x5807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x80000000, 0x00000000, 0x00000000, 0x00000000,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf274,
- ];
-
- // Padding processed in the 3rd transform (byteswapped).
- const FINAL: [u32; 8] = [0x80000000, 0, 0, 0, 0, 0, 0, 0x100];
-
- let (mut state0_a, mut state0_b, mut state1_a, mut state1_b);
- let (abcd_save_a, abcd_save_b, efgh_save_a, efgh_save_b);
-
- #[rustfmt::skip]
- let (mut msg0_a, mut msg0_b, mut msg1_a, mut msg1_b, mut msg2_a, mut msg2_b, mut msg3_a, mut msg3_b);
- let (mut tmp0_a, mut tmp0_b, mut tmp2_a, mut tmp2_b, mut tmp);
-
- // Load state
- state0_a = vld1q_u32(INIT.as_ptr().add(0));
- state0_b = state0_a;
- state1_a = vld1q_u32(INIT.as_ptr().add(4));
- state1_b = state1_a;
-
- // Load message
- msg0_a = vld1q_u32(input[0].as_ptr().add(0).cast::<u32>());
- msg1_a = vld1q_u32(input[0].as_ptr().add(16).cast::<u32>());
- msg2_a = vld1q_u32(input[0].as_ptr().add(32).cast::<u32>());
- msg3_a = vld1q_u32(input[0].as_ptr().add(48).cast::<u32>());
- msg0_b = vld1q_u32(input[1].as_ptr().add(0).cast::<u32>());
- msg1_b = vld1q_u32(input[1].as_ptr().add(16).cast::<u32>());
- msg2_b = vld1q_u32(input[1].as_ptr().add(32).cast::<u32>());
- msg3_b = vld1q_u32(input[1].as_ptr().add(48).cast::<u32>());
-
- // Reverse for little endian
- msg0_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg0_a)));
- msg1_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg1_a)));
- msg2_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg2_a)));
- msg3_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg3_a)));
- msg0_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg0_b)));
- msg1_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg1_b)));
- msg2_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg2_b)));
- msg3_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg3_b)));
-
- // Transform 1: Rounds 1-4
- tmp = vld1q_u32(K.as_ptr().add(0));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
- msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
- msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
-
- // Transform 1: Rounds 5-8
- tmp = vld1q_u32(K.as_ptr().add(4));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
- msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
- msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
-
- // Transform 1: Rounds 9-12
- tmp = vld1q_u32(K.as_ptr().add(8));
- tmp0_a = vaddq_u32(msg2_a, tmp);
- tmp0_b = vaddq_u32(msg2_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
- msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
- msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
-
- // Transform 1: Rounds 13-16
- tmp = vld1q_u32(K.as_ptr().add(12));
- tmp0_a = vaddq_u32(msg3_a, tmp);
- tmp0_b = vaddq_u32(msg3_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
- msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
- msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
-
- // Transform 1: Rounds 17-20
- tmp = vld1q_u32(K.as_ptr().add(16));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
- msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
- msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
-
- // Transform 1: Rounds 21-24
- tmp = vld1q_u32(K.as_ptr().add(20));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
- msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
- msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
-
- // Transform 1: Rounds 25-28
- tmp = vld1q_u32(K.as_ptr().add(24));
- tmp0_a = vaddq_u32(msg2_a, tmp);
- tmp0_b = vaddq_u32(msg2_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
- msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
- msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
-
- // Transform 1: Rounds 29-32
- tmp = vld1q_u32(K.as_ptr().add(28));
- tmp0_a = vaddq_u32(msg3_a, tmp);
- tmp0_b = vaddq_u32(msg3_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
- msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
- msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
-
- // Transform 1: Rounds 33-36
- tmp = vld1q_u32(K.as_ptr().add(32));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
- msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
- msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
-
- // Transform 1: Rounds 37-40
- tmp = vld1q_u32(K.as_ptr().add(36));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
- msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
- msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
-
- // Transform 1: Rounds 41-44
- tmp = vld1q_u32(K.as_ptr().add(40));
- tmp0_a = vaddq_u32(msg2_a, tmp);
- tmp0_b = vaddq_u32(msg2_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
- msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
- msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
-
- // Transform 1: Rounds 45-48
- tmp = vld1q_u32(K.as_ptr().add(44));
- tmp0_a = vaddq_u32(msg3_a, tmp);
- tmp0_b = vaddq_u32(msg3_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
- msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
- msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
-
- // Transform 1: Rounds 49-52
- tmp = vld1q_u32(K.as_ptr().add(48));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 1: Rounds 53-56
- tmp = vld1q_u32(K.as_ptr().add(52));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 1: Rounds 57-60
- tmp = vld1q_u32(K.as_ptr().add(56));
- tmp0_a = vaddq_u32(msg2_a, tmp);
- tmp0_b = vaddq_u32(msg2_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 1: Rounds 61-64
- tmp = vld1q_u32(K.as_ptr().add(60));
- tmp0_a = vaddq_u32(msg3_a, tmp);
- tmp0_b = vaddq_u32(msg3_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 1: Update state
- tmp = vld1q_u32(&INIT[0]);
- state0_a = vaddq_u32(state0_a, tmp);
- state0_b = vaddq_u32(state0_b, tmp);
- tmp = vld1q_u32(&INIT[4]);
- state1_a = vaddq_u32(state1_a, tmp);
- state1_b = vaddq_u32(state1_b, tmp);
-
- // ------------------ Transform 2 -------------------
-
- // Transform 2: Save state
- abcd_save_a = state0_a;
- abcd_save_b = state0_b;
- efgh_save_a = state1_a;
- efgh_save_b = state1_b;
-
- // Transform 2: Rounds 1-4
- tmp = vld1q_u32(MIDS.as_ptr().add(0));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 5-8
- tmp = vld1q_u32(MIDS.as_ptr().add(4));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 9-12
- tmp = vld1q_u32(MIDS.as_ptr().add(8));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 13-16
- tmp = vld1q_u32(MIDS.as_ptr().add(12));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 17-20
- tmp = vld1q_u32(MIDS.as_ptr().add(16));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 21-24
- tmp = vld1q_u32(MIDS.as_ptr().add(20));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 25-28
- tmp = vld1q_u32(MIDS.as_ptr().add(24));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 29-32
- tmp = vld1q_u32(MIDS.as_ptr().add(28));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 33-36
- tmp = vld1q_u32(MIDS.as_ptr().add(32));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 37-40
- tmp = vld1q_u32(MIDS.as_ptr().add(36));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 41-44
- tmp = vld1q_u32(MIDS.as_ptr().add(40));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 45-48
- tmp = vld1q_u32(MIDS.as_ptr().add(44));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 49-52
- tmp = vld1q_u32(MIDS.as_ptr().add(48));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 53-56
- tmp = vld1q_u32(MIDS.as_ptr().add(52));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 57-60
- tmp = vld1q_u32(MIDS.as_ptr().add(56));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Rounds 61-64
- tmp = vld1q_u32(MIDS.as_ptr().add(60));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
-
- // Transform 2: Update state
- state0_a = vaddq_u32(state0_a, abcd_save_a);
- state0_b = vaddq_u32(state0_b, abcd_save_b);
- state1_a = vaddq_u32(state1_a, efgh_save_a);
- state1_b = vaddq_u32(state1_b, efgh_save_b);
-
- // ------------------ Transform 3 -------------------
-
- msg0_a = state0_a;
- msg0_b = state0_b;
- msg1_a = state1_a;
- msg1_b = state1_b;
- msg2_a = vld1q_u32(FINAL.as_ptr().add(0));
- msg2_b = msg2_a;
- msg3_a = vld1q_u32(FINAL.as_ptr().add(4));
- msg3_b = msg3_a;
-
- // Transform 3: Load state
- state0_a = vld1q_u32(INIT.as_ptr());
- state0_b = state0_a;
- state1_a = vld1q_u32(INIT.as_ptr().add(4));
- state1_b = state1_a;
-
- // Transform 3: Rounds 1-4
- tmp = vld1q_u32(K.as_ptr().add(0));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
- msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
- msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
-
- // Transform 3: Rounds 5-8
- tmp = vld1q_u32(K.as_ptr().add(4));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
- msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
- msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
-
- // Transform 3: Rounds 9-12
- tmp = vld1q_u32(FINS.as_ptr().add(0));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg2_a = vld1q_u32(FINS.as_ptr().add(4));
- msg2_b = msg2_a;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
- msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
- msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
-
- // Transform 3: Rounds 13-16
- tmp = vld1q_u32(FINS.as_ptr().add(8));
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
- msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
- msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
- msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
-
- // Transform 3: Rounds 17-20
- tmp = vld1q_u32(K.as_ptr().add(16));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
- msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
- msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
-
- // Transform 3: Rounds 21-24
- tmp = vld1q_u32(K.as_ptr().add(20));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
- msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
- msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
-
- // Transform 3: Rounds 25-28
- tmp = vld1q_u32(K.as_ptr().add(24));
- tmp0_a = vaddq_u32(msg2_a, tmp);
- tmp0_b = vaddq_u32(msg2_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
- msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
- msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
-
- // Transform 3: Rounds 29-32
- tmp = vld1q_u32(K.as_ptr().add(28));
- tmp0_a = vaddq_u32(msg3_a, tmp);
- tmp0_b = vaddq_u32(msg3_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
- msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
- msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
-
- // Transform 3: Rounds 33-36
- tmp = vld1q_u32(K.as_ptr().add(32));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
- msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
- msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
-
- // Transform 3: Rounds 37-40
- tmp = vld1q_u32(K.as_ptr().add(36));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
- msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
- msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
-
- // Transform 3: Rounds 41-44
- tmp = vld1q_u32(K.as_ptr().add(40));
- tmp0_a = vaddq_u32(msg2_a, tmp);
- tmp0_b = vaddq_u32(msg2_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
- msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
- msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
-
- // Transform 3: Rounds 45-48
- tmp = vld1q_u32(K.as_ptr().add(44));
- tmp0_a = vaddq_u32(msg3_a, tmp);
- tmp0_b = vaddq_u32(msg3_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
- msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
- msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
- msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
-
- // Transform 3: Rounds 49-52
- tmp = vld1q_u32(K.as_ptr().add(48));
- tmp0_a = vaddq_u32(msg0_a, tmp);
- tmp0_b = vaddq_u32(msg0_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 3: Rounds 53-56
- tmp = vld1q_u32(K.as_ptr().add(52));
- tmp0_a = vaddq_u32(msg1_a, tmp);
- tmp0_b = vaddq_u32(msg1_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 3: Rounds 57-60
- tmp = vld1q_u32(K.as_ptr().add(56));
- tmp0_a = vaddq_u32(msg2_a, tmp);
- tmp0_b = vaddq_u32(msg2_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 3: Rounds 61-64
- tmp = vld1q_u32(K.as_ptr().add(60));
- tmp0_a = vaddq_u32(msg3_a, tmp);
- tmp0_b = vaddq_u32(msg3_b, tmp);
- tmp2_a = state0_a;
- tmp2_b = state0_b;
- state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
- state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
- state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
- state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
-
- // Transform 3: Update state
- tmp = vld1q_u32(INIT.as_ptr().add(0));
- state0_a = vaddq_u32(state0_a, tmp);
- state0_b = vaddq_u32(state0_b, tmp);
- tmp = vld1q_u32(INIT.as_ptr().add(4));
- state1_a = vaddq_u32(state1_a, tmp);
- state1_b = vaddq_u32(state1_b, tmp);
-
- // Store result
- vst1q_u8(output[0].as_mut_ptr().add(0), vrev32q_u8(vreinterpretq_u8_u32(state0_a)));
- vst1q_u8(output[0].as_mut_ptr().add(16), vrev32q_u8(vreinterpretq_u8_u32(state1_a)));
- vst1q_u8(output[1].as_mut_ptr().add(0), vrev32q_u8(vreinterpretq_u8_u32(state0_b)));
- vst1q_u8(output[1].as_mut_ptr().add(16), vrev32q_u8(vreinterpretq_u8_u32(state1_b)));
- }
-
- // Algorithm copied from libsecp256k1
- fn software_process_block(state: &mut [u32; 8], blocks: &[u8]) {
- debug_assert!(!blocks.is_empty() && blocks.len() % BLOCK_SIZE == 0);
-
- for block in blocks.chunks_exact(BLOCK_SIZE) {
- let mut w = [0u32; 16];
- for (w_val, buff_bytes) in w.iter_mut().zip(block.bitcoin_as_chunks().0) {
- *w_val = u32::from_be_bytes(*buff_bytes);
- }
-
- let mut a = state[0];
- let mut b = state[1];
- let mut c = state[2];
- let mut d = state[3];
- let mut e = state[4];
- let mut f = state[5];
- let mut g = state[6];
- let mut h = state[7];
-
- round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]);
- round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]);
- round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]);
- round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]);
- round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]);
- round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]);
- round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]);
- round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]);
- round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]);
- round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]);
- round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]);
- round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]);
- round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]);
- round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]);
- round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]);
- round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]);
-
- round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]);
- round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]);
- round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]);
- round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]);
- round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]);
- round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]);
- round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]);
- round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]);
- round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]);
- round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]);
- round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]);
- round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]);
- round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]);
- round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]);
- round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]);
- round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]);
-
- round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]);
- round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]);
- round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]);
- round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]);
- round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]);
- round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]);
- round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]);
- round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]);
- round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]);
- round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]);
- round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]);
- round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]);
- round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]);
- round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]);
- round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]);
- round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]);
-
- round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]);
- round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]);
- round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]);
- round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]);
- round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]);
- round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]);
- round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]);
- round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]);
- round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]);
- round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]);
- round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]);
- round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]);
- round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]);
- round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]);
- round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]);
- round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]);
- let _ = w[15]; // silence "unnecessary assignment" lint in macro
-
- state[0] = state[0].wrapping_add(a);
- state[1] = state[1].wrapping_add(b);
- state[2] = state[2].wrapping_add(c);
- state[3] = state[3].wrapping_add(d);
- state[4] = state[4].wrapping_add(e);
- state[5] = state[5].wrapping_add(f);
- state[6] = state[6].wrapping_add(g);
- state[7] = state[7].wrapping_add(h);
- }
- }
-}
diff --git a/hashes/src/sha256/crypto/arm_sha2.rs b/hashes/src/sha256/crypto/arm_sha2.rs
new file mode 100644
index 00000000..812f1c5c
--- /dev/null
+++ b/hashes/src/sha256/crypto/arm_sha2.rs
@@ -0,0 +1,947 @@
+// SPDX-License-Identifier: CC0-1.0
+
+//! ARM sha2 intrinsics for sha256.
+
+#![allow(clippy::unreadable_literal)]
+#![allow(clippy::cast_ptr_alignment)]
+#![allow(clippy::too_many_lines)]
+#![allow(clippy::many_single_char_names)]
+
+use core::arch::aarch64::{
+ vaddq_u32, vld1q_u32, vreinterpretq_u32_u8, vreinterpretq_u8_u32, vrev32q_u8, vsha256h2q_u32,
+ vsha256hq_u32, vsha256su0q_u32, vsha256su1q_u32, vst1q_u32,
+};
+
+/// Processes a single sha256 block using ARM SHA2 intrinsics.
+#[target_feature(enable = "sha2")]
+pub(super) unsafe fn process_block(state: &mut [u32; 8], block: &[u8]) {
+ // Code translated and based on from
+ // https://github.com/noloader/SHA-Intrinsics/blob/4e754bec921a9f281b69bd681ca0065763aa911c/sha256-arm.c
+
+ /* sha256-arm.c - ARMv8 SHA extensions using C intrinsics */
+ /* Written and placed in public domain by Jeffrey Walton */
+ /* Based on code from ARM, and by Johannes Schneiders, Skip */
+ /* Hovsmith and Barry O'Rourke for the mbedTLS project. */
+
+ // SHA256 round constants
+ #[rustfmt::skip]
+ const K: [u32; 64] = [
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+ ];
+
+ let (mut state0, mut state1);
+ let (abcd_save, efgh_save);
+
+ let (mut msg0, mut msg1, mut msg2, mut msg3);
+ let (mut tmp0, mut tmp1, mut tmp2);
+
+ // Load state
+ state0 = vld1q_u32(state.as_ptr().add(0));
+ state1 = vld1q_u32(state.as_ptr().add(4));
+
+ // Save state
+ abcd_save = state0;
+ efgh_save = state1;
+
+ // Load message
+ msg0 = vld1q_u32(block.as_ptr().add(0).cast::<u32>());
+ msg1 = vld1q_u32(block.as_ptr().add(16).cast::<u32>());
+ msg2 = vld1q_u32(block.as_ptr().add(32).cast::<u32>());
+ msg3 = vld1q_u32(block.as_ptr().add(48).cast::<u32>());
+
+ // Reverse for little endian
+ msg0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg0)));
+ msg1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg1)));
+ msg2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg2)));
+ msg3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg3)));
+
+ tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x00)));
+
+ // Rounds 0-3
+ msg0 = vsha256su0q_u32(msg0, msg1);
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x04)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+ msg0 = vsha256su1q_u32(msg0, msg2, msg3);
+
+ // Rounds 4-7
+ msg1 = vsha256su0q_u32(msg1, msg2);
+ tmp2 = state0;
+ tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x08)));
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+ msg1 = vsha256su1q_u32(msg1, msg3, msg0);
+
+ // Rounds 8-11
+ msg2 = vsha256su0q_u32(msg2, msg3);
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x0c)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+ msg2 = vsha256su1q_u32(msg2, msg0, msg1);
+
+ // Rounds 12-15
+ msg3 = vsha256su0q_u32(msg3, msg0);
+ tmp2 = state0;
+ tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x10)));
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+ msg3 = vsha256su1q_u32(msg3, msg1, msg2);
+
+ // Rounds 16-19
+ msg0 = vsha256su0q_u32(msg0, msg1);
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x14)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+ msg0 = vsha256su1q_u32(msg0, msg2, msg3);
+
+ // Rounds 20-23
+ msg1 = vsha256su0q_u32(msg1, msg2);
+ tmp2 = state0;
+ tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x18)));
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+ msg1 = vsha256su1q_u32(msg1, msg3, msg0);
+
+ // Rounds 24-27
+ msg2 = vsha256su0q_u32(msg2, msg3);
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x1c)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+ msg2 = vsha256su1q_u32(msg2, msg0, msg1);
+
+ // Rounds 28-31
+ msg3 = vsha256su0q_u32(msg3, msg0);
+ tmp2 = state0;
+ tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x20)));
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+ msg3 = vsha256su1q_u32(msg3, msg1, msg2);
+
+ // Rounds 32-35
+ msg0 = vsha256su0q_u32(msg0, msg1);
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x24)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+ msg0 = vsha256su1q_u32(msg0, msg2, msg3);
+
+ // Rounds 36-39
+ msg1 = vsha256su0q_u32(msg1, msg2);
+ tmp2 = state0;
+ tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x28)));
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+ msg1 = vsha256su1q_u32(msg1, msg3, msg0);
+
+ // Rounds 40-43
+ msg2 = vsha256su0q_u32(msg2, msg3);
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x2c)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+ msg2 = vsha256su1q_u32(msg2, msg0, msg1);
+
+ // Rounds 44-47
+ msg3 = vsha256su0q_u32(msg3, msg0);
+ tmp2 = state0;
+ tmp0 = vaddq_u32(msg0, vld1q_u32(K.as_ptr().add(0x30)));
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+ msg3 = vsha256su1q_u32(msg3, msg1, msg2);
+
+ // Rounds 48-51
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg1, vld1q_u32(K.as_ptr().add(0x34)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+
+ // Rounds 52-55
+ tmp2 = state0;
+ tmp0 = vaddq_u32(msg2, vld1q_u32(K.as_ptr().add(0x38)));
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+
+ // Rounds 56-59
+ tmp2 = state0;
+ tmp1 = vaddq_u32(msg3, vld1q_u32(K.as_ptr().add(0x3c)));
+ state0 = vsha256hq_u32(state0, state1, tmp0);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp0);
+
+ // Rounds 60-63
+ tmp2 = state0;
+ state0 = vsha256hq_u32(state0, state1, tmp1);
+ state1 = vsha256h2q_u32(state1, tmp2, tmp1);
+
+ // Combine state
+ state0 = vaddq_u32(state0, abcd_save);
+ state1 = vaddq_u32(state1, efgh_save);
+
+ // Save state
+ vst1q_u32(state.as_mut_ptr().add(0), state0);
+ vst1q_u32(state.as_mut_ptr().add(4), state1);
+}
+
+/// computes `SHA256d` of two 64-byte inputs in parallel using ARM SHA2 intrinsics.
+#[target_feature(enable = "sha2")]
+pub(super) unsafe fn sha256d_64_2way(output: &mut [[u8; 32]; 2], input: &[[u8; 64]; 2]) {
+ // Based on Bitcoin Core's sha256d64_arm_shani::Transform_2way
+ // https://github.com/bitcoin/bitcoin/blob/master/src/crypto/sha256_arm_shani.cpp#L200-L895
+ use core::arch::aarch64::vst1q_u8;
+
+ // initial state
+ #[rustfmt::skip]
+ const INIT: [u32; 8] = [
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+ ];
+
+ // SHA256 round constants
+ #[rustfmt::skip]
+ const K: [u32; 64] = [
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+ ];
+
+ // Precomputed W[i] + K[i] for the 2nd transform (padding block).
+ #[rustfmt::skip]
+ const MIDS: [u32; 64] = [
+ 0xc28a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf374,
+ 0x649b69c1, 0xf0fe4786, 0x0fe1edc6, 0x240cf254,
+ 0x4fe9346f, 0x6cc984be, 0x61b9411e, 0x16f988fa,
+ 0xf2c65152, 0xa88e5a6d, 0xb019fc65, 0xb9d99ec7,
+ 0x9a1231c3, 0xe70eeaa0, 0xfdb1232b, 0xc7353eb0,
+ 0x3069bad5, 0xcb976d5f, 0x5a0f118f, 0xdc1eeefd,
+ 0x0a35b689, 0xde0b7a04, 0x58f4ca9d, 0xe15d5b16,
+ 0x007f3e86, 0x37088980, 0xa507ea32, 0x6fab9537,
+ 0x17406110, 0x0d8cd6f1, 0xcdaa3b6d, 0xc0bbbe37,
+ 0x83613bda, 0xdb48a363, 0x0b02e931, 0x6fd15ca7,
+ 0x521afaca, 0x31338431, 0x6ed41a95, 0x6d437890,
+ 0xc39c91f2, 0x9eccabbd, 0xb5c9a0e6, 0x532fb63c,
+ 0xd2c741c6, 0x07237ea3, 0xa4954b68, 0x4c191d76
+ ];
+
+ // Precomputed values for Transform 3 rounds 9-16.
+ // FINS[0..3]: msg2 + K[8..11]
+ // FINS[4..7]: vsha256su0q_u32(msg2, msg3)
+ // FINS[8..11]: msg2 + K[12..15]
+ #[rustfmt::skip]
+ const FINS: [u32; 12] = [
+ 0x5807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x80000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf274,
+ ];
+
+ // Padding processed in the 3rd transform (byteswapped).
+ const FINAL: [u32; 8] = [0x80000000, 0, 0, 0, 0, 0, 0, 0x100];
+
+ let (mut state0_a, mut state0_b, mut state1_a, mut state1_b);
+ let (abcd_save_a, abcd_save_b, efgh_save_a, efgh_save_b);
+
+ #[rustfmt::skip]
+ let (mut msg0_a, mut msg0_b, mut msg1_a, mut msg1_b, mut msg2_a, mut msg2_b, mut msg3_a, mut msg3_b);
+ let (mut tmp0_a, mut tmp0_b, mut tmp2_a, mut tmp2_b, mut tmp);
+
+ // Load state
+ state0_a = vld1q_u32(INIT.as_ptr().add(0));
+ state0_b = state0_a;
+ state1_a = vld1q_u32(INIT.as_ptr().add(4));
+ state1_b = state1_a;
+
+ // Load message
+ msg0_a = vld1q_u32(input[0].as_ptr().add(0).cast::<u32>());
+ msg1_a = vld1q_u32(input[0].as_ptr().add(16).cast::<u32>());
+ msg2_a = vld1q_u32(input[0].as_ptr().add(32).cast::<u32>());
+ msg3_a = vld1q_u32(input[0].as_ptr().add(48).cast::<u32>());
+ msg0_b = vld1q_u32(input[1].as_ptr().add(0).cast::<u32>());
+ msg1_b = vld1q_u32(input[1].as_ptr().add(16).cast::<u32>());
+ msg2_b = vld1q_u32(input[1].as_ptr().add(32).cast::<u32>());
+ msg3_b = vld1q_u32(input[1].as_ptr().add(48).cast::<u32>());
+
+ // Reverse for little endian
+ msg0_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg0_a)));
+ msg1_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg1_a)));
+ msg2_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg2_a)));
+ msg3_a = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg3_a)));
+ msg0_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg0_b)));
+ msg1_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg1_b)));
+ msg2_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg2_b)));
+ msg3_b = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg3_b)));
+
+ // Transform 1: Rounds 1-4
+ tmp = vld1q_u32(K.as_ptr().add(0));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
+ msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
+ msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
+
+ // Transform 1: Rounds 5-8
+ tmp = vld1q_u32(K.as_ptr().add(4));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
+ msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
+ msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
+
+ // Transform 1: Rounds 9-12
+ tmp = vld1q_u32(K.as_ptr().add(8));
+ tmp0_a = vaddq_u32(msg2_a, tmp);
+ tmp0_b = vaddq_u32(msg2_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
+ msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
+ msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
+
+ // Transform 1: Rounds 13-16
+ tmp = vld1q_u32(K.as_ptr().add(12));
+ tmp0_a = vaddq_u32(msg3_a, tmp);
+ tmp0_b = vaddq_u32(msg3_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
+ msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
+ msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
+
+ // Transform 1: Rounds 17-20
+ tmp = vld1q_u32(K.as_ptr().add(16));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
+ msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
+ msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
+
+ // Transform 1: Rounds 21-24
+ tmp = vld1q_u32(K.as_ptr().add(20));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
+ msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
+ msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
+
+ // Transform 1: Rounds 25-28
+ tmp = vld1q_u32(K.as_ptr().add(24));
+ tmp0_a = vaddq_u32(msg2_a, tmp);
+ tmp0_b = vaddq_u32(msg2_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
+ msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
+ msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
+
+ // Transform 1: Rounds 29-32
+ tmp = vld1q_u32(K.as_ptr().add(28));
+ tmp0_a = vaddq_u32(msg3_a, tmp);
+ tmp0_b = vaddq_u32(msg3_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
+ msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
+ msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
+
+ // Transform 1: Rounds 33-36
+ tmp = vld1q_u32(K.as_ptr().add(32));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
+ msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
+ msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
+
+ // Transform 1: Rounds 37-40
+ tmp = vld1q_u32(K.as_ptr().add(36));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
+ msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
+ msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
+
+ // Transform 1: Rounds 41-44
+ tmp = vld1q_u32(K.as_ptr().add(40));
+ tmp0_a = vaddq_u32(msg2_a, tmp);
+ tmp0_b = vaddq_u32(msg2_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
+ msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
+ msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
+
+ // Transform 1: Rounds 45-48
+ tmp = vld1q_u32(K.as_ptr().add(44));
+ tmp0_a = vaddq_u32(msg3_a, tmp);
+ tmp0_b = vaddq_u32(msg3_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
+ msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
+ msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
+
+ // Transform 1: Rounds 49-52
+ tmp = vld1q_u32(K.as_ptr().add(48));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 1: Rounds 53-56
+ tmp = vld1q_u32(K.as_ptr().add(52));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 1: Rounds 57-60
+ tmp = vld1q_u32(K.as_ptr().add(56));
+ tmp0_a = vaddq_u32(msg2_a, tmp);
+ tmp0_b = vaddq_u32(msg2_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 1: Rounds 61-64
+ tmp = vld1q_u32(K.as_ptr().add(60));
+ tmp0_a = vaddq_u32(msg3_a, tmp);
+ tmp0_b = vaddq_u32(msg3_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 1: Update state
+ tmp = vld1q_u32(&INIT[0]);
+ state0_a = vaddq_u32(state0_a, tmp);
+ state0_b = vaddq_u32(state0_b, tmp);
+ tmp = vld1q_u32(&INIT[4]);
+ state1_a = vaddq_u32(state1_a, tmp);
+ state1_b = vaddq_u32(state1_b, tmp);
+
+ // ------------------ Transform 2 -------------------
+
+ // Transform 2: Save state
+ abcd_save_a = state0_a;
+ abcd_save_b = state0_b;
+ efgh_save_a = state1_a;
+ efgh_save_b = state1_b;
+
+ // Transform 2: Rounds 1-4
+ tmp = vld1q_u32(MIDS.as_ptr().add(0));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 5-8
+ tmp = vld1q_u32(MIDS.as_ptr().add(4));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 9-12
+ tmp = vld1q_u32(MIDS.as_ptr().add(8));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 13-16
+ tmp = vld1q_u32(MIDS.as_ptr().add(12));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 17-20
+ tmp = vld1q_u32(MIDS.as_ptr().add(16));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 21-24
+ tmp = vld1q_u32(MIDS.as_ptr().add(20));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 25-28
+ tmp = vld1q_u32(MIDS.as_ptr().add(24));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 29-32
+ tmp = vld1q_u32(MIDS.as_ptr().add(28));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 33-36
+ tmp = vld1q_u32(MIDS.as_ptr().add(32));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 37-40
+ tmp = vld1q_u32(MIDS.as_ptr().add(36));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 41-44
+ tmp = vld1q_u32(MIDS.as_ptr().add(40));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 45-48
+ tmp = vld1q_u32(MIDS.as_ptr().add(44));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 49-52
+ tmp = vld1q_u32(MIDS.as_ptr().add(48));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 53-56
+ tmp = vld1q_u32(MIDS.as_ptr().add(52));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 57-60
+ tmp = vld1q_u32(MIDS.as_ptr().add(56));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Rounds 61-64
+ tmp = vld1q_u32(MIDS.as_ptr().add(60));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+
+ // Transform 2: Update state
+ state0_a = vaddq_u32(state0_a, abcd_save_a);
+ state0_b = vaddq_u32(state0_b, abcd_save_b);
+ state1_a = vaddq_u32(state1_a, efgh_save_a);
+ state1_b = vaddq_u32(state1_b, efgh_save_b);
+
+ // ------------------ Transform 3 -------------------
+
+ msg0_a = state0_a;
+ msg0_b = state0_b;
+ msg1_a = state1_a;
+ msg1_b = state1_b;
+ msg2_a = vld1q_u32(FINAL.as_ptr().add(0));
+ msg2_b = msg2_a;
+ msg3_a = vld1q_u32(FINAL.as_ptr().add(4));
+ msg3_b = msg3_a;
+
+ // Transform 3: Load state
+ state0_a = vld1q_u32(INIT.as_ptr());
+ state0_b = state0_a;
+ state1_a = vld1q_u32(INIT.as_ptr().add(4));
+ state1_b = state1_a;
+
+ // Transform 3: Rounds 1-4
+ tmp = vld1q_u32(K.as_ptr().add(0));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
+ msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
+ msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
+
+ // Transform 3: Rounds 5-8
+ tmp = vld1q_u32(K.as_ptr().add(4));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
+ msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
+ msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
+
+ // Transform 3: Rounds 9-12
+ tmp = vld1q_u32(FINS.as_ptr().add(0));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg2_a = vld1q_u32(FINS.as_ptr().add(4));
+ msg2_b = msg2_a;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+ msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
+ msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
+
+ // Transform 3: Rounds 13-16
+ tmp = vld1q_u32(FINS.as_ptr().add(8));
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
+ msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp);
+ msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
+ msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
+
+ // Transform 3: Rounds 17-20
+ tmp = vld1q_u32(K.as_ptr().add(16));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
+ msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
+ msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
+
+ // Transform 3: Rounds 21-24
+ tmp = vld1q_u32(K.as_ptr().add(20));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
+ msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
+ msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
+
+ // Transform 3: Rounds 25-28
+ tmp = vld1q_u32(K.as_ptr().add(24));
+ tmp0_a = vaddq_u32(msg2_a, tmp);
+ tmp0_b = vaddq_u32(msg2_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
+ msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
+ msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
+
+ // Transform 3: Rounds 29-32
+ tmp = vld1q_u32(K.as_ptr().add(28));
+ tmp0_a = vaddq_u32(msg3_a, tmp);
+ tmp0_b = vaddq_u32(msg3_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
+ msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
+ msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
+
+ // Transform 3: Rounds 33-36
+ tmp = vld1q_u32(K.as_ptr().add(32));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg0_a = vsha256su0q_u32(msg0_a, msg1_a);
+ msg0_b = vsha256su0q_u32(msg0_b, msg1_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg0_a = vsha256su1q_u32(msg0_a, msg2_a, msg3_a);
+ msg0_b = vsha256su1q_u32(msg0_b, msg2_b, msg3_b);
+
+ // Transform 3: Rounds 37-40
+ tmp = vld1q_u32(K.as_ptr().add(36));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg1_a = vsha256su0q_u32(msg1_a, msg2_a);
+ msg1_b = vsha256su0q_u32(msg1_b, msg2_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg1_a = vsha256su1q_u32(msg1_a, msg3_a, msg0_a);
+ msg1_b = vsha256su1q_u32(msg1_b, msg3_b, msg0_b);
+
+ // Transform 3: Rounds 41-44
+ tmp = vld1q_u32(K.as_ptr().add(40));
+ tmp0_a = vaddq_u32(msg2_a, tmp);
+ tmp0_b = vaddq_u32(msg2_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg2_a = vsha256su0q_u32(msg2_a, msg3_a);
+ msg2_b = vsha256su0q_u32(msg2_b, msg3_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg2_a = vsha256su1q_u32(msg2_a, msg0_a, msg1_a);
+ msg2_b = vsha256su1q_u32(msg2_b, msg0_b, msg1_b);
+
+ // Transform 3: Rounds 45-48
+ tmp = vld1q_u32(K.as_ptr().add(44));
+ tmp0_a = vaddq_u32(msg3_a, tmp);
+ tmp0_b = vaddq_u32(msg3_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ msg3_a = vsha256su0q_u32(msg3_a, msg0_a);
+ msg3_b = vsha256su0q_u32(msg3_b, msg0_b);
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+ msg3_a = vsha256su1q_u32(msg3_a, msg1_a, msg2_a);
+ msg3_b = vsha256su1q_u32(msg3_b, msg1_b, msg2_b);
+
+ // Transform 3: Rounds 49-52
+ tmp = vld1q_u32(K.as_ptr().add(48));
+ tmp0_a = vaddq_u32(msg0_a, tmp);
+ tmp0_b = vaddq_u32(msg0_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 3: Rounds 53-56
+ tmp = vld1q_u32(K.as_ptr().add(52));
+ tmp0_a = vaddq_u32(msg1_a, tmp);
+ tmp0_b = vaddq_u32(msg1_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 3: Rounds 57-60
+ tmp = vld1q_u32(K.as_ptr().add(56));
+ tmp0_a = vaddq_u32(msg2_a, tmp);
+ tmp0_b = vaddq_u32(msg2_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 3: Rounds 61-64
+ tmp = vld1q_u32(K.as_ptr().add(60));
+ tmp0_a = vaddq_u32(msg3_a, tmp);
+ tmp0_b = vaddq_u32(msg3_b, tmp);
+ tmp2_a = state0_a;
+ tmp2_b = state0_b;
+ state0_a = vsha256hq_u32(state0_a, state1_a, tmp0_a);
+ state0_b = vsha256hq_u32(state0_b, state1_b, tmp0_b);
+ state1_a = vsha256h2q_u32(state1_a, tmp2_a, tmp0_a);
+ state1_b = vsha256h2q_u32(state1_b, tmp2_b, tmp0_b);
+
+ // Transform 3: Update state
+ tmp = vld1q_u32(INIT.as_ptr().add(0));
+ state0_a = vaddq_u32(state0_a, tmp);
+ state0_b = vaddq_u32(state0_b, tmp);
+ tmp = vld1q_u32(INIT.as_ptr().add(4));
+ state1_a = vaddq_u32(state1_a, tmp);
+ state1_b = vaddq_u32(state1_b, tmp);
+
+ // Store result
+ vst1q_u8(output[0].as_mut_ptr().add(0), vrev32q_u8(vreinterpretq_u8_u32(state0_a)));
+ vst1q_u8(output[0].as_mut_ptr().add(16), vrev32q_u8(vreinterpretq_u8_u32(state1_a)));
+ vst1q_u8(output[1].as_mut_ptr().add(0), vrev32q_u8(vreinterpretq_u8_u32(state0_b)));
+ vst1q_u8(output[1].as_mut_ptr().add(16), vrev32q_u8(vreinterpretq_u8_u32(state1_b)));
+}
+
diff --git a/hashes/src/sha256/crypto/mod.rs b/hashes/src/sha256/crypto/mod.rs
new file mode 100644
index 00000000..83e0b115
--- /dev/null
+++ b/hashes/src/sha256/crypto/mod.rs
@@ -0,0 +1,476 @@
+// SPDX-License-Identifier: CC0-1.0
+
+#![allow(clippy::unreadable_literal)]
+#![allow(clippy::cast_ptr_alignment)]
+#![allow(clippy::too_many_lines)]
+#![allow(clippy::many_single_char_names)]
+
+
+#[cfg(target_arch = "aarch64")]
+#[cfg(any(feature = "cpufeatures", feature = "std"))]
+mod arm_sha2;
+
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[cfg(any(feature = "cpufeatures", feature = "std"))]
+mod x86_shani;
+
+use internals::slice::SliceExt;
+
+use super::{HashEngine, Midstate, BLOCK_SIZE};
+use crate::sha256d;
+
+#[cfg(feature = "cpufeatures")]
+#[cfg(target_arch = "aarch64")]
+// cpufeatures crate internally uses `u8::max_value()` which will be deprecated.
+// See: https://docs.rs/cpufeatures/0.2.17/src/cpufeatures/lib.rs.html#161
+#[allow(deprecated_in_future)]
+mod cpuid_sha256_aarch64 {
+ cpufeatures::new!(inner, "sha2");
+ pub fn get() -> bool { inner::get() }
+}
+#[cfg(feature = "cpufeatures")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+// cpufeatures crate internally uses `u8::max_value()` which will be deprecated.
+// See: https://docs.rs/cpufeatures/0.2.17/src/cpufeatures/lib.rs.html#161
+#[allow(deprecated_in_future)]
+mod cpuid_sha256_x86 {
+ cpufeatures::new!(inner, "sha", "sse2", "ssse3", "sse4.1");
+ pub fn get() -> bool { inner::get() }
+}
+
+#[allow(non_snake_case)]
+const fn Ch(x: u32, y: u32, z: u32) -> u32 { z ^ (x & (y ^ z)) }
+#[allow(non_snake_case)]
+const fn Maj(x: u32, y: u32, z: u32) -> u32 { (x & y) | (z & (x | y)) }
+#[allow(non_snake_case)]
+const fn Sigma0(x: u32) -> u32 { x.rotate_left(30) ^ x.rotate_left(19) ^ x.rotate_left(10) }
+#[allow(non_snake_case)]
+const fn Sigma1(x: u32) -> u32 { x.rotate_left(26) ^ x.rotate_left(21) ^ x.rotate_left(7) }
+const fn sigma0(x: u32) -> u32 { x.rotate_left(25) ^ x.rotate_left(14) ^ (x >> 3) }
+const fn sigma1(x: u32) -> u32 { x.rotate_left(15) ^ x.rotate_left(13) ^ (x >> 10) }
+
+#[cfg(feature = "small-hash")]
+#[macro_use]
+mod small_hash {
+ use super::{sigma0, sigma1, Ch, Maj, Sigma0, Sigma1};
+
+ #[rustfmt::skip]
+ #[allow(clippy::too_many_arguments)]
+ pub(super) const fn round(a: u32, b: u32, c: u32, d: u32, e: u32,
+ f: u32, g: u32, h: u32, k: u32, w: u32) -> (u32, u32) {
+ let t1 =
+ h.wrapping_add(Sigma1(e)).wrapping_add(Ch(e, f, g)).wrapping_add(k).wrapping_add(w);
+ let t2 = Sigma0(a).wrapping_add(Maj(a, b, c));
+ (d.wrapping_add(t1), t1.wrapping_add(t2))
+ }
+ #[rustfmt::skip]
+ #[allow(clippy::too_many_arguments)]
+ pub(super) const fn later_round(a: u32, b: u32, c: u32, d: u32, e: u32,
+ f: u32, g: u32, h: u32, k: u32, w: u32,
+ w1: u32, w2: u32, w3: u32,
+ ) -> (u32, u32, u32) {
+ let w = w.wrapping_add(sigma1(w1)).wrapping_add(w2).wrapping_add(sigma0(w3));
+ let (d, h) = round(a, b, c, d, e, f, g, h, k, w);
+ (d, h, w)
+ }
+
+ macro_rules! round(
+ // first round
+ ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => (
+ let updates = small_hash::round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w);
+ $d = updates.0;
+ $h = updates.1;
+ );
+ // later rounds we reassign $w before doing the first-round computation
+ ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => (
+ let updates = small_hash::later_round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w, $w1, $w2, $w3);
+ $d = updates.0;
+ $h = updates.1;
+ $w = updates.2;
+ )
+ );
+}
+
+#[cfg(not(feature = "small-hash"))]
+#[macro_use]
+mod fast_hash {
+ macro_rules! round(
+ // first round
+ ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => (
+ let t1 = $h.wrapping_add(Sigma1($e)).wrapping_add(Ch($e, $f, $g)).wrapping_add($k).wrapping_add($w);
+ let t2 = Sigma0($a).wrapping_add(Maj($a, $b, $c));
+ $d = $d.wrapping_add(t1);
+ $h = t1.wrapping_add(t2);
+ );
+ // later rounds we reassign $w before doing the first-round computation
+ ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => (
+ $w = $w.wrapping_add(sigma1($w1)).wrapping_add($w2).wrapping_add(sigma0($w3));
+ round!($a, $b, $c, $d, $e, $f, $g, $h, $k, $w);
+ )
+ );
+}
+
+impl Midstate {
+ #[allow(clippy::identity_op)] // more readable
+ const fn read_u32(bytes: &[u8], index: usize) -> u32 {
+ ((bytes[index + 0] as u32) << 24)
+ | ((bytes[index + 1] as u32) << 16)
+ | ((bytes[index + 2] as u32) << 8)
+ | ((bytes[index + 3] as u32) << 0)
+ }
+
+ const fn copy_w(bytes: &[u8], index: usize) -> [u32; 16] {
+ let mut w = [0u32; 16];
+ let mut i = 0;
+ while i < 16 {
+ w[i] = Self::read_u32(bytes, index + i * 4);
+ i += 1;
+ }
+ w
+ }
+
+ pub(super) const fn compute_midstate_unoptimized(bytes: &[u8], finalize: bool) -> Self {
+ let mut state = [
+ 0x6a09e667u32,
+ 0xbb67ae85,
+ 0x3c6ef372,
+ 0xa54ff53a,
+ 0x510e527f,
+ 0x9b05688c,
+ 0x1f83d9ab,
+ 0x5be0cd19,
+ ];
+
+ let num_chunks = (bytes.len() + 9).div_ceil(64);
+ let mut chunk = 0;
+ #[allow(clippy::precedence)]
+ while chunk < num_chunks {
+ if !finalize && chunk + 1 == num_chunks {
+ break;
+ }
+ let mut w = if chunk * 64 + 64 <= bytes.len() {
+ Self::copy_w(bytes, chunk * 64)
+ } else {
+ let mut buf = [0; 64];
+ let mut i = 0;
+ let offset = chunk * 64;
+ while offset + i < bytes.len() {
+ buf[i] = bytes[offset + i];
+ i += 1;
+ }
+ if (bytes.len() % 64 <= 64 - 9) || (chunk + 2 == num_chunks) {
+ buf[i] = 0x80;
+ }
+ #[allow(clippy::identity_op)] // more readable
+ #[allow(clippy::erasing_op)]
+ if chunk + 1 == num_chunks {
+ let bit_len = bytes.len() as u64 * 8;
+ buf[64 - 8] = ((bit_len >> 8 * 7) & 0xFF) as u8;
+ buf[64 - 7] = ((bit_len >> 8 * 6) & 0xFF) as u8;
+ buf[64 - 6] = ((bit_len >> 8 * 5) & 0xFF) as u8;
+ buf[64 - 5] = ((bit_len >> 8 * 4) & 0xFF) as u8;
+ buf[64 - 4] = ((bit_len >> 8 * 3) & 0xFF) as u8;
+ buf[64 - 3] = ((bit_len >> 8 * 2) & 0xFF) as u8;
+ buf[64 - 2] = ((bit_len >> 8 * 1) & 0xFF) as u8;
+ buf[64 - 1] = ((bit_len >> 8 * 0) & 0xFF) as u8;
+ }
+ Self::copy_w(&buf, 0)
+ };
+ chunk += 1;
+
+ let mut a = state[0];
+ let mut b = state[1];
+ let mut c = state[2];
+ let mut d = state[3];
+ let mut e = state[4];
+ let mut f = state[5];
+ let mut g = state[6];
+ let mut h = state[7];
+
+ round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]);
+ round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]);
+ round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]);
+ round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]);
+ round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]);
+ round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]);
+ round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]);
+ round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]);
+ round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]);
+ round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]);
+ round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]);
+ round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]);
+ round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]);
+ round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]);
+ round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]);
+ round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]);
+
+ round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]);
+ round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]);
+ round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]);
+ round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]);
+ round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]);
+ round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]);
+ round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]);
+ round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]);
+ round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]);
+ round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]);
+ round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]);
+ round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]);
+ round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]);
+ round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]);
+ round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]);
+ round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]);
+
+ round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]);
+ round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]);
+ round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]);
+ round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]);
+ round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]);
+ round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]);
+ round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]);
+ round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]);
+ round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]);
+ round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]);
+ round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]);
+ round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]);
+ round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]);
+ round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]);
+ round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]);
+ round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]);
+
+ round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]);
+ round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]);
+ round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]);
+ round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]);
+ round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]);
+ round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]);
+ round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]);
+ round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]);
+ round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]);
+ round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]);
+ round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]);
+ round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]);
+ round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]);
+ round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]);
+ round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]);
+ round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]);
+
+ state[0] = state[0].wrapping_add(a);
+ state[1] = state[1].wrapping_add(b);
+ state[2] = state[2].wrapping_add(c);
+ state[3] = state[3].wrapping_add(d);
+ state[4] = state[4].wrapping_add(e);
+ state[5] = state[5].wrapping_add(f);
+ state[6] = state[6].wrapping_add(g);
+ state[7] = state[7].wrapping_add(h);
+ }
+ let mut output = [0u8; 32];
+ let mut i = 0;
+ #[allow(clippy::identity_op)] // more readable
+ while i < 8 {
+ output[i * 4 + 0] = (state[i + 0] >> 24) as u8;
+ output[i * 4 + 1] = (state[i + 0] >> 16) as u8;
+ output[i * 4 + 2] = (state[i + 0] >> 8) as u8;
+ output[i * 4 + 3] = (state[i + 0] >> 0) as u8;
+ i += 1;
+ }
+ Self { bytes: output, bytes_hashed: bytes.len() as u64 }
+ }
+}
+
+impl HashEngine {
+ pub(super) fn process_blocks(state: &mut [u32; 8], blocks: &[u8]) {
+ #[cfg(feature = "std")]
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ if std::is_x86_feature_detected!("sse4.1")
+ && std::is_x86_feature_detected!("sha")
+ && std::is_x86_feature_detected!("sse2")
+ && std::is_x86_feature_detected!("ssse3")
+ {
+ for block in blocks.chunks_exact(BLOCK_SIZE) {
+ unsafe { x86_shani::process_block(state, block) };
+ }
+ return;
+ }
+ }
+
+ #[cfg(feature = "cpufeatures")]
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ if cpuid_sha256_x86::get() {
+ for block in blocks.chunks_exact(BLOCK_SIZE) {
+ unsafe { x86_shani::process_block(state, block) };
+ }
+ return;
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[cfg(target_arch = "aarch64")]
+ {
+ if std::arch::is_aarch64_feature_detected!("sha2") {
+ for block in blocks.chunks_exact(BLOCK_SIZE) {
+ unsafe { arm_sha2::process_block(state, block) };
+ }
+ return;
+ }
+ }
+
+ #[cfg(feature = "cpufeatures")]
+ #[cfg(target_arch = "aarch64")]
+ {
+ if cpuid_sha256_aarch64::get() {
+ for block in blocks.chunks_exact(BLOCK_SIZE) {
+ unsafe { arm_sha2::process_block(state, block) };
+ }
+ return;
+ }
+ }
+
+ // fallback implementation without using any intrinsics
+ Self::software_process_block(state, blocks);
+ }
+
+ pub(crate) fn sha256d_64(outputs: &mut [[u8; 32]], inputs: &[[u8; 64]]) {
+ assert_eq!(outputs.len(), inputs.len());
+ let mut i = 0;
+ let count = inputs.len();
+
+ // TODO: 8-way AVX2
+ // TODO: 4-way SSE4.1
+ // TODO: 2-way x86 SHA-NI
+
+ // 2-way ARM SHA2
+ #[cfg(feature = "std")]
+ #[cfg(target_arch = "aarch64")]
+ {
+ if std::arch::is_aarch64_feature_detected!("sha2") {
+ while count - i >= 2 {
+ let out = <&mut [[u8; 32]; 2]>::try_from(&mut outputs[i..i + 2]).unwrap();
+ let inp = <&[[u8; 64]; 2]>::try_from(&inputs[i..i + 2]).unwrap();
+ unsafe { arm_sha2::sha256d_64_2way(out, inp) };
+ i += 2;
+ }
+ }
+ }
+
+ #[cfg(feature = "cpufeatures")]
+ #[cfg(target_arch = "aarch64")]
+ {
+ if cpuid_sha256_aarch64::get() {
+ while count - i >= 2 {
+ let out = <&mut [[u8; 32]; 2]>::try_from(&mut outputs[i..i + 2]).unwrap();
+ let inp = <&[[u8; 64]; 2]>::try_from(&inputs[i..i + 2]).unwrap();
+ unsafe { arm_sha2::sha256d_64_2way(out, inp) };
+ i += 2;
+ }
+ }
+ }
+
+ // fallback
+ while i < count {
+ outputs[i] = sha256d::hash(&inputs[i]).to_byte_array();
+ i += 1;
+ }
+ }
+
+ // Algorithm copied from libsecp256k1
+ fn software_process_block(state: &mut [u32; 8], blocks: &[u8]) {
+ debug_assert!(!blocks.is_empty() && blocks.len() % BLOCK_SIZE == 0);
+
+ for block in blocks.chunks_exact(BLOCK_SIZE) {
+ let mut w = [0u32; 16];
+ for (w_val, buff_bytes) in w.iter_mut().zip(block.bitcoin_as_chunks().0) {
+ *w_val = u32::from_be_bytes(*buff_bytes);
+ }
+
+ let mut a = state[0];
+ let mut b = state[1];
+ let mut c = state[2];
+ let mut d = state[3];
+ let mut e = state[4];
+ let mut f = state[5];
+ let mut g = state[6];
+ let mut h = state[7];
+
+ round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]);
+ round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]);
+ round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]);
+ round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]);
+ round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]);
+ round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]);
+ round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]);
+ round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]);
+ round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]);
+ round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]);
+ round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]);
+ round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]);
+ round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]);
+ round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]);
+ round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]);
+ round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]);
+
+ round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]);
+ round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]);
+ round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]);
+ round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]);
+ round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]);
+ round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]);
+ round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]);
+ round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]);
+ round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]);
+ round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]);
+ round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]);
+ round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]);
+ round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]);
+ round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]);
+ round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]);
+ round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]);
+
+ round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]);
+ round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]);
+ round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]);
+ round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]);
+ round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]);
+ round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]);
+ round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]);
+ round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]);
+ round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]);
+ round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]);
+ round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]);
+ round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]);
+ round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]);
+ round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]);
+ round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]);
+ round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]);
+
+ round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]);
+ round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]);
+ round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]);
+ round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]);
+ round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]);
+ round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]);
+ round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]);
+ round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]);
+ round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]);
+ round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]);
+ round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]);
+ round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]);
+ round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]);
+ round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]);
+ round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]);
+ round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]);
+ let _ = w[15]; // silence "unnecessary assignment" lint in macro
+
+ state[0] = state[0].wrapping_add(a);
+ state[1] = state[1].wrapping_add(b);
+ state[2] = state[2].wrapping_add(c);
+ state[3] = state[3].wrapping_add(d);
+ state[4] = state[4].wrapping_add(e);
+ state[5] = state[5].wrapping_add(f);
+ state[6] = state[6].wrapping_add(g);
+ state[7] = state[7].wrapping_add(h);
+ }
+ }
+}
diff --git a/hashes/src/sha256/crypto/x86_shani.rs b/hashes/src/sha256/crypto/x86_shani.rs
new file mode 100644
index 00000000..87e0d250
--- /dev/null
+++ b/hashes/src/sha256/crypto/x86_shani.rs
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: CC0-1.0
+
+//! x86 SHA-NI intrinsics for sha256
+
+#![allow(clippy::cast_ptr_alignment)]
+
+#[cfg(target_arch = "x86")]
+use core::arch::x86::{
+ __m128i, _mm_add_epi32, _mm_alignr_epi8, _mm_blend_epi16, _mm_loadu_si128, _mm_set_epi64x,
+ _mm_sha256msg1_epu32, _mm_sha256msg2_epu32, _mm_sha256rnds2_epu32, _mm_shuffle_epi32,
+ _mm_shuffle_epi8, _mm_storeu_si128,
+};
+#[cfg(target_arch = "x86_64")]
+use core::arch::x86_64::{
+ __m128i, _mm_add_epi32, _mm_alignr_epi8, _mm_blend_epi16, _mm_loadu_si128, _mm_set_epi64x,
+ _mm_sha256msg1_epu32, _mm_sha256msg2_epu32, _mm_sha256rnds2_epu32, _mm_shuffle_epi32,
+ _mm_shuffle_epi8, _mm_storeu_si128,
+};
+
+/// Processes a single sha256 block using x86 SHA-NI intrinsics.
+#[target_feature(enable = "sha,sse2,ssse3,sse4.1")]
+pub(super) unsafe fn process_block(state: &mut [u32; 8], block: &[u8]) {
+ // Code translated and based on from
+ // https://github.com/noloader/SHA-Intrinsics/blob/4899efc81d1af159c1fd955936c673139f35aea9/sha256-x86.c
+
+ /* sha256-x86.c - Intel SHA extensions using C intrinsics */
+ /* Written and place in public domain by Jeffrey Walton */
+ /* Based on code from Intel, and by Sean Gulley for */
+ /* the miTLS project. */
+
+ // Variable names are also kept the same as in the original C code for easier comparison.
+ let (mut state0, mut state1);
+ let (mut msg, mut tmp);
+
+ let (mut msg0, mut msg1, mut msg2, mut msg3);
+
+ let (abef_save, cdgh_save);
+
+ #[allow(non_snake_case)]
+ let MASK: __m128i =
+ _mm_set_epi64x(0x0c0d_0e0f_0809_0a0bu64 as i64, 0x0405_0607_0001_0203u64 as i64);
+
+ let block_offset = 0;
+
+ // Load initial values
+ // CAST SAFETY: loadu_si128 documentation states that mem_addr does not
+ // need to be aligned on any particular boundary.
+ tmp = _mm_loadu_si128(state.as_ptr().add(0).cast::<__m128i>());
+ state1 = _mm_loadu_si128(state.as_ptr().add(4).cast::<__m128i>());
+
+ tmp = _mm_shuffle_epi32(tmp, 0xB1); // CDAB
+ state1 = _mm_shuffle_epi32(state1, 0x1B); // EFGH
+ state0 = _mm_alignr_epi8(tmp, state1, 8); // ABEF
+ state1 = _mm_blend_epi16(state1, tmp, 0xF0); // CDGH
+
+ // Process a single block
+ {
+ // Save current state
+ abef_save = state0;
+ cdgh_save = state1;
+
+ // Rounds 0-3
+ msg = _mm_loadu_si128(block.as_ptr().add(block_offset).cast::<__m128i>());
+ msg0 = _mm_shuffle_epi8(msg, MASK);
+ msg = _mm_add_epi32(
+ msg0,
+ _mm_set_epi64x(0xE9B5DBA5B5C0FBCFu64 as i64, 0x71374491428A2F98u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+
+ // Rounds 4-7
+ msg1 = _mm_loadu_si128(block.as_ptr().add(block_offset + 16).cast::<__m128i>());
+ msg1 = _mm_shuffle_epi8(msg1, MASK);
+ msg = _mm_add_epi32(
+ msg1,
+ _mm_set_epi64x(0xAB1C5ED5923F82A4u64 as i64, 0x59F111F13956C25Bu64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg0 = _mm_sha256msg1_epu32(msg0, msg1);
+
+ // Rounds 8-11
+ msg2 = _mm_loadu_si128(block.as_ptr().add(block_offset + 32).cast::<__m128i>());
+ msg2 = _mm_shuffle_epi8(msg2, MASK);
+ msg = _mm_add_epi32(
+ msg2,
+ _mm_set_epi64x(0x550C7DC3243185BEu64 as i64, 0x12835B01D807AA98u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg1 = _mm_sha256msg1_epu32(msg1, msg2);
+
+ // Rounds 12-15
+ msg3 = _mm_loadu_si128(block.as_ptr().add(block_offset + 48).cast::<__m128i>());
+ msg3 = _mm_shuffle_epi8(msg3, MASK);
+ msg = _mm_add_epi32(
+ msg3,
+ _mm_set_epi64x(0xC19BF1749BDC06A7u64 as i64, 0x80DEB1FE72BE5D74u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg3, msg2, 4);
+ msg0 = _mm_add_epi32(msg0, tmp);
+ msg0 = _mm_sha256msg2_epu32(msg0, msg3);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg2 = _mm_sha256msg1_epu32(msg2, msg3);
+
+ // Rounds 16-19
+ msg = _mm_add_epi32(
+ msg0,
+ _mm_set_epi64x(0x240CA1CC0FC19DC6u64 as i64, 0xEFBE4786E49B69C1u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg0, msg3, 4);
+ msg1 = _mm_add_epi32(msg1, tmp);
+ msg1 = _mm_sha256msg2_epu32(msg1, msg0);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg3 = _mm_sha256msg1_epu32(msg3, msg0);
+
+ // Rounds 20-23
+ msg = _mm_add_epi32(
+ msg1,
+ _mm_set_epi64x(0x76F988DA5CB0A9DCu64 as i64, 0x4A7484AA2DE92C6Fu64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg1, msg0, 4);
+ msg2 = _mm_add_epi32(msg2, tmp);
+ msg2 = _mm_sha256msg2_epu32(msg2, msg1);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg0 = _mm_sha256msg1_epu32(msg0, msg1);
+
+ // Rounds 24-27
+ msg = _mm_add_epi32(
+ msg2,
+ _mm_set_epi64x(0xBF597FC7B00327C8u64 as i64, 0xA831C66D983E5152u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg2, msg1, 4);
+ msg3 = _mm_add_epi32(msg3, tmp);
+ msg3 = _mm_sha256msg2_epu32(msg3, msg2);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg1 = _mm_sha256msg1_epu32(msg1, msg2);
+
+ // Rounds 28-31
+ msg = _mm_add_epi32(
+ msg3,
+ _mm_set_epi64x(0x1429296706CA6351u64 as i64, 0xD5A79147C6E00BF3u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg3, msg2, 4);
+ msg0 = _mm_add_epi32(msg0, tmp);
+ msg0 = _mm_sha256msg2_epu32(msg0, msg3);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg2 = _mm_sha256msg1_epu32(msg2, msg3);
+
+ // Rounds 32-35
+ msg = _mm_add_epi32(
+ msg0,
+ _mm_set_epi64x(0x53380D134D2C6DFCu64 as i64, 0x2E1B213827B70A85u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg0, msg3, 4);
+ msg1 = _mm_add_epi32(msg1, tmp);
+ msg1 = _mm_sha256msg2_epu32(msg1, msg0);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg3 = _mm_sha256msg1_epu32(msg3, msg0);
+
+ // Rounds 36-39
+ msg = _mm_add_epi32(
+ msg1,
+ _mm_set_epi64x(0x92722C8581C2C92Eu64 as i64, 0x766A0ABB650A7354u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg1, msg0, 4);
+ msg2 = _mm_add_epi32(msg2, tmp);
+ msg2 = _mm_sha256msg2_epu32(msg2, msg1);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg0 = _mm_sha256msg1_epu32(msg0, msg1);
+
+ // Rounds 40-43
+ msg = _mm_add_epi32(
+ msg2,
+ _mm_set_epi64x(0xC76C51A3C24B8B70u64 as i64, 0xA81A664BA2BFE8A1u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg2, msg1, 4);
+ msg3 = _mm_add_epi32(msg3, tmp);
+ msg3 = _mm_sha256msg2_epu32(msg3, msg2);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg1 = _mm_sha256msg1_epu32(msg1, msg2);
+
+ // Rounds 44-47
+ msg = _mm_add_epi32(
+ msg3,
+ _mm_set_epi64x(0x106AA070F40E3585u64 as i64, 0xD6990624D192E819u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg3, msg2, 4);
+ msg0 = _mm_add_epi32(msg0, tmp);
+ msg0 = _mm_sha256msg2_epu32(msg0, msg3);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg2 = _mm_sha256msg1_epu32(msg2, msg3);
+
+ // Rounds 48-51
+ msg = _mm_add_epi32(
+ msg0,
+ _mm_set_epi64x(0x34B0BCB52748774Cu64 as i64, 0x1E376C0819A4C116u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg0, msg3, 4);
+ msg1 = _mm_add_epi32(msg1, tmp);
+ msg1 = _mm_sha256msg2_epu32(msg1, msg0);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+ msg3 = _mm_sha256msg1_epu32(msg3, msg0);
+
+ // Rounds 52-55
+ msg = _mm_add_epi32(
+ msg1,
+ _mm_set_epi64x(0x682E6FF35B9CCA4Fu64 as i64, 0x4ED8AA4A391C0CB3u64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg1, msg0, 4);
+ msg2 = _mm_add_epi32(msg2, tmp);
+ msg2 = _mm_sha256msg2_epu32(msg2, msg1);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+
+ // Rounds 56-59
+ msg = _mm_add_epi32(
+ msg2,
+ _mm_set_epi64x(0x8CC7020884C87814u64 as i64, 0x78A5636F748F82EEu64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ tmp = _mm_alignr_epi8(msg2, msg1, 4);
+ msg3 = _mm_add_epi32(msg3, tmp);
+ msg3 = _mm_sha256msg2_epu32(msg3, msg2);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+
+ // Rounds 60-63
+ msg = _mm_add_epi32(
+ msg3,
+ _mm_set_epi64x(0xC67178F2BEF9A3F7u64 as i64, 0xA4506CEB90BEFFFAu64 as i64),
+ );
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ msg = _mm_shuffle_epi32(msg, 0x0E);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, msg);
+
+ // Combine state
+ state0 = _mm_add_epi32(state0, abef_save);
+ state1 = _mm_add_epi32(state1, cdgh_save);
+ }
+
+ tmp = _mm_shuffle_epi32(state0, 0x1B); // FEBA
+ state1 = _mm_shuffle_epi32(state1, 0xB1); // DCHG
+ state0 = _mm_blend_epi16(tmp, state1, 0xF0); // DCBA
+ state1 = _mm_alignr_epi8(state1, tmp, 8); // ABEF
+
+ // Save state
+ // CAST SAFETY: storeu_si128 documentation states that mem_addr does not
+ // need to be aligned on any particular boundary.
+ _mm_storeu_si128(state.as_mut_ptr().add(0).cast::<__m128i>(), state0);
+ _mm_storeu_si128(state.as_mut_ptr().add(4).cast::<__m128i>(), state1);
+}
+
Why this scored 15/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.