1#![no_std]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6#![doc = include_str!("../README.md")]
7#![warn(missing_docs)]
8
9use core::{fmt, marker::PhantomData};
34
35use ascon_core::State;
36#[cfg(feature = "zeroize")]
37use digest::zeroize::ZeroizeOnDrop;
38pub use digest::{self, Digest, ExtendableOutput, Reset, Update, XofReader};
39use digest::{
40 CollisionResistance, HashMarker, Output, OutputSizeUser,
41 block_api::{
42 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, Eager, ExtendableOutputCore,
43 FixedOutputCore, UpdateCore, XofReaderCore,
44 },
45 common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
46 consts::{U8, U16, U32, U40},
47};
48
49#[inline(always)]
51const fn pad(n: usize) -> u64 {
52 0x01_u64 << (8 * n)
53}
54
55trait HashParameters {
59 const IV0: u64;
61 const IV1: u64;
63 const IV2: u64;
65 const IV3: u64;
67 const IV4: u64;
69}
70
71#[derive(Clone, Debug)]
73struct Parameters;
74
75impl HashParameters for Parameters {
76 const IV0: u64 = 0x9b1e5494e934d681;
77 const IV1: u64 = 0x4bc3a01e333751d2;
78 const IV2: u64 = 0xae65396c6b34b81a;
79 const IV3: u64 = 0x3c7fd4a4d56a4db3;
80 const IV4: u64 = 0x1a5c464906c5976d;
81}
82
83#[derive(Clone, Debug)]
85struct ParametersXof;
86
87impl HashParameters for ParametersXof {
88 const IV0: u64 = 0xda82ce768d9447eb;
89 const IV1: u64 = 0xcc7ce6c75f1ef969;
90 const IV2: u64 = 0xe7508fd780085631;
91 const IV3: u64 = 0x0ee0ea53416b58cc;
92 const IV4: u64 = 0xe0547524db6f0bde;
93}
94
95#[derive(Clone, Debug)]
96struct HashCore<P: HashParameters> {
97 state: State,
98 phantom: PhantomData<P>,
99}
100
101#[cfg(feature = "zeroize")]
102impl<P: HashParameters> ZeroizeOnDrop for HashCore<P> {}
103
104impl<P: HashParameters> HashCore<P> {
105 fn absorb_block(&mut self, block: &[u8; 8]) {
106 self.state[0] ^= u64::from_le_bytes(*block);
107 self.permute_state();
108 }
109
110 fn absorb_last_block(&mut self, block: &[u8]) {
111 debug_assert!(block.len() < 8);
112
113 let len = block.len();
114 if len > 0 {
115 let mut tmp = [0u8; 8];
116 tmp[0..len].copy_from_slice(block);
117 self.state[0] ^= u64::from_le_bytes(tmp);
118 }
119 self.state[0] ^= pad(len);
120 self.state.permute_12();
121 }
122
123 fn squeeze(&mut self, mut block: &mut [u8]) {
125 debug_assert_eq!(block.len() % 8, 0);
126
127 while block.len() > 8 {
128 block[..8].copy_from_slice(&u64::to_le_bytes(self.state[0]));
129 self.permute_state();
130 block = &mut block[8..];
131 }
132 block[..8].copy_from_slice(&u64::to_le_bytes(self.state[0]));
133 }
134
135 fn squeeze_block(&mut self) -> [u8; 8] {
137 let ret = u64::to_le_bytes(self.state[0]);
138 self.permute_state();
139 ret
140 }
141
142 #[inline(always)]
143 fn permute_state(&mut self) {
144 self.state.permute_12();
145 }
146}
147
148impl<P: HashParameters> Default for HashCore<P> {
149 fn default() -> Self {
150 Self {
151 state: State::new(P::IV0, P::IV1, P::IV2, P::IV3, P::IV4),
152 phantom: PhantomData,
153 }
154 }
155}
156
157#[derive(Clone, Debug, Default)]
159pub struct AsconCore {
160 state: HashCore<Parameters>,
161}
162
163#[cfg(feature = "zeroize")]
164impl ZeroizeOnDrop for AsconCore {}
165
166impl HashMarker for AsconCore {}
167
168impl BlockSizeUser for AsconCore {
169 type BlockSize = U8;
170}
171
172impl BufferKindUser for AsconCore {
173 type BufferKind = Eager;
174}
175
176impl OutputSizeUser for AsconCore {
177 type OutputSize = U32;
178}
179
180impl UpdateCore for AsconCore {
181 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
182 for block in blocks {
183 self.state.absorb_block(block.as_ref());
184 }
185 }
186}
187
188impl FixedOutputCore for AsconCore {
189 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
190 debug_assert!(buffer.get_pos() < 8);
191 self.state
192 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
193 self.state.squeeze(out);
194 }
195}
196
197impl Reset for AsconCore {
198 fn reset(&mut self) {
199 *self = Default::default();
200 }
201}
202
203impl AlgorithmName for AsconCore {
204 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 f.write_str("Ascon-Hash256")
206 }
207}
208
209impl SerializableState for AsconCore {
210 type SerializedStateSize = U40;
211
212 fn serialize(&self) -> SerializedState<Self> {
213 self.state.state.as_bytes().into()
214 }
215
216 fn deserialize(
217 serialized_state: &SerializedState<Self>,
218 ) -> Result<Self, DeserializeStateError> {
219 let state = State::from(&serialized_state.0);
220 Ok(Self {
221 state: HashCore {
222 state,
223 phantom: PhantomData,
224 },
225 })
226 }
227}
228
229#[derive(Clone, Debug, Default)]
231pub struct AsconXofCore {
232 state: HashCore<ParametersXof>,
233}
234
235#[cfg(feature = "zeroize")]
236impl ZeroizeOnDrop for AsconXofCore {}
237
238impl HashMarker for AsconXofCore {}
239
240impl BlockSizeUser for AsconXofCore {
241 type BlockSize = U8;
242}
243
244impl BufferKindUser for AsconXofCore {
245 type BufferKind = Eager;
246}
247
248impl UpdateCore for AsconXofCore {
249 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
250 for block in blocks {
251 self.state.absorb_block(block.as_ref());
252 }
253 }
254}
255
256#[derive(Clone, Debug)]
258pub struct AsconXofReaderCore {
259 hasher: HashCore<ParametersXof>,
260}
261
262#[cfg(feature = "zeroize")]
263impl ZeroizeOnDrop for AsconXofReaderCore {}
264
265impl BlockSizeUser for AsconXofReaderCore {
266 type BlockSize = U8;
267}
268
269impl XofReaderCore for AsconXofReaderCore {
270 fn read_block(&mut self) -> Block<Self> {
271 self.hasher.squeeze_block().into()
272 }
273}
274
275impl ExtendableOutputCore for AsconXofCore {
276 type ReaderCore = AsconXofReaderCore;
277
278 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
279 debug_assert!(buffer.get_pos() < 8);
280 self.state
281 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
282 Self::ReaderCore {
283 hasher: self.state.clone(),
284 }
285 }
286}
287
288impl Reset for AsconXofCore {
289 fn reset(&mut self) {
290 *self = Default::default();
291 }
292}
293
294impl AlgorithmName for AsconXofCore {
295 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 f.write_str("Ascon-XOF128")
297 }
298}
299
300impl SerializableState for AsconXofCore {
301 type SerializedStateSize = U40;
302
303 fn serialize(&self) -> SerializedState<Self> {
304 self.state.state.as_bytes().into()
305 }
306
307 fn deserialize(
308 serialized_state: &SerializedState<Self>,
309 ) -> Result<Self, DeserializeStateError> {
310 let state = State::from(&serialized_state.0);
311 Ok(Self {
312 state: HashCore {
313 state,
314 phantom: PhantomData,
315 },
316 })
317 }
318}
319
320digest::buffer_fixed!(
321 pub struct AsconHash256(AsconCore);
323 impl: FixedHashTraits;
324);
325
326digest::buffer_xof!(
327 pub struct AsconXof128(AsconXofCore);
329 impl: XofHasherTraits;
330 pub struct AsconXof128Reader(AsconXofReaderCore);
332 impl: XofReaderTraits;
333);
334
335impl CollisionResistance for AsconXof128 {
336 type CollisionResistance = U16;
338}