xoodyak/xoodyak/
mod.rs

1#[allow(clippy::unit_arg)]
2mod any;
3mod hash;
4mod keyed;
5mod tag;
6
7pub use any::*;
8pub use hash::*;
9pub use keyed::*;
10pub use tag::*;
11
12use crate::error::*;
13use crate::xoodoo::*;
14
15pub(crate) const HASH_ABSORB_RATE: usize = 16;
16pub(crate) const HASH_SQUEEZE_RATE: usize = 16;
17pub(crate) const KEYED_ABSORB_RATE: usize = 44;
18pub(crate) const KEYED_SQUEEZE_RATE: usize = 24;
19pub(crate) const RATCHET_RATE: usize = 16;
20
21mod internal {
22    use super::*;
23
24    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
25    pub enum Mode {
26        Hash,
27        Keyed,
28    }
29
30    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
31    pub enum Phase {
32        Up,
33        Down,
34    }
35
36    pub trait XoodyakCommon {
37        fn state(&mut self) -> &mut Xoodoo;
38        fn mode(&self) -> Mode;
39        fn phase(&self) -> Phase;
40        fn set_phase(&mut self, phase: Phase);
41        fn absorb_rate(&self) -> usize;
42        fn squeeze_rate(&self) -> usize;
43
44        #[inline(always)]
45        fn permute(&mut self) {
46            self.state().permute()
47        }
48
49        #[inline(always)]
50        fn add_byte(&mut self, byte: u8, offset: usize) {
51            self.state().add_byte(byte, offset);
52        }
53
54        #[inline(always)]
55        fn add_bytes(&mut self, bytes: &[u8]) {
56            self.state().add_bytes(bytes);
57        }
58
59        #[inline(always)]
60        fn extract_bytes(&mut self, out: &mut [u8]) {
61            self.state().extract_bytes(out);
62        }
63
64        #[inline(always)]
65        fn up(&mut self, out: Option<&mut [u8]>, cu: u8) {
66            debug_assert!(out.as_ref().map(|x| x.len()).unwrap_or(0) <= self.squeeze_rate());
67            self.set_phase(Phase::Up);
68            if self.mode() != Mode::Hash {
69                self.add_byte(cu, 47);
70            }
71            self.permute();
72            if let Some(out) = out {
73                self.extract_bytes(out);
74            }
75        }
76
77        #[inline(always)]
78        fn down(&mut self, bin: Option<&[u8]>, cd: u8) {
79            debug_assert!(bin.as_ref().map(|x| x.len()).unwrap_or(0) <= self.absorb_rate());
80            self.set_phase(Phase::Down);
81            if let Some(bin) = bin {
82                self.add_bytes(bin);
83                self.add_byte(0x01, bin.len());
84            } else {
85                self.add_byte(0x01, 0);
86            }
87            if self.mode() == Mode::Hash {
88                self.add_byte(cd & 0x01, 47);
89            } else {
90                self.add_byte(cd, 47);
91            }
92        }
93
94        #[inline]
95        fn absorb_any(&mut self, bin: &[u8], rate: usize, cd: u8) {
96            let mut chunks_it = bin.chunks(rate);
97            if self.phase() != Phase::Up {
98                self.up(None, 0x00)
99            }
100            self.down(chunks_it.next(), cd);
101            for chunk in chunks_it {
102                self.up(None, 0x00);
103                self.down(Some(chunk), 0x00);
104            }
105        }
106
107        #[inline]
108        fn squeeze_any(&mut self, out: &mut [u8], cu: u8) {
109            let mut chunks_it = out.chunks_mut(self.squeeze_rate());
110            self.up(chunks_it.next(), cu);
111            for chunk in chunks_it {
112                self.down(None, 0x00);
113                self.up(Some(chunk), 0x00);
114            }
115        }
116    }
117}
118
119pub trait XoodyakCommon: internal::XoodyakCommon {
120    #[inline(always)]
121    fn absorb(&mut self, bin: &[u8]) {
122        self.absorb_any(bin, self.absorb_rate(), 0x03);
123    }
124
125    #[inline]
126    fn absorb_more(&mut self, bin: &[u8], rate: usize) {
127        for chunk in bin.chunks(rate) {
128            self.up(None, 0x00);
129            self.down(Some(chunk), 0x00);
130        }
131    }
132
133    #[inline(always)]
134    fn squeeze(&mut self, out: &mut [u8]) {
135        self.squeeze_any(out, 0x40);
136    }
137
138    #[inline(always)]
139    fn squeeze_key(&mut self, out: &mut [u8]) {
140        self.squeeze_any(out, 0x20);
141    }
142
143    #[inline]
144    fn squeeze_more(&mut self, out: &mut [u8]) {
145        for chunk in out.chunks_mut(self.squeeze_rate()) {
146            self.down(None, 0x00);
147            self.up(Some(chunk), 0x00);
148        }
149    }
150
151    #[cfg(feature = "std")]
152    fn squeeze_to_vec(&mut self, len: usize) -> Vec<u8> {
153        let mut out = vec![0u8; len];
154        self.squeeze(&mut out);
155        out
156    }
157}