1#![no_std]
5#![cfg_attr(docsrs, feature(doc_auto_cfg))]
6#![doc = include_str!("../README.md")]
7#![doc(
8 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
9 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
10)]
11#![warn(missing_docs)]
12
13use core::marker::PhantomData;
38
39use ascon::{pad, State};
40pub use digest::{self, Digest, ExtendableOutput, Reset, Update, XofReader};
41use digest::{
42 block_buffer::Eager,
43 consts::{U32, U8},
44 core_api::{
45 AlgorithmName, Block, Buffer, BufferKindUser, CoreWrapper, ExtendableOutputCore,
46 FixedOutputCore, UpdateCore, XofReaderCore, XofReaderCoreWrapper,
47 },
48 crypto_common::BlockSizeUser,
49 HashMarker, Output, OutputSizeUser,
50};
51
52trait HashParameters {
54 const ROUNDS: usize;
56 const IV0: u64;
58 const IV1: u64;
60 const IV2: u64;
62 const IV3: u64;
64 const IV4: u64;
66}
67
68#[derive(Clone, Debug)]
70struct Parameters;
71
72impl HashParameters for Parameters {
73 const ROUNDS: usize = 12;
74 const IV0: u64 = 0xee9398aadb67f03d;
75 const IV1: u64 = 0x8bb21831c60f1002;
76 const IV2: u64 = 0xb48a92db98d5da62;
77 const IV3: u64 = 0x43189921b8f8e3e8;
78 const IV4: u64 = 0x348fa5c9d525e140;
79}
80
81#[derive(Clone, Debug)]
83struct ParametersA;
84
85impl HashParameters for ParametersA {
86 const ROUNDS: usize = 8;
87 const IV0: u64 = 0x01470194fc6528a6;
88 const IV1: u64 = 0x738ec38ac0adffa7;
89 const IV2: u64 = 0x2ec8e3296c76384c;
90 const IV3: u64 = 0xd6f6a54d7f52377d;
91 const IV4: u64 = 0xa13c42a223be8d87;
92}
93
94#[derive(Clone, Debug)]
95struct ParametersXof;
96
97impl HashParameters for ParametersXof {
98 const ROUNDS: usize = 12;
99 const IV0: u64 = 0xb57e273b814cd416;
100 const IV1: u64 = 0x2b51042562ae2420;
101 const IV2: u64 = 0x66a3a7768ddf2218;
102 const IV3: u64 = 0x5aad0a7a8153650c;
103 const IV4: u64 = 0x4f3e0e32539493b6;
104}
105
106#[derive(Clone, Debug)]
107struct ParametersAXof;
108
109impl HashParameters for ParametersAXof {
110 const ROUNDS: usize = 8;
111 const IV0: u64 = 0x44906568b77b9832;
112 const IV1: u64 = 0xcd8d6cae53455532;
113 const IV2: u64 = 0xf7b5212756422129;
114 const IV3: u64 = 0x246885e1de0d225b;
115 const IV4: u64 = 0xa8cb5ce33449973f;
116}
117
118#[derive(Clone, Debug)]
119struct HashCore<P: HashParameters> {
120 state: State,
121 phantom: PhantomData<P>,
122}
123
124impl<P: HashParameters> HashCore<P> {
125 fn absorb_block(&mut self, block: &[u8; 8]) {
126 self.state[0] ^= u64::from_be_bytes(*block);
127 self.permute_state();
128 }
129
130 fn absorb_last_block(&mut self, block: &[u8]) {
131 debug_assert!(block.len() < 8);
132
133 let len = block.len();
134 if len > 0 {
135 let mut tmp = [0u8; 8];
136 tmp[0..len].copy_from_slice(block);
137 self.state[0] ^= u64::from_be_bytes(tmp);
138 }
139 self.state[0] ^= pad(len);
140 self.state.permute_12();
141 }
142
143 fn squeeze(&mut self, mut block: &mut [u8]) {
145 debug_assert_eq!(block.len() % 8, 0);
146
147 while block.len() > 8 {
148 block[..8].copy_from_slice(&u64::to_be_bytes(self.state[0]));
149 self.permute_state();
150 block = &mut block[8..];
151 }
152 block[..8].copy_from_slice(&u64::to_be_bytes(self.state[0]));
153 }
154
155 fn squeeze_block(&mut self) -> [u8; 8] {
157 let ret = u64::to_be_bytes(self.state[0]);
158 self.permute_state();
159 ret
160 }
161
162 #[inline(always)]
163 fn permute_state(&mut self) {
164 if P::ROUNDS == 12 {
165 self.state.permute_12();
166 } else if P::ROUNDS == 8 {
167 self.state.permute_8();
168 } else if P::ROUNDS == 6 {
169 self.state.permute_6();
170 }
171 }
172}
173
174impl<P: HashParameters> Default for HashCore<P> {
175 fn default() -> Self {
176 Self {
177 state: State::new(P::IV0, P::IV1, P::IV2, P::IV3, P::IV4),
178 phantom: PhantomData,
179 }
180 }
181}
182
183#[derive(Clone, Debug, Default)]
185pub struct AsconCore {
186 state: HashCore<Parameters>,
187}
188
189impl HashMarker for AsconCore {}
190
191impl BlockSizeUser for AsconCore {
192 type BlockSize = U8;
193}
194
195impl BufferKindUser for AsconCore {
196 type BufferKind = Eager;
197}
198
199impl OutputSizeUser for AsconCore {
200 type OutputSize = U32;
201}
202
203impl UpdateCore for AsconCore {
204 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
205 for block in blocks {
206 self.state.absorb_block(block.as_ref());
207 }
208 }
209}
210
211impl FixedOutputCore for AsconCore {
212 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
213 debug_assert!(buffer.get_pos() < 8);
214 self.state
215 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
216 self.state.squeeze(out);
217 }
218}
219
220impl Reset for AsconCore {
221 fn reset(&mut self) {
222 *self = Default::default();
223 }
224}
225
226impl AlgorithmName for AsconCore {
227 fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
228 f.write_str("AsconHash")
229 }
230}
231
232#[derive(Clone, Debug, Default)]
234pub struct AsconACore {
235 state: HashCore<ParametersA>,
236}
237
238impl HashMarker for AsconACore {}
239
240impl BlockSizeUser for AsconACore {
241 type BlockSize = U8;
242}
243
244impl BufferKindUser for AsconACore {
245 type BufferKind = Eager;
246}
247
248impl OutputSizeUser for AsconACore {
249 type OutputSize = U32;
250}
251
252impl UpdateCore for AsconACore {
253 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
254 for block in blocks {
255 self.state.absorb_block(block.as_ref());
256 }
257 }
258}
259
260impl FixedOutputCore for AsconACore {
261 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
262 debug_assert!(buffer.get_pos() < 8);
263 self.state
264 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
265 self.state.squeeze(out);
266 }
267}
268
269impl Reset for AsconACore {
270 fn reset(&mut self) {
271 *self = Default::default();
272 }
273}
274
275impl AlgorithmName for AsconACore {
276 fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
277 f.write_str("AsconAHash")
278 }
279}
280
281#[derive(Clone, Debug, Default)]
283pub struct AsconXofCore {
284 state: HashCore<ParametersXof>,
285}
286
287impl HashMarker for AsconXofCore {}
288
289impl BlockSizeUser for AsconXofCore {
290 type BlockSize = U8;
291}
292
293impl BufferKindUser for AsconXofCore {
294 type BufferKind = Eager;
295}
296
297impl UpdateCore for AsconXofCore {
298 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
299 for block in blocks {
300 self.state.absorb_block(block.as_ref());
301 }
302 }
303}
304
305#[derive(Clone, Debug)]
307pub struct AsconXofReaderCore {
308 hasher: HashCore<ParametersXof>,
309}
310
311impl BlockSizeUser for AsconXofReaderCore {
312 type BlockSize = U8;
313}
314
315impl XofReaderCore for AsconXofReaderCore {
316 fn read_block(&mut self) -> Block<Self> {
317 self.hasher.squeeze_block().into()
318 }
319}
320
321impl ExtendableOutputCore for AsconXofCore {
322 type ReaderCore = AsconXofReaderCore;
323
324 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
325 debug_assert!(buffer.get_pos() < 8);
326 self.state
327 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
328 Self::ReaderCore {
329 hasher: self.state.clone(),
330 }
331 }
332}
333
334impl Reset for AsconXofCore {
335 fn reset(&mut self) {
336 *self = Default::default();
337 }
338}
339
340impl AlgorithmName for AsconXofCore {
341 fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
342 f.write_str("AsconXOF")
343 }
344}
345
346#[derive(Clone, Debug, Default)]
348pub struct AsconAXofCore {
349 state: HashCore<ParametersAXof>,
350}
351
352impl HashMarker for AsconAXofCore {}
353
354impl BlockSizeUser for AsconAXofCore {
355 type BlockSize = U8;
356}
357
358impl BufferKindUser for AsconAXofCore {
359 type BufferKind = Eager;
360}
361
362impl UpdateCore for AsconAXofCore {
363 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
364 for block in blocks {
365 self.state.absorb_block(block.as_ref());
366 }
367 }
368}
369
370#[derive(Clone, Debug)]
372pub struct AsconAXofReaderCore {
373 hasher: HashCore<ParametersAXof>,
374}
375
376impl BlockSizeUser for AsconAXofReaderCore {
377 type BlockSize = U8;
378}
379
380impl XofReaderCore for AsconAXofReaderCore {
381 fn read_block(&mut self) -> Block<Self> {
382 self.hasher.squeeze_block().into()
383 }
384}
385
386impl ExtendableOutputCore for AsconAXofCore {
387 type ReaderCore = AsconAXofReaderCore;
388
389 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
390 debug_assert!(buffer.get_pos() < 8);
391 self.state
392 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
393 Self::ReaderCore {
394 hasher: self.state.clone(),
395 }
396 }
397}
398
399impl Reset for AsconAXofCore {
400 fn reset(&mut self) {
401 *self = Default::default();
402 }
403}
404
405impl AlgorithmName for AsconAXofCore {
406 fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
407 f.write_str("AsconAXOF")
408 }
409}
410
411pub type AsconHash = CoreWrapper<AsconCore>;
422pub type AsconAHash = CoreWrapper<AsconACore>;
433pub type AsconXof = CoreWrapper<AsconXofCore>;
446pub type AsconAXofReader = XofReaderCoreWrapper<AsconAXofReaderCore>;
448pub type AsconAXof = CoreWrapper<AsconAXofCore>;
461pub type AsconXofReader = XofReaderCoreWrapper<AsconAXofReaderCore>;