k12 0.5.1

Implementation of the KangarooTwelve family of extendable-output functions
Documentation
use crate::consts::{INTERMEDIATE_NODE_DS, PAD};
use keccak::{Fn1600, State1600};
use sponge_cursor::SpongeCursor;

use crate::utils::copy_cv;

#[derive(Default, Clone)]
pub(crate) struct TurboShake<const RATE: usize> {
    state: State1600,
    cursor: SpongeCursor<RATE>,
}

impl<const RATE: usize> TurboShake<RATE> {
    pub(crate) fn absorb(&mut self, p1600: Fn1600, data: &[u8]) {
        self.cursor.absorb_u64_le(&mut self.state, p1600, data);
    }

    pub(crate) fn pad<const DS: u8>(&mut self) {
        let pos = self.cursor.pos();
        let word_offset = pos / 8;
        let byte_offset = pos % 8;

        let pad = u64::from(DS) << (8 * byte_offset);
        self.state[word_offset] ^= pad;
        self.state[RATE / 8 - 1] ^= PAD;
    }

    pub(crate) fn finalize_intermediate_node(&mut self, p1600: Fn1600, cv_dst: &mut [u8]) {
        self.pad::<INTERMEDIATE_NODE_DS>();
        p1600(&mut self.state);
        copy_cv(self.state(), cv_dst);
    }

    pub(crate) fn state(&self) -> &State1600 {
        &self.state
    }

    pub(crate) fn reset(&mut self) {
        self.state = Default::default();
        self.cursor = Default::default();
    }
}

impl<const RATE: usize> Drop for TurboShake<RATE> {
    fn drop(&mut self) {
        #[cfg(feature = "zeroize")]
        {
            use digest::zeroize::Zeroize;
            self.state.zeroize();
            self.cursor.zeroize();
        }
    }
}