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