1#![cfg(target_endian="little")]
28#![doc(cfg(target_endian="little"))]
29
30use {
86 core::mem,
87 alloc::{
88 string::String,
89 vec::Vec,
90 },
91 crate::{Bytes, Result},
92 self::{
93 bits::Bits,
94 state::State,
95 },
96};
97
98#[cfg(feature="std")]
99use {
100 std::io::Write,
101 crate::IoResult,
102};
103
104pub use self::{
105 hash::Hash,
106 keccak_x::{KeccakX, XType},
107 r#type::Type,
108};
109
110#[cfg(feature="std")]
111pub use self::{
112 hash_reader::*,
113 hash_writer::*,
114};
115
116macro_rules! u8_bits { () => { 8 }}
117
118mod bits;
119mod hash;
120mod keccak_x;
121mod state;
122mod tests;
123mod r#type;
124
125#[cfg(feature="std")]
126mod hash_reader;
127#[cfg(feature="std")]
128mod hash_writer;
129
130type OneLane = u64;
131const SIZE_OF_ONE_LANE: usize = mem::size_of::<OneLane>();
132
133type Lanes = [OneLane; NUMBER_OF_LANES];
134const NUMBER_OF_LANES: usize = 25;
135const LANES_OF_ZEROS: Lanes = [OneLane::MIN; NUMBER_OF_LANES];
136
137type InnerType = char;
140
141#[derive(Debug, Clone, Eq, PartialEq)]
143pub struct Keccak<const TYPE: InnerType> {
144 hash: Hash,
145 bits: Bits,
146 buf: Vec<u8>,
147 buf_chunk: usize,
148 lanes: Lanes,
149 output_bytes: Option<usize>,
150}
151
152impl<const TYPE: InnerType> Keccak<TYPE> {
153
154 fn with(hash: Hash) -> Keccak<TYPE> {
156 let bits = Bits::B1600;
157 let buf_chunk = hash.rate() / u8_bits!();
158 let buf = Vec::with_capacity(buf_chunk);
159 let output_bytes = Some(hash.output_bytes());
160
161 Self {
162 hash,
163 bits,
164 buf,
165 buf_chunk,
166 lanes: LANES_OF_ZEROS,
167 output_bytes,
168 }
169 }
170
171 pub (crate) fn new(hash: Hash) -> Keccak<{Type::Function.id()}> {
173 Keccak::with(hash)
174 }
175
176 pub (crate) fn make_with_output_bytes(hash: Hash, output_bytes: usize) -> Result<Keccak<{Type::LimitedXOF.id()}>> {
178 if hash.is_extendable_output_function() {
179 if output_bytes >= Hash::MIN_CUSTOM_OUTPUT_BYTES {
180 let mut result = Keccak::with(hash);
181 result.output_bytes = Some(output_bytes);
182 Ok(result)
183 } else {
184 Err(err!("Custom output bytes must be equal to or larger than {min}", min=Hash::MIN_CUSTOM_OUTPUT_BYTES))
185 }
186 } else {
187 Err(err!("{hash} does not support custom output bits", hash=hash))
188 }
189 }
190
191 pub (crate) fn make_with_unlimited_output_bytes(hash: Hash) -> Result<Keccak<{Type::UnlimitedXOF.id()}>> {
193 if hash.is_extendable_output_function() {
194 let mut result = Keccak::with(hash);
195 result.output_bytes = None;
196 Ok(result)
197 } else {
198 Err(err!("{hash} does not support custom output bits", hash=hash))
199 }
200 }
201
202 pub const fn hash(&self) -> &Hash {
204 &self.hash
205 }
206
207 pub fn update<B>(&mut self, bytes: B) -> usize where B: AsRef<[u8]> {
211 macro_rules! proc { ($buf: expr) => {{
212 let buf = $buf.unwrap_or(&self.buf);
213 for (idx, c) in {
215 let chunks = buf.chunks_exact(SIZE_OF_ONE_LANE);
216 #[cfg(test)]
217 assert!(chunks.remainder().is_empty());
218 chunks.enumerate()
219 } {
220 self.lanes[idx] ^= u64::from_le_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]]);
221 }
222 keccak_p_1600_24(&mut self.lanes);
224 }}}
225
226 let mut bytes = bytes.as_ref();
227 let result = bytes.len();
228
229 if crate::io::fill_buffer(&mut self.buf, self.buf_chunk, &mut bytes) {
231 proc!(None);
232 self.buf.clear();
233 }
234
235 let chunks = bytes.chunks_exact(self.buf_chunk);
237 self.buf.extend(chunks.remainder());
238 chunks.for_each(|c| proc!(Some(c)));
239
240 result
241 }
242
243 pub fn update_bytes<'a, const N: usize, B, B0>(&mut self, bytes: B) -> Option<usize> where B: Into<Bytes<'a, N, B0>>, B0: AsRef<[u8]> + 'a {
247 let mut result = Some(usize::MIN);
248 for bytes in bytes.into().as_slice() {
249 let size = self.update(bytes);
250 if let Some(current) = result.as_mut() {
251 match current.checked_add(size) {
252 Some(new) => *current = new,
253 None => result = None,
254 };
255 }
256 }
257
258 result
259 }
260
261 fn finish_as_keccak_x<const T: keccak_x::InnerXType>(mut self) -> KeccakX<T> {
263 const ZEROS: &[u8] = &[u8::MIN; 128];
264
265 let suffix = self.hash.suffix();
267 let suffix_len = (u8_bits!() - suffix.leading_zeros()) as u8;
268 let bits = {
269 let j = (|| {
270 let j = isize::try_from(self.buf.len()).ok()?.checked_mul(u8_bits!())?.checked_add(suffix_len.into())?
271 .checked_neg()?.checked_sub(2)?.rem_euclid(isize::try_from(self.hash.rate()).ok()?);
272 usize::try_from(j).ok()
273 })().unwrap();
274 match j.checked_add(2).map(|n| n.checked_add(suffix_len.into())) {
275 Some(Some(bits)) => bits,
276 _ => panic!("{}", e!()),
277 }
278 };
279
280 let bytes = if bits % u8_bits!() == usize::MIN { bits / u8_bits!() } else { panic!("{}", err!("Invalid bits: {bits}")); };
281 self.buf.reserve(bytes);
282
283 self.buf.push(suffix | (1 << u32::from(suffix_len)));
285 if let Some(mut bytes) = bytes.checked_sub(1) {
286 while bytes > usize::MIN {
287 let count = bytes.min(ZEROS.len());
288 self.buf.extend(&ZEROS[..count]);
289 bytes -= count;
290 }
291 }
292 *self.buf.last_mut().unwrap() |= 0b_1000_0000;
293
294 self.update(&[]);
295
296 KeccakX::new(self.hash, self.lanes, self.buf_chunk, self.output_bytes)
298 }
299
300}
301
302impl Keccak<{Type::Function.id()}> {
303
304 pub fn finish(self) -> Vec<u8> {
306 self.finish_as_keccak_x::<{XType::Limited.id()}>().finish()
307 }
308
309 pub fn finish_as_hex(self) -> String {
311 crate::bytes_to_hex(self.finish())
312 }
313
314}
315
316impl Keccak<{Type::LimitedXOF.id()}> {
318
319 pub fn finish(self) -> KeccakX<{XType::Limited.id()}> {
321 self.finish_as_keccak_x()
322 }
323
324}
325
326impl Keccak<{Type::UnlimitedXOF.id()}> {
328
329 pub fn finish(self) -> KeccakX<{XType::Unlimited.id()}> {
331 self.finish_as_keccak_x()
332 }
333
334}
335
336impl From<Hash> for Keccak<{Type::Function.id()}> {
337
338 fn from(hash: Hash) -> Self {
339 Self::new(hash)
340 }
341
342}
343
344impl From<&Hash> for Keccak<{Type::Function.id()}> {
345
346 fn from(hash: &Hash) -> Self {
347 Self::new(hash.clone())
348 }
349
350}
351
352#[cfg(feature="std")]
353#[doc(cfg(feature="std"))]
354impl<const TYPE: InnerType> Write for Keccak<TYPE> {
355
356 #[inline(always)]
357 fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
358 Ok(self.update(buf))
359 }
360
361 #[inline(always)]
362 fn flush(&mut self) -> IoResult<()> {
363 Ok(())
364 }
365
366}
367
368#[inline(always)]
370fn keccak_p_1600_24(lanes: &mut Lanes) {
371 keccak_p(&Bits::B1600, 24, lanes);
372}
373
374#[inline(always)]
376fn keccak_p(bits: &Bits, rounds: usize, lanes: &mut Lanes) {
377 let mut state = State::new(lanes);
378
379 let end = 12 + 2 * bits.l();
380 for round_index in end - rounds .. end {
381 state.theta();
382 state.rho_and_pi();
383 state.chi();
384 state.iota(round_index);
385 }
386}
387
388#[allow(unused)]
390fn keccak_f(bits: &Bits, lanes: &mut Lanes) {
391 let rounds = 12 + 2 * bits.l();
392 keccak_p(bits, rounds, lanes);
393}