1#![no_std]
4#![cfg_attr(
5 all(
6 feature = "nightly-features",
7 target_arch = "x86_64",
8 target_feature = "avx512f"
9 ),
10 feature(stdarch_x86_avx512)
11)]
12
13use p3_symmetric::{CryptographicHasher, CryptographicPermutation, Permutation};
14use tiny_keccak::{keccakf, Hasher, Keccak};
15
16#[cfg(all(
17 feature = "nightly-features",
18 target_arch = "x86_64",
19 target_feature = "avx512f"
20))]
21pub mod avx512;
22#[cfg(all(
23 feature = "nightly-features",
24 target_arch = "x86_64",
25 target_feature = "avx512f"
26))]
27pub use avx512::*;
28
29#[cfg(all(
30 target_arch = "x86_64",
31 target_feature = "avx2",
32 not(all(feature = "nightly-features", target_feature = "avx512f"))
33))]
34pub mod avx2;
35#[cfg(all(
36 target_arch = "x86_64",
37 target_feature = "avx2",
38 not(all(feature = "nightly-features", target_feature = "avx512f"))
39))]
40pub use avx2::*;
41
42#[cfg(all(target_arch = "x86_64", not(target_feature = "avx2")))]
43pub mod sse2;
44#[cfg(all(target_arch = "x86_64", not(target_feature = "avx2")))]
45pub use sse2::*;
46
47#[cfg(all(
48 target_arch = "aarch64",
49 target_feature = "neon",
50 target_feature = "sha3"
51))]
52pub mod neon;
53#[cfg(all(
54 target_arch = "aarch64",
55 target_feature = "neon",
56 target_feature = "sha3"
57))]
58pub use neon::*;
59
60#[cfg(not(any(
61 all(
62 target_arch = "aarch64",
63 target_feature = "neon",
64 target_feature = "sha3",
65 ),
66 target_arch = "x86_64",
67)))]
68mod fallback;
69#[cfg(not(any(
70 all(
71 target_arch = "aarch64",
72 target_feature = "neon",
73 target_feature = "sha3",
74 ),
75 target_arch = "x86_64",
76)))]
77pub use fallback::*;
78
79#[derive(Copy, Clone, Debug)]
81pub struct KeccakF;
82
83impl Permutation<[u64; 25]> for KeccakF {
84 fn permute_mut(&self, input: &mut [u64; 25]) {
85 keccakf(input);
86 }
87}
88
89impl CryptographicPermutation<[u64; 25]> for KeccakF {}
90
91impl Permutation<[u8; 200]> for KeccakF {
92 fn permute(&self, input_u8s: [u8; 200]) -> [u8; 200] {
93 let mut state_u64s: [u64; 25] = core::array::from_fn(|i| {
94 u64::from_le_bytes(input_u8s[i * 8..][..8].try_into().unwrap())
95 });
96
97 keccakf(&mut state_u64s);
98
99 core::array::from_fn(|i| {
100 let u64_limb = state_u64s[i / 8];
101 u64_limb.to_le_bytes()[i % 8]
102 })
103 }
104
105 fn permute_mut(&self, input: &mut [u8; 200]) {
106 *input = self.permute(*input);
107 }
108}
109
110impl CryptographicPermutation<[u8; 200]> for KeccakF {}
111
112#[derive(Copy, Clone, Debug)]
115pub struct Keccak256Hash;
116
117impl CryptographicHasher<u8, [u8; 32]> for Keccak256Hash {
118 fn hash_iter<I>(&self, input: I) -> [u8; 32]
119 where
120 I: IntoIterator<Item = u8>,
121 {
122 const BUFLEN: usize = 512; let mut hasher = Keccak::v256();
124 p3_util::apply_to_chunks::<BUFLEN, _, _>(input, |buf| hasher.update(buf));
125
126 let mut output = [0u8; 32];
127 hasher.finalize(&mut output);
128 output
129 }
130
131 fn hash_iter_slices<'a, I>(&self, input: I) -> [u8; 32]
132 where
133 I: IntoIterator<Item = &'a [u8]>,
134 {
135 let mut hasher = Keccak::v256();
136 for chunk in input.into_iter() {
137 hasher.update(chunk);
138 }
139
140 let mut output = [0u8; 32];
141 hasher.finalize(&mut output);
142 output
143 }
144}