1#![no_std]
2#![doc = include_str!("../README.md")]
3#![doc(
4 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
5 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
6)]
7#![cfg_attr(docsrs, feature(doc_cfg))]
8#![forbid(unsafe_code)]
9
10pub use digest::{self, ExtendableOutput, Update, XofReader};
11
12use core::fmt;
13use digest::{
14 CollisionResistance, ExtendableOutputReset, HashMarker, Reset,
15 common::AlgorithmName,
16 consts::{U16, U32},
17};
18
19mod consts;
20pub mod custom;
22mod node_turbo_shake;
24mod reader;
26mod turbo_shake;
28mod update;
30mod utils;
32
33pub use custom::*;
34pub use reader::KtReader;
35
36use consts::{CHUNK_SIZE_U64, FINAL_NODE_DS, ROUNDS, SINGLE_NODE_DS};
37use turbo_shake::TurboShake;
38use utils::length_encode;
39
40#[derive(Clone)]
45pub struct Kt<const RATE: usize> {
46 accum_tshk: TurboShake<RATE>,
47 node_tshk: TurboShake<RATE>,
48 consumed_len: u64,
49 keccak: keccak::Keccak,
50}
51
52impl<const RATE: usize> Default for Kt<RATE> {
53 #[inline]
54 fn default() -> Self {
55 const { assert!(matches!(RATE, 136 | 168)) }
56 Self {
57 accum_tshk: Default::default(),
58 node_tshk: Default::default(),
59 consumed_len: 0,
60 keccak: Default::default(),
61 }
62 }
63}
64
65impl<const RATE: usize> fmt::Debug for Kt<RATE> {
66 #[inline]
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
68 write!(f, "Kt{} {{ ... }}", 4 * (200 - RATE))
69 }
70}
71
72impl<const RATE: usize> AlgorithmName for Kt<RATE> {
73 #[inline]
74 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "KT{}", 4 * (200 - RATE))
76 }
77}
78
79impl<const RATE: usize> HashMarker for Kt<RATE> {}
80
81impl<const RATE: usize> Update for Kt<RATE> {
82 #[inline]
83 fn update(&mut self, data: &[u8]) {
84 let keccak = self.keccak;
85 let closure = update::Closure::<'_, RATE> { data, kt: self };
86 keccak.with_backend(closure);
87 }
88}
89
90impl<const RATE: usize> Reset for Kt<RATE> {
91 #[inline]
92 fn reset(&mut self) {
93 self.accum_tshk.reset();
94 self.node_tshk.reset();
95 self.consumed_len = 0;
96 }
97}
98
99impl<const RATE: usize> Kt<RATE> {
100 #[inline]
101 fn raw_finalize(&mut self) -> KtReader<RATE> {
102 let keccak = self.keccak;
103
104 if self.consumed_len <= CHUNK_SIZE_U64 {
107 self.accum_tshk.pad::<SINGLE_NODE_DS>();
108 } else {
109 keccak.with_p1600::<ROUNDS>(|p1600| {
110 let nodes_len = (self.consumed_len - 1) / CHUNK_SIZE_U64;
111 let partial_node_len = self.consumed_len % CHUNK_SIZE_U64;
112
113 if partial_node_len != 0 {
114 let cv_dst = &mut [0u8; 200][..200 - RATE];
116 self.node_tshk.finalize_intermediate_node(p1600, cv_dst);
117 self.accum_tshk.absorb(p1600, cv_dst);
118 }
119
120 length_encode(nodes_len, |enc_len| self.accum_tshk.absorb(p1600, enc_len));
121 self.accum_tshk.absorb(p1600, b"\xFF\xFF");
122 self.accum_tshk.pad::<FINAL_NODE_DS>();
123 });
124 };
125
126 KtReader::new(self.accum_tshk.state(), keccak)
127 }
128}
129
130impl<const RATE: usize> ExtendableOutput for Kt<RATE> {
131 type Reader = KtReader<RATE>;
132
133 #[inline]
134 fn finalize_xof(mut self) -> Self::Reader {
135 self.update(&[0x00]);
136 self.raw_finalize()
137 }
138}
139
140impl<const RATE: usize> ExtendableOutputReset for Kt<RATE> {
141 #[inline]
142 fn finalize_xof_reset(&mut self) -> Self::Reader {
143 self.update(&[0x00]);
144 let reader = self.raw_finalize();
145 self.reset();
146 reader
147 }
148}
149
150impl<const RATE: usize> Drop for Kt<RATE> {
151 fn drop(&mut self) {
152 #[cfg(feature = "zeroize")]
153 {
154 use digest::zeroize::Zeroize;
155 self.consumed_len.zeroize();
156 }
158 }
159}
160
161#[cfg(feature = "zeroize")]
162impl<const RATE: usize> digest::zeroize::ZeroizeOnDrop for Kt<RATE> {}
163
164pub type Kt128 = Kt<168>;
166pub type Kt256 = Kt<136>;
168
169pub type Kt128Reader = KtReader<168>;
171pub type Kt256Reader = KtReader<136>;
173
174impl CollisionResistance for Kt128 {
176 type CollisionResistance = U16;
177}
178
179impl CollisionResistance for Kt256 {
181 type CollisionResistance = U32;
182}