Skip to main content

sha3/
utils.rs

1use keccak::State1600;
2use sponge_cursor::SpongeCursor;
3
4#[inline(always)]
5pub(crate) fn pad<const PAD: u8, const RATE: usize>(
6    state: &mut State1600,
7    cursor: &SpongeCursor<RATE>,
8) {
9    let pos = cursor.pos();
10    let word_offset = pos / 8;
11    let byte_offset = pos % 8;
12
13    let pad = u64::from(PAD) << (8 * byte_offset);
14    state[word_offset] ^= pad;
15    state[RATE / 8 - 1] ^= 1 << 63;
16}
17
18#[inline(always)]
19pub(crate) fn read_state(state: &State1600, dst: &mut [u8]) {
20    assert!(size_of_val(dst) <= size_of_val(state));
21
22    let chunks = dst.chunks_mut(size_of::<u64>());
23    for (src, dst) in state.iter().zip(chunks) {
24        dst.copy_from_slice(&src.to_le_bytes()[..dst.len()]);
25    }
26}
27
28#[inline(always)]
29pub(crate) fn serialize<const RATE: usize>(
30    state: &State1600,
31    cursor: &SpongeCursor<RATE>,
32) -> [u8; 201] {
33    let mut ser_state = [0u8; 201];
34    // TODO(MSRV-1.88): use `ser_state.as_chunks_mut()`
35    let [state_dst @ .., cursor_dst] = &mut ser_state;
36
37    let state_dst_chunks = state_dst.chunks_exact_mut(size_of::<u64>());
38    for (src, dst) in state.iter().zip(state_dst_chunks) {
39        dst.copy_from_slice(&src.to_le_bytes());
40    }
41
42    *cursor_dst = cursor.raw_pos();
43    ser_state
44}
45
46#[inline(always)]
47pub(crate) fn deserialize<const RATE: usize>(
48    ser_state: &[u8; 201],
49) -> Option<(State1600, SpongeCursor<RATE>)> {
50    // TODO(MSRV-1.88): use `ser_state.as_chunks()`
51    let [state_src @ .., cursor_src] = ser_state;
52
53    let n = size_of::<u64>();
54    let state = core::array::from_fn(|i| {
55        let chunk = state_src[n * i..][..n]
56            .try_into()
57            .expect("chunk has correct length");
58        u64::from_le_bytes(chunk)
59    });
60
61    let cursor = SpongeCursor::new(*cursor_src)?;
62    Some((state, cursor))
63}