1#![no_std]
42#![deny(missing_docs)]
43
44use borsh::io;
45use borsh::io::Write;
46use borsh::{BorshDeserialize, BorshSerialize};
47const RHO: [u32; 24] = [
48 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
49];
50
51const PI: [usize; 24] = [
52 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
53];
54
55const WORDS: usize = 25;
56
57macro_rules! keccak_function {
58 ($doc: expr, $name: ident, $rounds: expr, $rc: expr) => {
59 #[doc = $doc]
60 #[allow(unused_assignments)]
61 #[allow(non_upper_case_globals)]
62 pub fn $name(a: &mut [u64; $crate::WORDS]) {
63 use crunchy::unroll;
64
65 for i in 0..$rounds {
66 let mut array: [u64; 5] = [0; 5];
67
68 unroll! {
70 for x in 0..5 {
71 unroll! {
72 for y_count in 0..5 {
73 let y = y_count * 5;
74 array[x] ^= a[x + y];
75 }
76 }
77 }
78 }
79
80 unroll! {
81 for x in 0..5 {
82 unroll! {
83 for y_count in 0..5 {
84 let y = y_count * 5;
85 a[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1);
86 }
87 }
88 }
89 }
90
91 let mut last = a[1];
93 unroll! {
94 for x in 0..24 {
95 array[0] = a[$crate::PI[x]];
96 a[$crate::PI[x]] = last.rotate_left($crate::RHO[x]);
97 last = array[0];
98 }
99 }
100
101 unroll! {
103 for y_step in 0..5 {
104 let y = y_step * 5;
105
106 unroll! {
107 for x in 0..5 {
108 array[x] = a[y + x];
109 }
110 }
111
112 unroll! {
113 for x in 0..5 {
114 a[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5]));
115 }
116 }
117 }
118 };
119
120 a[0] ^= $rc[i];
122 }
123 }
124 }
125}
126
127#[cfg(feature = "k12")]
128mod keccakp;
129
130#[cfg(feature = "k12")]
131pub use keccakp::keccakp;
132
133#[cfg(any(
134 feature = "keccak",
135 feature = "shake",
136 feature = "sha3",
137 feature = "cshake",
138 feature = "kmac",
139 feature = "tuple_hash",
140 feature = "parallel_hash"
141))]
142mod keccakf;
143
144#[cfg(any(
145 feature = "keccak",
146 feature = "shake",
147 feature = "sha3",
148 feature = "cshake",
149 feature = "kmac",
150 feature = "tuple_hash",
151 feature = "parallel_hash"
152))]
153pub use keccakf::keccakf;
154
155#[cfg(feature = "k12")]
156mod k12;
157
158#[cfg(feature = "k12")]
159pub use k12::{KangarooTwelve, KangarooTwelveXof};
160
161#[cfg(feature = "keccak")]
162mod keccak;
163
164#[cfg(feature = "keccak")]
165pub use keccak::Keccak;
166
167#[cfg(feature = "shake")]
168mod shake;
169
170#[cfg(feature = "shake")]
171pub use shake::Shake;
172
173#[cfg(feature = "sha3")]
174mod sha3;
175
176#[cfg(feature = "sha3")]
177pub use sha3::Sha3;
178
179#[cfg(feature = "cshake")]
180mod cshake;
181
182#[cfg(feature = "cshake")]
183pub use cshake::CShake;
184
185#[cfg(feature = "kmac")]
186mod kmac;
187
188#[cfg(feature = "kmac")]
189pub use kmac::{Kmac, KmacXof};
190
191#[cfg(feature = "tuple_hash")]
192mod tuple_hash;
193
194#[cfg(feature = "tuple_hash")]
195pub use tuple_hash::{TupleHash, TupleHashXof};
196
197#[cfg(feature = "parallel_hash")]
198mod parallel_hash;
199
200#[cfg(feature = "parallel_hash")]
201pub use parallel_hash::{ParallelHash, ParallelHashXof};
202
203#[cfg(test)]
204use quickcheck::{Arbitrary, Gen};
205
206pub trait Hasher {
223 fn update(&mut self, input: &[u8]);
225
226 fn finalize(self, output: &mut [u8]);
228}
229
230pub trait IntoXof {
245 type Xof: Xof;
249
250 fn into_xof(self) -> Self::Xof;
254}
255
256pub trait Xof {
271 fn squeeze(&mut self, output: &mut [u8]);
273}
274
275struct EncodedLen {
276 offset: usize,
277 buffer: [u8; 9],
278}
279
280impl EncodedLen {
281 fn value(&self) -> &[u8] {
282 &self.buffer[self.offset..]
283 }
284}
285
286fn left_encode(len: usize) -> EncodedLen {
287 let mut buffer = [0u8; 9];
288 buffer[1..].copy_from_slice(&(len as u64).to_be_bytes());
289 let offset = buffer.iter().position(|i| *i != 0).unwrap_or(8);
290 buffer[offset - 1] = 9 - offset as u8;
291
292 EncodedLen {
293 offset: offset - 1,
294 buffer,
295 }
296}
297
298fn right_encode(len: usize) -> EncodedLen {
299 let mut buffer = [0u8; 9];
300 buffer[..8].copy_from_slice(&(len as u64).to_be_bytes());
301 let offset = buffer.iter().position(|i| *i != 0).unwrap_or(7);
302 buffer[8] = 8 - offset as u8;
303 EncodedLen { offset, buffer }
304}
305
306#[derive(Default, Debug, Clone)]
308pub struct Buffer([u64; WORDS]);
309
310impl Buffer {
311 fn words(&mut self) -> &mut [u64; WORDS] {
312 &mut self.0
313 }
314
315 #[cfg(target_endian = "little")]
316 #[inline]
317 fn execute<F: FnOnce(&mut [u8])>(&mut self, offset: usize, len: usize, f: F) {
318 let buffer: &mut [u8; WORDS * 8] = unsafe { core::mem::transmute(&mut self.0) };
319 f(&mut buffer[offset..][..len]);
320 }
321
322 #[cfg(target_endian = "big")]
323 #[inline]
324 fn execute<F: FnOnce(&mut [u8])>(&mut self, offset: usize, len: usize, f: F) {
325 fn swap_endianess(buffer: &mut [u64]) {
326 for item in buffer {
327 *item = item.swap_bytes();
328 }
329 }
330
331 let start = offset / 8;
332 let end = (offset + len + 7) / 8;
333 swap_endianess(&mut self.0[start..end]);
334 let buffer: &mut [u8; WORDS * 8] = unsafe { core::mem::transmute(&mut self.0) };
335 f(&mut buffer[offset..][..len]);
336 swap_endianess(&mut self.0[start..end]);
337 }
338
339 fn setout(&mut self, dst: &mut [u8], offset: usize, len: usize) {
340 self.execute(offset, len, |buffer| dst[..len].copy_from_slice(buffer));
341 }
342
343 fn xorin(&mut self, src: &[u8], offset: usize, len: usize) {
344 self.execute(offset, len, |dst| {
345 assert!(dst.len() <= src.len());
346 let len = dst.len();
347 let mut dst_ptr = dst.as_mut_ptr();
348 let mut src_ptr = src.as_ptr();
349 for _ in 0..len {
350 unsafe {
351 *dst_ptr ^= *src_ptr;
352 src_ptr = src_ptr.offset(1);
353 dst_ptr = dst_ptr.offset(1);
354 }
355 }
356 });
357 }
358
359 fn pad(&mut self, offset: usize, delim: u8, rate: usize) {
360 self.execute(offset, 1, |buff| buff[0] ^= delim);
361 self.execute(rate - 1, 1, |buff| buff[0] ^= 0x80);
362 }
363}
364
365#[cfg(test)]
366impl Arbitrary for Buffer {
367 fn arbitrary(g: &mut Gen) -> Self {
368 let mut buf = [0u64; WORDS];
369 for i in 0..WORDS {
370 buf[i] = u64::arbitrary(g);
371 }
372 Buffer(buf)
373 }
374}
375
376impl BorshSerialize for Buffer {
377 fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
378 for word in self.0 {
379 BorshSerialize::serialize(&word, writer)?;
380 }
381 Ok(())
382 }
383}
384
385impl BorshDeserialize for Buffer {
386 fn deserialize_reader<R>(reader: &mut R) -> Result<Self, io::Error>
387 where
388 R: io::Read,
389 {
390 let mut buf = [0u64; WORDS];
391 for i in 0..WORDS {
392 buf[i] = BorshDeserialize::deserialize_reader(reader)?;
393 }
394 Ok(Self(buf))
395 }
396}
397
398trait Permutation {
399 fn execute(a: &mut Buffer);
400}
401
402#[derive(Clone, Debug, Copy, BorshSerialize, BorshDeserialize)]
404#[borsh(use_discriminant = true)]
405#[repr(u8)]
406pub enum Mode {
407 Absorbing = 1u8,
409 Squeezing = 2u8,
411}
412
413#[derive(Debug)]
414struct KeccakState<P> {
415 buffer: Buffer,
416 offset: u8,
417 rate: u8,
418 delim: u8,
419 mode: Mode,
420 permutation: core::marker::PhantomData<P>,
421}
422
423impl<P> BorshSerialize for KeccakState<P> {
424 fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
425 BorshSerialize::serialize(&self.buffer, writer)?;
426 BorshSerialize::serialize(&self.offset, writer)?;
427 BorshSerialize::serialize(&self.rate, writer)?;
428 BorshSerialize::serialize(&self.mode, writer)?;
429 Ok(())
430 }
431}
432
433impl<P> BorshDeserialize for KeccakState<P> {
434 fn deserialize_reader<R>(reader: &mut R) -> Result<Self, io::Error>
435 where
436 R: io::Read,
437 {
438 let buffer = BorshDeserialize::deserialize_reader(reader)?;
439 let offset = BorshDeserialize::deserialize_reader(reader)?;
440 let rate = BorshDeserialize::deserialize_reader(reader)?;
441 let mode = BorshDeserialize::deserialize_reader(reader)?;
442 Ok(Self {
443 buffer,
444 offset,
445 rate,
446 delim: 0x01,
447 mode,
448 permutation: core::marker::PhantomData,
449 })
450 }
451}
452
453impl<P> Clone for KeccakState<P> {
454 fn clone(&self) -> Self {
455 KeccakState {
456 buffer: self.buffer.clone(),
457 offset: self.offset,
458 rate: self.rate,
459 delim: self.delim,
460 mode: self.mode,
461 permutation: core::marker::PhantomData,
462 }
463 }
464}
465
466impl<P: Permutation> KeccakState<P> {
467 fn new(rate: u8, delim: u8) -> Self {
468 assert!(rate != 0, "rate cannot be equal 0");
469 KeccakState {
470 buffer: Buffer::default(),
471 offset: 0,
472 rate,
473 delim,
474 mode: Mode::Absorbing,
475 permutation: core::marker::PhantomData,
476 }
477 }
478 #[cfg(test)]
479 pub fn new_with(buffer: Buffer, offset: u8, rate: u8, delim: u8, mode: Mode) -> Self {
480 KeccakState {
481 buffer,
482 offset,
483 rate,
484 delim,
485 mode,
486 permutation: core::marker::PhantomData,
487 }
488 }
489
490 fn keccak(&mut self) {
491 P::execute(&mut self.buffer);
492 }
493
494 fn update(&mut self, input: &[u8]) {
495 if self.rate >= 200 || self.rate <= 1 || self.rate <= self.offset {
496 return;
497 }
498 if let Mode::Squeezing = self.mode {
499 self.mode = Mode::Absorbing;
500 self.fill_block();
501 }
502 let mut ip = 0;
504 let mut l = input.len();
505 let mut rate = (self.rate - self.offset) as usize;
506 let mut offset = self.offset as usize;
507 while l >= rate as usize {
508 self.buffer.xorin(&input[ip..], offset, rate);
509 self.keccak();
510 ip += rate;
511 l -= rate;
512 rate = self.rate as usize;
513 offset = 0;
514 }
515
516 self.buffer.xorin(&input[ip..], offset, l);
517 self.offset = (offset + l) as u8;
519 }
520
521 fn pad(&mut self) {
522 self.buffer
523 .pad(self.offset as usize, self.delim, self.rate as usize);
524 }
525
526 fn squeeze(&mut self, output: &mut [u8]) {
527 if self.rate >= 200 || self.rate <= 1 || self.rate <= self.offset {
528 return;
529 }
530 if let Mode::Absorbing = self.mode {
531 self.mode = Mode::Squeezing;
532 self.pad();
533 self.fill_block();
534 }
535
536 let mut op = 0;
538 let mut l = output.len();
539 let mut rate = (self.rate - self.offset) as usize;
540 let mut offset = self.offset as usize;
541 while l >= rate {
542 self.buffer.setout(&mut output[op..], offset, rate);
543 self.keccak();
544 op += rate;
545 l -= rate;
546 rate = self.rate as usize;
547 offset = 0;
548 }
549
550 self.buffer.setout(&mut output[op..], offset, l);
551 self.offset = (offset + l) as u8;
552 }
553
554 fn finalize(mut self, output: &mut [u8]) {
555 self.squeeze(output);
556 }
557
558 fn fill_block(&mut self) {
559 self.keccak();
560 self.offset = 0;
561 }
562
563 fn reset(&mut self) {
564 self.buffer = Buffer::default();
565 self.offset = 0;
566 self.mode = Mode::Absorbing;
567 }
568}
569
570fn bits_to_rate(bits: u16) -> u8 {
571 (200u16.saturating_sub(bits / 4)) as u8
573}
574
575#[cfg(test)]
576mod tests {
577 use crate::{left_encode, right_encode};
578
579 #[test]
580 fn test_left_encode() {
581 assert_eq!(left_encode(0).value(), &[1, 0]);
582 assert_eq!(left_encode(128).value(), &[1, 128]);
583 assert_eq!(left_encode(65536).value(), &[3, 1, 0, 0]);
584 assert_eq!(left_encode(4096).value(), &[2, 16, 0]);
585 assert_eq!(left_encode(54321).value(), &[2, 212, 49]);
586 }
587
588 #[test]
589 fn test_right_encode() {
590 assert_eq!(right_encode(0).value(), &[0, 1]);
591 assert_eq!(right_encode(128).value(), &[128, 1]);
592 assert_eq!(right_encode(65536).value(), &[1, 0, 0, 3]);
593 assert_eq!(right_encode(4096).value(), &[16, 0, 2]);
594 assert_eq!(right_encode(54321).value(), &[212, 49, 2]);
595 }
596
597 mod quicktest {
598 use crate::{Buffer, Hasher, Keccak, Mode};
599 use quickcheck::{quickcheck, Arbitrary, Gen};
600
601 #[derive(Clone, Debug)]
602
603 struct Data([u8; 25]);
604
605 impl Data {
606 pub fn as_slice(&self) -> &[u8] {
607 &self.0
608 }
609 }
610 impl Arbitrary for Data {
611 fn arbitrary(g: &mut Gen) -> Data {
612 let mut buf = [0u8; 25];
613 for i in 0..25 {
614 buf[i] = u8::arbitrary(g);
615 }
616 Data(buf)
617 }
618 }
619 #[test]
620 fn test_ser_deserialize() {
621 fn test_hashing_a(buffer: Buffer, offset: u8, rate: u8, hash: Data) -> bool {
622 let mode = Mode::Absorbing;
623 let mut keccak = Keccak::new_with(buffer, offset, rate, mode);
624 keccak.update(hash.as_slice());
625 let mut out: [u8; 32] = [0; 32];
626 keccak.finalize(&mut out);
627 true
628 }
629
630 fn test_hashing_s(buffer: Buffer, offset: u8, rate: u8, hash: Data) -> bool {
631 let mode = Mode::Squeezing;
632 let mut keccak = Keccak::new_with(buffer, offset, rate, mode);
633 keccak.update(hash.as_slice());
634 let mut out: [u8; 32] = [0; 32];
635 keccak.finalize(&mut out);
636 true
637 }
638 quickcheck(test_hashing_a as fn(Buffer, u8, u8, Data) -> bool);
639 quickcheck(test_hashing_s as fn(Buffer, u8, u8, Data) -> bool);
640 }
641 }
642}