diff --git a/keccak/CHANGELOG.md b/keccak/CHANGELOG.md index b0e1721..c5d7645 100644 --- a/keccak/CHANGELOG.md +++ b/keccak/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### 0.2.2 (UNRELEASED) +### Changed +- Improved performance of software backend on some targets ([#129]) + +[#129]: https://github.com/RustCrypto/sponges/pull/129 + ## 0.2.1 (2026-08-05) ### Fixed - Warning on softfloat AArch64 targets by not enabling `aarch64_sha3` backend on them ([#126]) diff --git a/keccak/src/backends/simd.rs b/keccak/src/backends/simd.rs index 23ec35d..c9ee7da 100644 --- a/keccak/src/backends/simd.rs +++ b/keccak/src/backends/simd.rs @@ -12,11 +12,18 @@ use core::simd::u64x4 as u64xN; use core::simd::u64x8 as u64xN; impl LaneSize for u64xN { - const KECCAK_F_ROUND_COUNT: usize = crate::consts::F1600_ROUNDS; + const RC: &[Self] = &{ + use crate::consts::{F1600_ROUNDS, RC}; - fn truncate_rc(rc: u64) -> Self { - Self::splat(rc) - } + let mut res = [Self::splat(0); F1600_ROUNDS]; + let mut i = 0; + #[allow(clippy::cast_possible_truncation, trivial_numeric_casts)] + while i < res.len() { + res[i] = Self::splat(RC[i]); + i += 1; + } + res + }; fn rotate_left(self, n: u32) -> Self { self << Self::splat(n.into()) | self >> Self::splat((64 - n).into()) diff --git a/keccak/src/backends/soft.rs b/keccak/src/backends/soft.rs index f3ad673..7c0c906 100644 --- a/keccak/src/backends/soft.rs +++ b/keccak/src/backends/soft.rs @@ -15,12 +15,10 @@ pub trait LaneSize: + BitXorAssign + BitXor + Not + + 'static { - /// Number of rounds of the Keccak-f permutation. - const KECCAK_F_ROUND_COUNT: usize; - - /// Truncate function. - fn truncate_rc(rc: u64) -> Self; + /// Round constants + const RC: &[Self]; /// Rotate left function. #[must_use] @@ -30,12 +28,16 @@ pub trait LaneSize: macro_rules! impl_lanesize { ($type:ty, $round:expr) => { impl LaneSize for $type { - const KECCAK_F_ROUND_COUNT: usize = $round; - - #[allow(clippy::cast_possible_truncation, trivial_numeric_casts)] - fn truncate_rc(rc: u64) -> Self { - rc as Self - } + const RC: &[Self] = &{ + let mut res = [0; $round]; + let mut i = 0; + #[allow(clippy::cast_possible_truncation, trivial_numeric_casts)] + while i < res.len() { + res[i] = RC[i] as Self; + i += 1; + } + res + }; fn rotate_left(self, n: u32) -> Self { self.rotate_left(n) @@ -53,6 +55,7 @@ impl_lanesize!(u64, F1600_ROUNDS); macro_rules! unroll5 { ($var: ident, $body: block) => { #[cfg(not(keccak_backend_soft = "compact"))] + #[allow(non_upper_case_globals)] { { const $var: usize = 0; $body; } { const $var: usize = 1; $body; } @@ -71,6 +74,7 @@ macro_rules! unroll5 { macro_rules! unroll24 { ($var: ident, $body: block) => { #[cfg(not(keccak_backend_soft = "compact"))] + #[allow(non_upper_case_globals)] { { const $var: usize = 0; $body; } { const $var: usize = 1; $body; } @@ -108,14 +112,14 @@ macro_rules! unroll24 { /// /// # Panics /// If the `ROUNDS` is greater than `L::KECCAK_F_ROUND_COUNT`. -#[allow(non_upper_case_globals, unused_assignments)] pub(crate) fn keccak_p(state: &mut [L; PLEN]) { + const { assert!(ROUNDS <= L::RC.len()) }; + // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=25 // "the rounds of KECCAK-p[b, nr] match the last rounds of KECCAK-f[b]" - let round_consts = RC[..L::KECCAK_F_ROUND_COUNT] + let round_consts = L::RC .last_chunk::() - .expect("Number of rounds greater than `KECCAK_F_ROUND_COUNT` is not supported!") - .map(L::truncate_rc); + .expect("Number of rounds is checked above"); // Not unrolling this loop results in a much smaller function, plus // it positively influences performance due to the smaller load on I-cache @@ -142,7 +146,10 @@ pub(crate) fn keccak_p(state: &mut [L; PLEN]) unroll24!(x, { array[0] = state[PI[x]]; state[PI[x]] = last.rotate_left(RHO[x]); - last = array[0]; + #[allow(unused_assignments)] + { + last = array[0]; + } }); // Chi @@ -159,7 +166,7 @@ pub(crate) fn keccak_p(state: &mut [L; PLEN]) }); // Iota - state[0] ^= rc; + state[0] ^= *rc; } }