1#![no_std]
42#![deny(missing_docs)]
43
44const RHO: [u32; 24] = [
45 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
46];
47
48const PI: [usize; 24] = [
49 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
50];
51
52const WORDS: usize = 25;
53
54macro_rules! keccak_function {
55 ($doc: expr, $name: ident, $rounds: expr, $rc: expr) => {
56 #[doc = $doc]
57 #[allow(unused_assignments)]
58 #[allow(non_upper_case_globals)]
59 pub fn $name(a: &mut [u64; $crate::WORDS]) {
60 use crunchy::unroll;
61
62 for i in 0..$rounds {
63 let mut array: [u64; 5] = [0; 5];
64
65 unroll! {
67 for x in 0..5 {
68 unroll! {
69 for y_count in 0..5 {
70 let y = y_count * 5;
71 array[x] ^= a[x + y];
72 }
73 }
74 }
75 }
76
77 unroll! {
78 for x in 0..5 {
79 unroll! {
80 for y_count in 0..5 {
81 let y = y_count * 5;
82 a[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1);
83 }
84 }
85 }
86 }
87
88 let mut last = a[1];
90 unroll! {
91 for x in 0..24 {
92 array[0] = a[$crate::PI[x]];
93 a[$crate::PI[x]] = last.rotate_left($crate::RHO[x]);
94 last = array[0];
95 }
96 }
97
98 unroll! {
100 for y_step in 0..5 {
101 let y = y_step * 5;
102
103 unroll! {
104 for x in 0..5 {
105 array[x] = a[y + x];
106 }
107 }
108
109 unroll! {
110 for x in 0..5 {
111 a[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5]));
112 }
113 }
114 }
115 };
116
117 a[0] ^= $rc[i];
119 }
120 }
121 }
122}
123
124#[cfg(feature = "k12")]
125mod keccakp;
126
127#[cfg(feature = "k12")]
128pub use keccakp::keccakp;
129
130#[cfg(any(
131 feature = "keccak",
132 feature = "shake",
133 feature = "sha3",
134 feature = "cshake",
135 feature = "kmac",
136 feature = "tuple_hash",
137 feature = "parallel_hash"
138))]
139mod keccakf;
140
141#[cfg(any(
142 feature = "keccak",
143 feature = "shake",
144 feature = "sha3",
145 feature = "cshake",
146 feature = "kmac",
147 feature = "tuple_hash",
148 feature = "parallel_hash"
149))]
150pub use keccakf::keccakf;
151
152#[cfg(feature = "k12")]
153mod k12;
154
155#[cfg(feature = "k12")]
156pub use k12::{KangarooTwelve, KangarooTwelveXof};
157
158#[cfg(feature = "keccak")]
159mod keccak;
160
161#[cfg(feature = "keccak")]
162pub use keccak::Keccak;
163
164#[cfg(feature = "shake")]
165mod shake;
166
167#[cfg(feature = "shake")]
168pub use shake::Shake;
169
170#[cfg(feature = "sha3")]
171mod sha3;
172
173#[cfg(feature = "sha3")]
174pub use sha3::Sha3;
175
176#[cfg(feature = "cshake")]
177mod cshake;
178
179#[cfg(feature = "cshake")]
180pub use cshake::CShake;
181
182#[cfg(feature = "kmac")]
183mod kmac;
184
185#[cfg(feature = "kmac")]
186pub use kmac::{Kmac, KmacXof};
187
188#[cfg(feature = "tuple_hash")]
189mod tuple_hash;
190
191#[cfg(feature = "tuple_hash")]
192pub use tuple_hash::{TupleHash, TupleHashXof};
193
194#[cfg(feature = "parallel_hash")]
195mod parallel_hash;
196
197#[cfg(feature = "parallel_hash")]
198pub use parallel_hash::{ParallelHash, ParallelHashXof};
199
200pub trait Hasher {
217 fn update(&mut self, input: &[u8]);
219
220 fn finalize(self, output: &mut [u8]);
222}
223
224pub trait IntoXof {
239 type Xof: Xof;
243
244 fn into_xof(self) -> Self::Xof;
248}
249
250pub trait Xof {
265 fn squeeze(&mut self, output: &mut [u8]);
267}
268
269struct EncodedLen {
270 offset: usize,
271 buffer: [u8; 9],
272}
273
274impl EncodedLen {
275 fn value(&self) -> &[u8] {
276 &self.buffer[self.offset..]
277 }
278}
279
280fn left_encode(len: usize) -> EncodedLen {
281 let mut buffer = [0u8; 9];
282 buffer[1..].copy_from_slice(&(len as u64).to_be_bytes());
283 let offset = buffer.iter().position(|i| *i != 0).unwrap_or(8);
284 buffer[offset - 1] = 9 - offset as u8;
285
286 EncodedLen {
287 offset: offset - 1,
288 buffer,
289 }
290}
291
292fn right_encode(len: usize) -> EncodedLen {
293 let mut buffer = [0u8; 9];
294 buffer[..8].copy_from_slice(&(len as u64).to_be_bytes());
295 let offset = buffer.iter().position(|i| *i != 0).unwrap_or(7);
296 buffer[8] = 8 - offset as u8;
297 EncodedLen { offset, buffer }
298}
299
300#[derive(Default, Clone)]
301struct Buffer([u64; WORDS]);
302
303impl Buffer {
304 fn words(&mut self) -> &mut [u64; WORDS] {
305 &mut self.0
306 }
307
308 #[cfg(target_endian = "little")]
309 #[inline]
310 fn execute<F: FnOnce(&mut [u8])>(&mut self, offset: usize, len: usize, f: F) {
311 let buffer: &mut [u8; WORDS * 8] = unsafe { core::mem::transmute(&mut self.0) };
312 f(&mut buffer[offset..][..len]);
313 }
314
315 #[cfg(target_endian = "big")]
316 #[inline]
317 fn execute<F: FnOnce(&mut [u8])>(&mut self, offset: usize, len: usize, f: F) {
318 fn swap_endianess(buffer: &mut [u64]) {
319 for item in buffer {
320 *item = item.swap_bytes();
321 }
322 }
323
324 let start = offset / 8;
325 let end = (offset + len + 7) / 8;
326 swap_endianess(&mut self.0[start..end]);
327 let buffer: &mut [u8; WORDS * 8] = unsafe { core::mem::transmute(&mut self.0) };
328 f(&mut buffer[offset..][..len]);
329 swap_endianess(&mut self.0[start..end]);
330 }
331
332 fn setout(&mut self, dst: &mut [u8], offset: usize, len: usize) {
333 self.execute(offset, len, |buffer| dst[..len].copy_from_slice(buffer));
334 }
335
336 fn xorin(&mut self, src: &[u8], offset: usize, len: usize) {
337 self.execute(offset, len, |dst| {
338 assert!(dst.len() <= src.len());
339 let len = dst.len();
340 let mut dst_ptr = dst.as_mut_ptr();
341 let mut src_ptr = src.as_ptr();
342 for _ in 0..len {
343 unsafe {
344 *dst_ptr ^= *src_ptr;
345 src_ptr = src_ptr.offset(1);
346 dst_ptr = dst_ptr.offset(1);
347 }
348 }
349 });
350 }
351
352 fn pad(&mut self, offset: usize, delim: u8, rate: usize) {
353 self.execute(offset, 1, |buff| buff[0] ^= delim);
354 self.execute(rate - 1, 1, |buff| buff[0] ^= 0x80);
355 }
356}
357
358trait Permutation {
359 fn execute(a: &mut Buffer);
360}
361
362#[derive(Clone, Copy)]
363enum Mode {
364 Absorbing,
365 Squeezing,
366}
367
368struct KeccakState<P> {
369 buffer: Buffer,
370 offset: usize,
371 rate: usize,
372 delim: u8,
373 mode: Mode,
374 permutation: core::marker::PhantomData<P>,
375}
376
377impl<P> Clone for KeccakState<P> {
378 fn clone(&self) -> Self {
379 KeccakState {
380 buffer: self.buffer.clone(),
381 offset: self.offset,
382 rate: self.rate,
383 delim: self.delim,
384 mode: self.mode,
385 permutation: core::marker::PhantomData,
386 }
387 }
388}
389
390impl<P: Permutation> KeccakState<P> {
391 fn new(rate: usize, delim: u8) -> Self {
392 assert!(rate != 0, "rate cannot be equal 0");
393 KeccakState {
394 buffer: Buffer::default(),
395 offset: 0,
396 rate,
397 delim,
398 mode: Mode::Absorbing,
399 permutation: core::marker::PhantomData,
400 }
401 }
402
403 fn keccak(&mut self) {
404 P::execute(&mut self.buffer);
405 }
406
407 fn update(&mut self, input: &[u8]) {
408 if let Mode::Squeezing = self.mode {
409 self.mode = Mode::Absorbing;
410 self.fill_block();
411 }
412
413 let mut ip = 0;
415 let mut l = input.len();
416 let mut rate = self.rate - self.offset;
417 let mut offset = self.offset;
418 while l >= rate {
419 self.buffer.xorin(&input[ip..], offset, rate);
420 self.keccak();
421 ip += rate;
422 l -= rate;
423 rate = self.rate;
424 offset = 0;
425 }
426
427 self.buffer.xorin(&input[ip..], offset, l);
428 self.offset = offset + l;
429 }
430
431 fn pad(&mut self) {
432 self.buffer.pad(self.offset, self.delim, self.rate);
433 }
434
435 fn squeeze(&mut self, output: &mut [u8]) {
436 if let Mode::Absorbing = self.mode {
437 self.mode = Mode::Squeezing;
438 self.pad();
439 self.fill_block();
440 }
441
442 let mut op = 0;
444 let mut l = output.len();
445 let mut rate = self.rate - self.offset;
446 let mut offset = self.offset;
447 while l >= rate {
448 self.buffer.setout(&mut output[op..], offset, rate);
449 self.keccak();
450 op += rate;
451 l -= rate;
452 rate = self.rate;
453 offset = 0;
454 }
455
456 self.buffer.setout(&mut output[op..], offset, l);
457 self.offset = offset + l;
458 }
459
460 fn finalize(mut self, output: &mut [u8]) {
461 self.squeeze(output);
462 }
463
464 fn fill_block(&mut self) {
465 self.keccak();
466 self.offset = 0;
467 }
468
469 fn reset(&mut self) {
470 self.buffer = Buffer::default();
471 self.offset = 0;
472 self.mode = Mode::Absorbing;
473 }
474}
475
476fn bits_to_rate(bits: usize) -> usize {
477 200 - bits / 4
478}
479
480#[cfg(test)]
481mod tests {
482 use crate::{left_encode, right_encode};
483
484 #[test]
485 fn test_left_encode() {
486 assert_eq!(left_encode(0).value(), &[1, 0]);
487 assert_eq!(left_encode(128).value(), &[1, 128]);
488 assert_eq!(left_encode(65536).value(), &[3, 1, 0, 0]);
489 assert_eq!(left_encode(4096).value(), &[2, 16, 0]);
490 assert_eq!(left_encode(54321).value(), &[2, 212, 49]);
491 }
492
493 #[test]
494 fn test_right_encode() {
495 assert_eq!(right_encode(0).value(), &[0, 1]);
496 assert_eq!(right_encode(128).value(), &[128, 1]);
497 assert_eq!(right_encode(65536).value(), &[1, 0, 0, 3]);
498 assert_eq!(right_encode(4096).value(), &[16, 0, 2]);
499 assert_eq!(right_encode(54321).value(), &[212, 49, 2]);
500 }
501}