Skip to main content

k12/
reader.rs

1use crate::consts::ROUNDS;
2use core::fmt;
3use digest::XofReader;
4use keccak::{Keccak, State1600};
5use sponge_cursor::SpongeCursor;
6
7/// KangarooTwelve XOF reader generic over rate.
8#[derive(Clone)]
9pub struct KtReader<const RATE: usize> {
10    state: State1600,
11    cursor: SpongeCursor<RATE>,
12    keccak: Keccak,
13}
14
15impl<const RATE: usize> KtReader<RATE> {
16    pub(crate) fn new(state: &State1600, keccak: Keccak) -> Self {
17        Self {
18            state: *state,
19            cursor: Default::default(),
20            keccak,
21        }
22    }
23}
24
25impl<const RATE: usize> XofReader for KtReader<RATE> {
26    #[inline]
27    fn read(&mut self, buf: &mut [u8]) {
28        self.keccak.with_p1600::<ROUNDS>(|p1600| {
29            self.cursor.squeeze_read_u64_le(&mut self.state, p1600, buf);
30        });
31    }
32}
33
34impl<const RATE: usize> fmt::Debug for KtReader<RATE> {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        let debug_str = match RATE {
37            168 => "Kt128Reader { ... }",
38            136 => "Kt256Reader { ... }",
39            _ => unreachable!(),
40        };
41        f.write_str(debug_str)
42    }
43}
44
45impl<const RATE: usize> Drop for KtReader<RATE> {
46    fn drop(&mut self) {
47        #[cfg(feature = "zeroize")]
48        {
49            use digest::zeroize::Zeroize;
50            self.state.zeroize();
51            // self.buffer is zeroized by its `Drop`
52        }
53    }
54}
55
56#[cfg(feature = "zeroize")]
57impl<const RATE: usize> digest::zeroize::ZeroizeOnDrop for KtReader<RATE> {}