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