1use ascon::State;
2use digest::{
3 block_buffer::Eager,
4 core_api::{
5 AlgorithmName, BlockSizeUser, BufferKindUser, CoreWrapper, FixedOutputCore, UpdateCore,
6 },
7 crypto_common::{KeyInit, KeySizeUser},
8 MacMarker, OutputSizeUser,
9};
10use typenum::consts::{U16, U32};
11
12use crate::{compress, extract};
13
14#[derive(Clone, Debug)]
15pub struct AsconMacCore {
16 state: State,
17}
18
19pub type AsconMac = CoreWrapper<AsconMacCore>;
20
21impl KeySizeUser for AsconMacCore {
22 type KeySize = U16;
23}
24
25impl AlgorithmName for AsconMacCore {
26 fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27 f.write_str("Ascon-Mac")
28 }
29}
30
31impl KeyInit for AsconMacCore {
32 #[inline(always)]
33 fn new(key: &digest::Key<Self>) -> Self {
34 const IV: u64 = 0x00000080008c8080;
35 Self {
36 state: crate::init(IV, key),
37 }
38 }
39}
40
41impl BlockSizeUser for AsconMacCore {
42 type BlockSize = U32;
43}
44
45impl BufferKindUser for AsconMacCore {
46 type BufferKind = Eager;
47}
48
49impl UpdateCore for AsconMacCore {
50 fn update_blocks(&mut self, blocks: &[digest::core_api::Block<Self>]) {
51 blocks.iter().for_each(|b| compress(&mut self.state, b, 0));
52 }
53}
54
55impl OutputSizeUser for AsconMacCore {
56 type OutputSize = U16;
57}
58
59impl FixedOutputCore for AsconMacCore {
60 fn finalize_fixed_core(
61 &mut self,
62 buffer: &mut digest::core_api::Buffer<Self>,
63 out: &mut digest::Output<Self>,
64 ) {
65 buffer.digest_pad(0x01, &[], |block| {
66 compress(&mut self.state, block, 1);
67 });
68 extract(&self.state, out);
69 }
70}
71
72impl MacMarker for AsconMacCore {}
73
74#[cfg(test)]
75mod tests {
76 use digest::Mac;
77
78 use super::AsconMac;
79
80 #[test]
81 fn round_trip() {
82 let input = b"This is our great input sequence";
83
84 let mut mac = AsconMac::new(b"0123456789abcdef".into());
85 mac.update(input);
86 let output = mac.finalize().into_bytes();
87
88 assert_eq!(
89 &output[..],
90 &[53, 224, 223, 219, 242, 104, 181, 209, 23, 144, 216, 69, 242, 73, 137, 139]
91 );
92
93 let mut mac = AsconMac::new(b"0123456789abcdef".into());
94 mac.update(input);
95 mac.verify(&output).unwrap();
96 }
97}