1#![no_std]
5#![cfg_attr(docsrs, feature(doc_auto_cfg))]
6#![doc = include_str!("../README.md")]
7#![forbid(unsafe_code)]
8#![warn(missing_docs)]
9
10use core::{
11 mem::size_of,
12 ops::{Index, IndexMut},
13};
14
15#[cfg(feature = "zeroize")]
16use zeroize::{Zeroize, ZeroizeOnDrop};
17
18#[inline(always)]
20const fn round_constant(round: u64) -> u64 {
21 ((0xfu64 - round) << 4) | round
22}
23
24#[cfg(not(ascon_impl = "no_unroll"))]
25macro_rules! apply_permutation {
26 ($state:expr, $rc:literal) => {
27 round($state, $rc)
28 };
29 ($state:expr, $rc:literal, $($rcs:literal),+) => {
30 apply_permutation!(round($state, $rc), $($rcs),+)
31 };
32}
33
34#[cfg(ascon_impl = "no_unroll")]
35macro_rules! apply_permutation {
36 ($state:expr, $($rcs:literal),+) => {
37 [$($rcs),+].into_iter().fold($state, round)
38 };
39}
40
41#[derive(Clone, Debug, Default)]
45#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
46pub struct State {
47 x: [u64; 5],
48}
49
50const fn round(x: [u64; 5], c: u64) -> [u64; 5] {
52 let x0 = x[0] ^ x[4];
54 let x2 = x[2] ^ x[1] ^ c; let x4 = x[4] ^ x[3];
56
57 let tx0 = x0 ^ (!x[1] & x2);
58 let tx1 = x[1] ^ (!x2 & x[3]);
59 let tx2 = x2 ^ (!x[3] & x4);
60 let tx3 = x[3] ^ (!x4 & x0);
61 let tx4 = x4 ^ (!x0 & x[1]);
62 let tx1 = tx1 ^ tx0;
63 let tx3 = tx3 ^ tx2;
64 let tx0 = tx0 ^ tx4;
65
66 let x0 = tx0 ^ tx0.rotate_right(9);
68 let x1 = tx1 ^ tx1.rotate_right(22);
69 let x2 = tx2 ^ tx2.rotate_right(5);
70 let x3 = tx3 ^ tx3.rotate_right(7);
71 let x4 = tx4 ^ tx4.rotate_right(34);
72 [
73 tx0 ^ x0.rotate_right(19),
74 tx1 ^ x1.rotate_right(39),
75 !(tx2 ^ x2.rotate_right(1)),
76 tx3 ^ x3.rotate_right(10),
77 tx4 ^ x4.rotate_right(7),
78 ]
79}
80
81impl State {
82 pub fn new(x0: u64, x1: u64, x2: u64, x3: u64, x4: u64) -> Self {
84 State {
85 x: [x0, x1, x2, x3, x4],
86 }
87 }
88
89 pub fn permute_12(&mut self) {
91 self.x = apply_permutation!(
92 self.x, 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b
93 );
94 }
95
96 pub fn permute_8(&mut self) {
98 self.x = apply_permutation!(self.x, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b);
99 }
100
101 #[cfg(feature = "permute_6")]
102 pub fn permute_6(&mut self) {
104 self.x = apply_permutation!(self.x, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b);
105 }
106
107 #[cfg(feature = "permute_1")]
108 pub fn permute_1(&mut self) {
110 self.x = round(self.x, 0x4b);
111 }
112
113 pub fn permute_n(&mut self, rounds: usize) {
117 debug_assert!(rounds <= 12);
118
119 let start = 12 - rounds;
120 self.x = (start..12).fold(self.x, |x, round_index| {
121 round(x, round_constant(round_index as u64))
122 });
123 }
124
125 pub fn as_bytes(&self) -> [u8; 40] {
127 let mut bytes = [0u8; size_of::<u64>() * 5];
128 for (dst, src) in bytes
129 .chunks_exact_mut(size_of::<u64>())
130 .zip(self.x.into_iter())
131 {
132 dst.copy_from_slice(&u64::to_be_bytes(src));
133 }
134 bytes
135 }
136}
137
138impl Index<usize> for State {
139 type Output = u64;
140
141 #[inline(always)]
142 fn index(&self, index: usize) -> &Self::Output {
143 &self.x[index]
144 }
145}
146
147impl IndexMut<usize> for State {
148 #[inline(always)]
149 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
150 &mut self.x[index]
151 }
152}
153
154impl TryFrom<&[u64]> for State {
155 type Error = ();
156
157 fn try_from(value: &[u64]) -> Result<Self, Self::Error> {
158 match value.len() {
159 5 => Ok(Self::new(value[0], value[1], value[2], value[3], value[4])),
160 _ => Err(()),
161 }
162 }
163}
164
165impl From<&[u64; 5]> for State {
166 fn from(value: &[u64; 5]) -> Self {
167 Self { x: *value }
168 }
169}
170
171impl TryFrom<&[u8]> for State {
172 type Error = ();
173
174 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
175 if value.len() != core::mem::size_of::<u64>() * 5 {
176 return Err(());
177 }
178
179 let mut state = Self::default();
180 for (src, dst) in value
181 .chunks_exact(core::mem::size_of::<u64>())
182 .zip(state.x.iter_mut())
183 {
184 *dst = u64::from_be_bytes(src.try_into().unwrap());
185 }
186 Ok(state)
187 }
188}
189
190impl From<&[u8; size_of::<u64>() * 5]> for State {
191 fn from(value: &[u8; size_of::<u64>() * 5]) -> Self {
192 let mut state = Self::default();
193 for (src, dst) in value
194 .chunks_exact(core::mem::size_of::<u64>())
195 .zip(state.x.iter_mut())
196 {
197 *dst = u64::from_be_bytes(src.try_into().unwrap());
198 }
199 state
200 }
201}
202
203impl AsRef<[u64]> for State {
204 fn as_ref(&self) -> &[u64] {
205 &self.x
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
214 fn round_constants() {
215 assert_eq!(round_constant(0), 0xf0);
216 assert_eq!(round_constant(1), 0xe1);
217 assert_eq!(round_constant(2), 0xd2);
218 assert_eq!(round_constant(3), 0xc3);
219 assert_eq!(round_constant(4), 0xb4);
220 assert_eq!(round_constant(5), 0xa5);
221 assert_eq!(round_constant(6), 0x96);
222 assert_eq!(round_constant(7), 0x87);
223 assert_eq!(round_constant(8), 0x78);
224 assert_eq!(round_constant(9), 0x69);
225 assert_eq!(round_constant(10), 0x5a);
226 assert_eq!(round_constant(11), 0x4b);
227 }
228
229 #[test]
230 fn one_round() {
231 let state = round(
232 [
233 0x0123456789abcdef,
234 0x23456789abcdef01,
235 0x456789abcdef0123,
236 0x6789abcdef012345,
237 0x89abcde01234567f,
238 ],
239 0x1f,
240 );
241 assert_eq!(
242 state,
243 [
244 0x3c1748c9be2892ce,
245 0x5eafb305cd26164f,
246 0xf9470254bb3a4213,
247 0xf0428daf0c5d3948,
248 0x281375af0b294899
249 ]
250 );
251 }
252
253 #[test]
254 fn state_permute_12() {
255 let mut state = State::new(
256 0x0123456789abcdef,
257 0xef0123456789abcd,
258 0xcdef0123456789ab,
259 0xabcdef0123456789,
260 0x89abcdef01234567,
261 );
262 state.permute_12();
263 assert_eq!(state[0], 0x206416dfc624bb14);
264 assert_eq!(state[1], 0x1b0c47a601058aab);
265 assert_eq!(state[2], 0x8934cfc93814cddd);
266 assert_eq!(state[3], 0xa9738d287a748e4b);
267 assert_eq!(state[4], 0xddd934f058afc7e1);
268 }
269
270 #[test]
271 fn state_permute_8() {
272 let mut state = State::new(
273 0x0123456789abcdef,
274 0xef0123456789abcd,
275 0xcdef0123456789ab,
276 0xabcdef0123456789,
277 0x89abcdef01234567,
278 );
279 state.permute_8();
280 assert_eq!(state[0], 0x67ed228272f46eee);
281 assert_eq!(state[1], 0x80bc0b097aad7944);
282 assert_eq!(state[2], 0x2fa599382c6db215);
283 assert_eq!(state[3], 0x368133fae2f7667a);
284 assert_eq!(state[4], 0x28cefb195a7c651c);
285 }
286
287 #[cfg(feature = "permute_6")]
288 #[test]
289 fn state_permute_6() {
290 let mut state = State::new(
291 0x0123456789abcdef,
292 0xef0123456789abcd,
293 0xcdef0123456789ab,
294 0xabcdef0123456789,
295 0x89abcdef01234567,
296 );
297 state.permute_6();
298 assert_eq!(state[0], 0xc27b505c635eb07f);
299 assert_eq!(state[1], 0xd388f5d2a72046fa);
300 assert_eq!(state[2], 0x9e415c204d7b15e7);
301 assert_eq!(state[3], 0xce0d71450fe44581);
302 assert_eq!(state[4], 0xdd7c5fef57befe48);
303 }
304
305 #[test]
306 fn state_permute_n() {
307 let mut state = State::new(
308 0x0123456789abcdef,
309 0xef0123456789abcd,
310 0xcdef0123456789ab,
311 0xabcdef0123456789,
312 0x89abcdef01234567,
313 );
314 let mut state2 = state.clone();
315
316 #[cfg(feature = "permute_6")]
317 {
318 state.permute_6();
319 state2.permute_n(6);
320 assert_eq!(state.x, state2.x);
321 }
322
323 state.permute_8();
324 state2.permute_n(8);
325 assert_eq!(state.x, state2.x);
326
327 state.permute_12();
328 state2.permute_n(12);
329 assert_eq!(state.x, state2.x);
330 }
331
332 #[test]
333 fn state_convert_bytes() {
334 let state = State::new(
335 0x0123456789abcdef,
336 0xef0123456789abcd,
337 0xcdef0123456789ab,
338 0xabcdef0123456789,
339 0x89abcdef01234567,
340 );
341 let bytes = state.as_bytes();
342
343 let state2 = State::try_from(&bytes[..]);
345 assert_eq!(state2.expect("try_from bytes").x, state.x);
346
347 let state2 = State::from(&bytes);
348 assert_eq!(state2.x, state.x);
349 }
350}