Coverage Report

Created: 2025-07-11 06:35

/rust/registry/src/index.crates.io-6f17d22bba15001f/keccak-0.1.5/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
//! Keccak [sponge function](https://en.wikipedia.org/wiki/Sponge_function).
2
//!
3
//! If you are looking for SHA-3 hash functions take a look at [`sha3`][1] and
4
//! [`tiny-keccak`][2] crates.
5
//!
6
//! To disable loop unrolling (e.g. for constraint targets) use `no_unroll`
7
//! feature.
8
//!
9
//! ```
10
//! // Test vectors are from KeccakCodePackage
11
//! let mut data = [0u64; 25];
12
//!
13
//! keccak::f1600(&mut data);
14
//! assert_eq!(data, [
15
//!     0xF1258F7940E1DDE7, 0x84D5CCF933C0478A, 0xD598261EA65AA9EE, 0xBD1547306F80494D,
16
//!     0x8B284E056253D057, 0xFF97A42D7F8E6FD4, 0x90FEE5A0A44647C4, 0x8C5BDA0CD6192E76,
17
//!     0xAD30A6F71B19059C, 0x30935AB7D08FFC64, 0xEB5AA93F2317D635, 0xA9A6E6260D712103,
18
//!     0x81A57C16DBCF555F, 0x43B831CD0347C826, 0x01F22F1A11A5569F, 0x05E5635A21D9AE61,
19
//!     0x64BEFEF28CC970F2, 0x613670957BC46611, 0xB87C5A554FD00ECB, 0x8C3EE88A1CCF32C8,
20
//!     0x940C7922AE3A2614, 0x1841F924A2C509E4, 0x16F53526E70465C2, 0x75F644E97F30A13B,
21
//!     0xEAF1FF7B5CECA249,
22
//! ]);
23
//!
24
//! keccak::f1600(&mut data);
25
//! assert_eq!(data, [
26
//!     0x2D5C954DF96ECB3C, 0x6A332CD07057B56D, 0x093D8D1270D76B6C, 0x8A20D9B25569D094,
27
//!     0x4F9C4F99E5E7F156, 0xF957B9A2DA65FB38, 0x85773DAE1275AF0D, 0xFAF4F247C3D810F7,
28
//!     0x1F1B9EE6F79A8759, 0xE4FECC0FEE98B425, 0x68CE61B6B9CE68A1, 0xDEEA66C4BA8F974F,
29
//!     0x33C43D836EAFB1F5, 0xE00654042719DBD9, 0x7CF8A9F009831265, 0xFD5449A6BF174743,
30
//!     0x97DDAD33D8994B40, 0x48EAD5FC5D0BE774, 0xE3B8C8EE55B7B03C, 0x91A0226E649E42E9,
31
//!     0x900E3129E7BADD7B, 0x202A9EC5FAA3CCE8, 0x5B3402464E1C3DB6, 0x609F4E62A44C1059,
32
//!     0x20D06CD26A8FBF5C,
33
//! ]);
34
//! ```
35
//!
36
//! [1]: https://docs.rs/sha3
37
//! [2]: https://docs.rs/tiny-keccak
38
39
#![no_std]
40
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
41
#![cfg_attr(feature = "simd", feature(portable_simd))]
42
#![doc(
43
    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
44
    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
45
)]
46
#![allow(non_upper_case_globals)]
47
#![warn(
48
    clippy::mod_module_files,
49
    clippy::unwrap_used,
50
    missing_docs,
51
    rust_2018_idioms,
52
    unused_lifetimes,
53
    unused_qualifications
54
)]
55
56
use core::{
57
    convert::TryInto,
58
    fmt::Debug,
59
    mem::size_of,
60
    ops::{BitAnd, BitAndAssign, BitXor, BitXorAssign, Not},
61
};
62
63
#[rustfmt::skip]
64
mod unroll;
65
66
#[cfg(all(target_arch = "aarch64", feature = "asm"))]
67
mod armv8;
68
69
#[cfg(all(target_arch = "aarch64", feature = "asm"))]
70
cpufeatures::new!(armv8_sha3_intrinsics, "sha3");
71
72
const PLEN: usize = 25;
73
74
const RHO: [u32; 24] = [
75
    1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
76
];
77
78
const PI: [usize; 24] = [
79
    10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
80
];
81
82
const RC: [u64; 24] = [
83
    0x0000000000000001,
84
    0x0000000000008082,
85
    0x800000000000808a,
86
    0x8000000080008000,
87
    0x000000000000808b,
88
    0x0000000080000001,
89
    0x8000000080008081,
90
    0x8000000000008009,
91
    0x000000000000008a,
92
    0x0000000000000088,
93
    0x0000000080008009,
94
    0x000000008000000a,
95
    0x000000008000808b,
96
    0x800000000000008b,
97
    0x8000000000008089,
98
    0x8000000000008003,
99
    0x8000000000008002,
100
    0x8000000000000080,
101
    0x000000000000800a,
102
    0x800000008000000a,
103
    0x8000000080008081,
104
    0x8000000000008080,
105
    0x0000000080000001,
106
    0x8000000080008008,
107
];
108
109
/// Keccak is a permutation over an array of lanes which comprise the sponge
110
/// construction.
111
pub trait LaneSize:
112
    Copy
113
    + Clone
114
    + Debug
115
    + Default
116
    + PartialEq
117
    + BitAndAssign
118
    + BitAnd<Output = Self>
119
    + BitXorAssign
120
    + BitXor<Output = Self>
121
    + Not<Output = Self>
122
{
123
    /// Number of rounds of the Keccak-f permutation.
124
    const KECCAK_F_ROUND_COUNT: usize;
125
126
    /// Truncate function.
127
    fn truncate_rc(rc: u64) -> Self;
128
129
    /// Rotate left function.
130
    fn rotate_left(self, n: u32) -> Self;
131
}
132
133
macro_rules! impl_lanesize {
134
    ($type:ty, $round:expr, $truncate:expr) => {
135
        impl LaneSize for $type {
136
            const KECCAK_F_ROUND_COUNT: usize = $round;
137
138
3.08M
            fn truncate_rc(rc: u64) -> Self {
139
3.08M
                $truncate(rc)
140
3.08M
            }
Unexecuted instantiation: <u8 as keccak::LaneSize>::truncate_rc
Unexecuted instantiation: <u16 as keccak::LaneSize>::truncate_rc
Unexecuted instantiation: <u32 as keccak::LaneSize>::truncate_rc
<u64 as keccak::LaneSize>::truncate_rc
Line
Count
Source
138
3.08M
            fn truncate_rc(rc: u64) -> Self {
139
3.08M
                $truncate(rc)
140
3.08M
            }
141
142
150M
            fn rotate_left(self, n: u32) -> Self {
143
150M
                self.rotate_left(n)
144
150M
            }
Unexecuted instantiation: <u8 as keccak::LaneSize>::rotate_left
Unexecuted instantiation: <u16 as keccak::LaneSize>::rotate_left
Unexecuted instantiation: <u32 as keccak::LaneSize>::rotate_left
<u64 as keccak::LaneSize>::rotate_left
Line
Count
Source
142
150M
            fn rotate_left(self, n: u32) -> Self {
143
150M
                self.rotate_left(n)
144
150M
            }
145
        }
146
    };
147
}
148
149
0
impl_lanesize!(u8, 18, |rc: u64| { rc.to_le_bytes()[0] });
150
0
impl_lanesize!(u16, 20, |rc: u64| {
151
0
    let tmp = rc.to_le_bytes();
152
0
    #[allow(clippy::unwrap_used)]
153
0
    Self::from_le_bytes(tmp[..size_of::<Self>()].try_into().unwrap())
154
0
});
155
0
impl_lanesize!(u32, 22, |rc: u64| {
156
0
    let tmp = rc.to_le_bytes();
157
0
    #[allow(clippy::unwrap_used)]
158
0
    Self::from_le_bytes(tmp[..size_of::<Self>()].try_into().unwrap())
159
0
});
160
3.08M
impl_lanesize!(u64, 24, |rc: u64| { rc });
161
162
macro_rules! impl_keccak {
163
    ($pname:ident, $fname:ident, $type:ty) => {
164
        /// Keccak-p sponge function
165
128k
        pub fn $pname(state: &mut [$type; PLEN], round_count: usize) {
166
128k
            keccak_p(state, round_count);
167
128k
        }
Unexecuted instantiation: keccak::p200
Unexecuted instantiation: keccak::p400
Unexecuted instantiation: keccak::p800
keccak::p1600
Line
Count
Source
165
128k
        pub fn $pname(state: &mut [$type; PLEN], round_count: usize) {
166
128k
            keccak_p(state, round_count);
167
128k
        }
168
169
        /// Keccak-f sponge function
170
0
        pub fn $fname(state: &mut [$type; PLEN]) {
171
0
            keccak_p(state, <$type>::KECCAK_F_ROUND_COUNT);
172
0
        }
Unexecuted instantiation: keccak::f200
Unexecuted instantiation: keccak::f400
Unexecuted instantiation: keccak::f800
Unexecuted instantiation: keccak::f1600
173
    };
174
}
175
176
impl_keccak!(p200, f200, u8);
177
impl_keccak!(p400, f400, u16);
178
impl_keccak!(p800, f800, u32);
179
180
#[cfg(not(all(target_arch = "aarch64", feature = "asm")))]
181
impl_keccak!(p1600, f1600, u64);
182
183
/// Keccak-p[1600, rc] permutation.
184
#[cfg(all(target_arch = "aarch64", feature = "asm"))]
185
pub fn p1600(state: &mut [u64; PLEN], round_count: usize) {
186
    if armv8_sha3_intrinsics::get() {
187
        unsafe { armv8::p1600_armv8_sha3_asm(state, round_count) }
188
    } else {
189
        keccak_p(state, round_count);
190
    }
191
}
192
193
/// Keccak-f[1600] permutation.
194
#[cfg(all(target_arch = "aarch64", feature = "asm"))]
195
pub fn f1600(state: &mut [u64; PLEN]) {
196
    if armv8_sha3_intrinsics::get() {
197
        unsafe { armv8::p1600_armv8_sha3_asm(state, 24) }
198
    } else {
199
        keccak_p(state, u64::KECCAK_F_ROUND_COUNT);
200
    }
201
}
202
203
#[cfg(feature = "simd")]
204
/// SIMD implementations for Keccak-f1600 sponge function
205
pub mod simd {
206
    use crate::{keccak_p, LaneSize, PLEN};
207
    pub use core::simd::{u64x2, u64x4, u64x8};
208
209
    macro_rules! impl_lanesize_simd_u64xn {
210
        ($type:ty) => {
211
            impl LaneSize for $type {
212
                const KECCAK_F_ROUND_COUNT: usize = 24;
213
214
                fn truncate_rc(rc: u64) -> Self {
215
                    Self::splat(rc)
216
                }
217
218
                fn rotate_left(self, n: u32) -> Self {
219
                    self << Self::splat(n.into()) | self >> Self::splat((64 - n).into())
220
                }
221
            }
222
        };
223
    }
224
225
    impl_lanesize_simd_u64xn!(u64x2);
226
    impl_lanesize_simd_u64xn!(u64x4);
227
    impl_lanesize_simd_u64xn!(u64x8);
228
229
    impl_keccak!(p1600x2, f1600x2, u64x2);
230
    impl_keccak!(p1600x4, f1600x4, u64x4);
231
    impl_keccak!(p1600x8, f1600x8, u64x8);
232
}
233
234
#[allow(unused_assignments)]
235
/// Generic Keccak-p sponge function
236
128k
pub fn keccak_p<L: LaneSize>(state: &mut [L; PLEN], round_count: usize) {
237
128k
    if round_count > L::KECCAK_F_ROUND_COUNT {
238
0
        panic!("A round_count greater than KECCAK_F_ROUND_COUNT is not supported!");
239
128k
    }
240
128k
241
128k
    // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=25
242
128k
    // "the rounds of KECCAK-p[b, nr] match the last rounds of KECCAK-f[b]"
243
128k
    let round_consts = &RC[(L::KECCAK_F_ROUND_COUNT - round_count)..L::KECCAK_F_ROUND_COUNT];
244
245
    // not unrolling this loop results in a much smaller function, plus
246
    // it positively influences performance due to the smaller load on I-cache
247
3.20M
    for &rc in round_consts {
248
3.08M
        let mut array = [L::default(); 5];
249
3.08M
250
3.08M
        // Theta
251
3.08M
        unroll5!(x, {
252
3.08M
            unroll5!(y, {
253
3.08M
                array[x] ^= state[5 * y + x];
254
3.08M
            });
255
3.08M
        });
256
3.08M
257
3.08M
        unroll5!(x, {
258
3.08M
            unroll5!(y, {
259
3.08M
                let t1 = array[(x + 4) % 5];
260
3.08M
                let t2 = array[(x + 1) % 5].rotate_left(1);
261
3.08M
                state[5 * y + x] ^= t1 ^ t2;
262
3.08M
            });
263
3.08M
        });
264
3.08M
265
3.08M
        // Rho and pi
266
3.08M
        let mut last = state[1];
267
3.08M
        unroll24!(x, {
268
3.08M
            array[0] = state[PI[x]];
269
3.08M
            state[PI[x]] = last.rotate_left(RHO[x]);
270
3.08M
            last = array[0];
271
3.08M
        });
272
3.08M
273
3.08M
        // Chi
274
3.08M
        unroll5!(y_step, {
275
3.08M
            let y = 5 * y_step;
276
3.08M
277
3.08M
            unroll5!(x, {
278
3.08M
                array[x] = state[y + x];
279
3.08M
            });
280
3.08M
281
3.08M
            unroll5!(x, {
282
3.08M
                let t1 = !array[(x + 1) % 5];
283
3.08M
                let t2 = array[(x + 2) % 5];
284
3.08M
                state[y + x] = array[x] ^ (t1 & t2);
285
3.08M
            });
286
3.08M
        });
287
3.08M
288
3.08M
        // Iota
289
3.08M
        state[0] ^= L::truncate_rc(rc);
290
3.08M
    }
291
128k
}
Unexecuted instantiation: keccak::keccak_p::<u8>
Unexecuted instantiation: keccak::keccak_p::<u32>
Unexecuted instantiation: keccak::keccak_p::<u16>
keccak::keccak_p::<u64>
Line
Count
Source
236
128k
pub fn keccak_p<L: LaneSize>(state: &mut [L; PLEN], round_count: usize) {
237
128k
    if round_count > L::KECCAK_F_ROUND_COUNT {
238
0
        panic!("A round_count greater than KECCAK_F_ROUND_COUNT is not supported!");
239
128k
    }
240
128k
241
128k
    // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=25
242
128k
    // "the rounds of KECCAK-p[b, nr] match the last rounds of KECCAK-f[b]"
243
128k
    let round_consts = &RC[(L::KECCAK_F_ROUND_COUNT - round_count)..L::KECCAK_F_ROUND_COUNT];
244
245
    // not unrolling this loop results in a much smaller function, plus
246
    // it positively influences performance due to the smaller load on I-cache
247
3.20M
    for &rc in round_consts {
248
3.08M
        let mut array = [L::default(); 5];
249
3.08M
250
3.08M
        // Theta
251
3.08M
        unroll5!(x, {
252
3.08M
            unroll5!(y, {
253
3.08M
                array[x] ^= state[5 * y + x];
254
3.08M
            });
255
3.08M
        });
256
3.08M
257
3.08M
        unroll5!(x, {
258
3.08M
            unroll5!(y, {
259
3.08M
                let t1 = array[(x + 4) % 5];
260
3.08M
                let t2 = array[(x + 1) % 5].rotate_left(1);
261
3.08M
                state[5 * y + x] ^= t1 ^ t2;
262
3.08M
            });
263
3.08M
        });
264
3.08M
265
3.08M
        // Rho and pi
266
3.08M
        let mut last = state[1];
267
3.08M
        unroll24!(x, {
268
3.08M
            array[0] = state[PI[x]];
269
3.08M
            state[PI[x]] = last.rotate_left(RHO[x]);
270
3.08M
            last = array[0];
271
3.08M
        });
272
3.08M
273
3.08M
        // Chi
274
3.08M
        unroll5!(y_step, {
275
3.08M
            let y = 5 * y_step;
276
3.08M
277
3.08M
            unroll5!(x, {
278
3.08M
                array[x] = state[y + x];
279
3.08M
            });
280
3.08M
281
3.08M
            unroll5!(x, {
282
3.08M
                let t1 = !array[(x + 1) % 5];
283
3.08M
                let t2 = array[(x + 2) % 5];
284
3.08M
                state[y + x] = array[x] ^ (t1 & t2);
285
3.08M
            });
286
3.08M
        });
287
3.08M
288
3.08M
        // Iota
289
3.08M
        state[0] ^= L::truncate_rc(rc);
290
3.08M
    }
291
128k
}
292
293
#[cfg(test)]
294
mod tests {
295
    use crate::{keccak_p, LaneSize, PLEN};
296
297
    fn keccak_f<L: LaneSize>(state_first: [L; PLEN], state_second: [L; PLEN]) {
298
        let mut state = [L::default(); PLEN];
299
300
        keccak_p(&mut state, L::KECCAK_F_ROUND_COUNT);
301
        assert_eq!(state, state_first);
302
303
        keccak_p(&mut state, L::KECCAK_F_ROUND_COUNT);
304
        assert_eq!(state, state_second);
305
    }
306
307
    #[test]
308
    fn keccak_f200() {
309
        // Test vectors are copied from XKCP (eXtended Keccak Code Package)
310
        // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-200-IntermediateValues.txt
311
        let state_first = [
312
            0x3C, 0x28, 0x26, 0x84, 0x1C, 0xB3, 0x5C, 0x17, 0x1E, 0xAA, 0xE9, 0xB8, 0x11, 0x13,
313
            0x4C, 0xEA, 0xA3, 0x85, 0x2C, 0x69, 0xD2, 0xC5, 0xAB, 0xAF, 0xEA,
314
        ];
315
        let state_second = [
316
            0x1B, 0xEF, 0x68, 0x94, 0x92, 0xA8, 0xA5, 0x43, 0xA5, 0x99, 0x9F, 0xDB, 0x83, 0x4E,
317
            0x31, 0x66, 0xA1, 0x4B, 0xE8, 0x27, 0xD9, 0x50, 0x40, 0x47, 0x9E,
318
        ];
319
320
        keccak_f::<u8>(state_first, state_second);
321
    }
322
323
    #[test]
324
    fn keccak_f400() {
325
        // Test vectors are copied from XKCP (eXtended Keccak Code Package)
326
        // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-400-IntermediateValues.txt
327
        let state_first = [
328
            0x09F5, 0x40AC, 0x0FA9, 0x14F5, 0xE89F, 0xECA0, 0x5BD1, 0x7870, 0xEFF0, 0xBF8F, 0x0337,
329
            0x6052, 0xDC75, 0x0EC9, 0xE776, 0x5246, 0x59A1, 0x5D81, 0x6D95, 0x6E14, 0x633E, 0x58EE,
330
            0x71FF, 0x714C, 0xB38E,
331
        ];
332
        let state_second = [
333
            0xE537, 0xD5D6, 0xDBE7, 0xAAF3, 0x9BC7, 0xCA7D, 0x86B2, 0xFDEC, 0x692C, 0x4E5B, 0x67B1,
334
            0x15AD, 0xA7F7, 0xA66F, 0x67FF, 0x3F8A, 0x2F99, 0xE2C2, 0x656B, 0x5F31, 0x5BA6, 0xCA29,
335
            0xC224, 0xB85C, 0x097C,
336
        ];
337
338
        keccak_f::<u16>(state_first, state_second);
339
    }
340
341
    #[test]
342
    fn keccak_f800() {
343
        // Test vectors are copied from XKCP (eXtended Keccak Code Package)
344
        // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-800-IntermediateValues.txt
345
        let state_first = [
346
            0xE531D45D, 0xF404C6FB, 0x23A0BF99, 0xF1F8452F, 0x51FFD042, 0xE539F578, 0xF00B80A7,
347
            0xAF973664, 0xBF5AF34C, 0x227A2424, 0x88172715, 0x9F685884, 0xB15CD054, 0x1BF4FC0E,
348
            0x6166FA91, 0x1A9E599A, 0xA3970A1F, 0xAB659687, 0xAFAB8D68, 0xE74B1015, 0x34001A98,
349
            0x4119EFF3, 0x930A0E76, 0x87B28070, 0x11EFE996,
350
        ];
351
        let state_second = [
352
            0x75BF2D0D, 0x9B610E89, 0xC826AF40, 0x64CD84AB, 0xF905BDD6, 0xBC832835, 0x5F8001B9,
353
            0x15662CCE, 0x8E38C95E, 0x701FE543, 0x1B544380, 0x89ACDEFF, 0x51EDB5DE, 0x0E9702D9,
354
            0x6C19AA16, 0xA2913EEE, 0x60754E9A, 0x9819063C, 0xF4709254, 0xD09F9084, 0x772DA259,
355
            0x1DB35DF7, 0x5AA60162, 0x358825D5, 0xB3783BAB,
356
        ];
357
358
        keccak_f::<u32>(state_first, state_second);
359
    }
360
361
    #[test]
362
    fn keccak_f1600() {
363
        // Test vectors are copied from XKCP (eXtended Keccak Code Package)
364
        // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt
365
        let state_first = [
366
            0xF1258F7940E1DDE7,
367
            0x84D5CCF933C0478A,
368
            0xD598261EA65AA9EE,
369
            0xBD1547306F80494D,
370
            0x8B284E056253D057,
371
            0xFF97A42D7F8E6FD4,
372
            0x90FEE5A0A44647C4,
373
            0x8C5BDA0CD6192E76,
374
            0xAD30A6F71B19059C,
375
            0x30935AB7D08FFC64,
376
            0xEB5AA93F2317D635,
377
            0xA9A6E6260D712103,
378
            0x81A57C16DBCF555F,
379
            0x43B831CD0347C826,
380
            0x01F22F1A11A5569F,
381
            0x05E5635A21D9AE61,
382
            0x64BEFEF28CC970F2,
383
            0x613670957BC46611,
384
            0xB87C5A554FD00ECB,
385
            0x8C3EE88A1CCF32C8,
386
            0x940C7922AE3A2614,
387
            0x1841F924A2C509E4,
388
            0x16F53526E70465C2,
389
            0x75F644E97F30A13B,
390
            0xEAF1FF7B5CECA249,
391
        ];
392
        let state_second = [
393
            0x2D5C954DF96ECB3C,
394
            0x6A332CD07057B56D,
395
            0x093D8D1270D76B6C,
396
            0x8A20D9B25569D094,
397
            0x4F9C4F99E5E7F156,
398
            0xF957B9A2DA65FB38,
399
            0x85773DAE1275AF0D,
400
            0xFAF4F247C3D810F7,
401
            0x1F1B9EE6F79A8759,
402
            0xE4FECC0FEE98B425,
403
            0x68CE61B6B9CE68A1,
404
            0xDEEA66C4BA8F974F,
405
            0x33C43D836EAFB1F5,
406
            0xE00654042719DBD9,
407
            0x7CF8A9F009831265,
408
            0xFD5449A6BF174743,
409
            0x97DDAD33D8994B40,
410
            0x48EAD5FC5D0BE774,
411
            0xE3B8C8EE55B7B03C,
412
            0x91A0226E649E42E9,
413
            0x900E3129E7BADD7B,
414
            0x202A9EC5FAA3CCE8,
415
            0x5B3402464E1C3DB6,
416
            0x609F4E62A44C1059,
417
            0x20D06CD26A8FBF5C,
418
        ];
419
420
        keccak_f::<u64>(state_first, state_second);
421
    }
422
423
    #[cfg(feature = "simd")]
424
    mod simd {
425
        use super::keccak_f;
426
        use core::simd::{u64x2, u64x4, u64x8};
427
428
        macro_rules! impl_keccak_f1600xn {
429
            ($name:ident, $type:ty) => {
430
                #[test]
431
                fn $name() {
432
                    // Test vectors are copied from XKCP (eXtended Keccak Code Package)
433
                    // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt
434
                    let state_first = [
435
                        <$type>::splat(0xF1258F7940E1DDE7),
436
                        <$type>::splat(0x84D5CCF933C0478A),
437
                        <$type>::splat(0xD598261EA65AA9EE),
438
                        <$type>::splat(0xBD1547306F80494D),
439
                        <$type>::splat(0x8B284E056253D057),
440
                        <$type>::splat(0xFF97A42D7F8E6FD4),
441
                        <$type>::splat(0x90FEE5A0A44647C4),
442
                        <$type>::splat(0x8C5BDA0CD6192E76),
443
                        <$type>::splat(0xAD30A6F71B19059C),
444
                        <$type>::splat(0x30935AB7D08FFC64),
445
                        <$type>::splat(0xEB5AA93F2317D635),
446
                        <$type>::splat(0xA9A6E6260D712103),
447
                        <$type>::splat(0x81A57C16DBCF555F),
448
                        <$type>::splat(0x43B831CD0347C826),
449
                        <$type>::splat(0x01F22F1A11A5569F),
450
                        <$type>::splat(0x05E5635A21D9AE61),
451
                        <$type>::splat(0x64BEFEF28CC970F2),
452
                        <$type>::splat(0x613670957BC46611),
453
                        <$type>::splat(0xB87C5A554FD00ECB),
454
                        <$type>::splat(0x8C3EE88A1CCF32C8),
455
                        <$type>::splat(0x940C7922AE3A2614),
456
                        <$type>::splat(0x1841F924A2C509E4),
457
                        <$type>::splat(0x16F53526E70465C2),
458
                        <$type>::splat(0x75F644E97F30A13B),
459
                        <$type>::splat(0xEAF1FF7B5CECA249),
460
                    ];
461
                    let state_second = [
462
                        <$type>::splat(0x2D5C954DF96ECB3C),
463
                        <$type>::splat(0x6A332CD07057B56D),
464
                        <$type>::splat(0x093D8D1270D76B6C),
465
                        <$type>::splat(0x8A20D9B25569D094),
466
                        <$type>::splat(0x4F9C4F99E5E7F156),
467
                        <$type>::splat(0xF957B9A2DA65FB38),
468
                        <$type>::splat(0x85773DAE1275AF0D),
469
                        <$type>::splat(0xFAF4F247C3D810F7),
470
                        <$type>::splat(0x1F1B9EE6F79A8759),
471
                        <$type>::splat(0xE4FECC0FEE98B425),
472
                        <$type>::splat(0x68CE61B6B9CE68A1),
473
                        <$type>::splat(0xDEEA66C4BA8F974F),
474
                        <$type>::splat(0x33C43D836EAFB1F5),
475
                        <$type>::splat(0xE00654042719DBD9),
476
                        <$type>::splat(0x7CF8A9F009831265),
477
                        <$type>::splat(0xFD5449A6BF174743),
478
                        <$type>::splat(0x97DDAD33D8994B40),
479
                        <$type>::splat(0x48EAD5FC5D0BE774),
480
                        <$type>::splat(0xE3B8C8EE55B7B03C),
481
                        <$type>::splat(0x91A0226E649E42E9),
482
                        <$type>::splat(0x900E3129E7BADD7B),
483
                        <$type>::splat(0x202A9EC5FAA3CCE8),
484
                        <$type>::splat(0x5B3402464E1C3DB6),
485
                        <$type>::splat(0x609F4E62A44C1059),
486
                        <$type>::splat(0x20D06CD26A8FBF5C),
487
                    ];
488
489
                    keccak_f::<$type>(state_first, state_second);
490
                }
491
            };
492
        }
493
494
        impl_keccak_f1600xn!(keccak_f1600x2, u64x2);
495
        impl_keccak_f1600xn!(keccak_f1600x4, u64x4);
496
        impl_keccak_f1600xn!(keccak_f1600x8, u64x8);
497
    }
498
}