1#![no_std]
5#![cfg_attr(docsrs, feature(doc_auto_cfg))]
6#![doc = include_str!("../README.md")]
7#![warn(missing_docs)]
8
9use core::{fmt, marker::PhantomData};
34
35use ascon_core::State;
36pub use digest::{self, Digest, ExtendableOutput, Reset, Update, XofReader};
37use digest::{
38 HashMarker, Output, OutputSizeUser,
39 block_buffer::Eager,
40 consts::{U8, U32},
41 core_api::{
42 AlgorithmName, Block, Buffer, BufferKindUser, CoreWrapper, ExtendableOutputCore,
43 FixedOutputCore, UpdateCore, XofReaderCore, XofReaderCoreWrapper,
44 },
45 crypto_common::BlockSizeUser,
46};
47
48#[inline(always)]
50const fn pad(n: usize) -> u64 {
51 0x01_u64 << (8 * n)
52}
53
54trait HashParameters {
58 const IV0: u64;
60 const IV1: u64;
62 const IV2: u64;
64 const IV3: u64;
66 const IV4: u64;
68}
69
70#[derive(Clone, Debug)]
72struct Parameters;
73
74impl HashParameters for Parameters {
75 const IV0: u64 = 0x9b1e5494e934d681;
76 const IV1: u64 = 0x4bc3a01e333751d2;
77 const IV2: u64 = 0xae65396c6b34b81a;
78 const IV3: u64 = 0x3c7fd4a4d56a4db3;
79 const IV4: u64 = 0x1a5c464906c5976d;
80}
81
82#[derive(Clone, Debug)]
84struct ParametersXof;
85
86impl HashParameters for ParametersXof {
87 const IV0: u64 = 0xda82ce768d9447eb;
88 const IV1: u64 = 0xcc7ce6c75f1ef969;
89 const IV2: u64 = 0xe7508fd780085631;
90 const IV3: u64 = 0x0ee0ea53416b58cc;
91 const IV4: u64 = 0xe0547524db6f0bde;
92}
93
94#[derive(Clone, Debug)]
95struct HashCore<P: HashParameters> {
96 state: State,
97 phantom: PhantomData<P>,
98}
99
100impl<P: HashParameters> HashCore<P> {
101 fn absorb_block(&mut self, block: &[u8; 8]) {
102 self.state[0] ^= u64::from_le_bytes(*block);
103 self.permute_state();
104 }
105
106 fn absorb_last_block(&mut self, block: &[u8]) {
107 debug_assert!(block.len() < 8);
108
109 let len = block.len();
110 if len > 0 {
111 let mut tmp = [0u8; 8];
112 tmp[0..len].copy_from_slice(block);
113 self.state[0] ^= u64::from_le_bytes(tmp);
114 }
115 self.state[0] ^= pad(len);
116 self.state.permute_12();
117 }
118
119 fn squeeze(&mut self, mut block: &mut [u8]) {
121 debug_assert_eq!(block.len() % 8, 0);
122
123 while block.len() > 8 {
124 block[..8].copy_from_slice(&u64::to_le_bytes(self.state[0]));
125 self.permute_state();
126 block = &mut block[8..];
127 }
128 block[..8].copy_from_slice(&u64::to_le_bytes(self.state[0]));
129 }
130
131 fn squeeze_block(&mut self) -> [u8; 8] {
133 let ret = u64::to_le_bytes(self.state[0]);
134 self.permute_state();
135 ret
136 }
137
138 #[inline(always)]
139 fn permute_state(&mut self) {
140 self.state.permute_12();
141 }
142}
143
144impl<P: HashParameters> Default for HashCore<P> {
145 fn default() -> Self {
146 Self {
147 state: State::new(P::IV0, P::IV1, P::IV2, P::IV3, P::IV4),
148 phantom: PhantomData,
149 }
150 }
151}
152
153#[derive(Clone, Debug, Default)]
155pub struct AsconCore {
156 state: HashCore<Parameters>,
157}
158
159impl HashMarker for AsconCore {}
160
161impl BlockSizeUser for AsconCore {
162 type BlockSize = U8;
163}
164
165impl BufferKindUser for AsconCore {
166 type BufferKind = Eager;
167}
168
169impl OutputSizeUser for AsconCore {
170 type OutputSize = U32;
171}
172
173impl UpdateCore for AsconCore {
174 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
175 for block in blocks {
176 self.state.absorb_block(block.as_ref());
177 }
178 }
179}
180
181impl FixedOutputCore for AsconCore {
182 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
183 debug_assert!(buffer.get_pos() < 8);
184 self.state
185 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
186 self.state.squeeze(out);
187 }
188}
189
190impl Reset for AsconCore {
191 fn reset(&mut self) {
192 *self = Default::default();
193 }
194}
195
196impl AlgorithmName for AsconCore {
197 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 f.write_str("Ascon-Hash256")
199 }
200}
201
202#[derive(Clone, Debug, Default)]
204pub struct AsconXofCore {
205 state: HashCore<ParametersXof>,
206}
207
208impl HashMarker for AsconXofCore {}
209
210impl BlockSizeUser for AsconXofCore {
211 type BlockSize = U8;
212}
213
214impl BufferKindUser for AsconXofCore {
215 type BufferKind = Eager;
216}
217
218impl UpdateCore for AsconXofCore {
219 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
220 for block in blocks {
221 self.state.absorb_block(block.as_ref());
222 }
223 }
224}
225
226#[derive(Clone, Debug)]
228pub struct AsconXofReaderCore {
229 hasher: HashCore<ParametersXof>,
230}
231
232impl BlockSizeUser for AsconXofReaderCore {
233 type BlockSize = U8;
234}
235
236impl XofReaderCore for AsconXofReaderCore {
237 fn read_block(&mut self) -> Block<Self> {
238 self.hasher.squeeze_block().into()
239 }
240}
241
242impl ExtendableOutputCore for AsconXofCore {
243 type ReaderCore = AsconXofReaderCore;
244
245 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
246 debug_assert!(buffer.get_pos() < 8);
247 self.state
248 .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
249 Self::ReaderCore {
250 hasher: self.state.clone(),
251 }
252 }
253}
254
255impl Reset for AsconXofCore {
256 fn reset(&mut self) {
257 *self = Default::default();
258 }
259}
260
261impl AlgorithmName for AsconXofCore {
262 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 f.write_str("Ascon-XOF128")
264 }
265}
266
267pub type AsconHash256 = CoreWrapper<AsconCore>;
278pub type AsconXof128 = CoreWrapper<AsconXofCore>;
291pub type AsconXof128Reader = XofReaderCoreWrapper<AsconXofReaderCore>;