belt_mac/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
5    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg"
6)]
7#![forbid(unsafe_code)]
8#![cfg_attr(docsrs, feature(doc_cfg))]
9#![warn(missing_docs, rust_2018_idioms)]
10
11pub use digest::{self, Mac};
12
13use belt_block::BeltBlock;
14use cipher::{BlockBackend, BlockCipher, BlockClosure, BlockEncryptMut};
15use core::fmt;
16use digest::{
17    block_buffer::Lazy,
18    core_api::{
19        AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore,
20        UpdateCore,
21    },
22    crypto_common::{InnerInit, InnerUser},
23    generic_array::{
24        typenum::{IsLess, Le, NonZero, U256},
25        ArrayLength, GenericArray,
26    },
27    MacMarker, Output, OutputSizeUser, Reset,
28};
29
30#[cfg(feature = "zeroize")]
31use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
32
33/// Generic BeltMac instance.
34pub type BeltMac<C = BeltBlock> = CoreWrapper<BeltMacCore<C>>;
35
36#[derive(Clone)]
37/// Generic core BeltMac instance, which operates over blocks.
38pub struct BeltMacCore<C = BeltBlock>
39where
40    C: BlockCipher + BlockEncryptMut + Clone,
41{
42    cipher: C,
43    state: Block<C>,
44    r: Block<C>,
45}
46
47impl<C> BlockSizeUser for BeltMacCore<C>
48where
49    C: BlockCipher + BlockEncryptMut + Clone,
50{
51    type BlockSize = C::BlockSize;
52}
53
54impl<C> OutputSizeUser for BeltMacCore<C>
55where
56    C: BlockCipher + BlockEncryptMut + Clone,
57{
58    type OutputSize = C::BlockSize;
59}
60
61impl<C> InnerUser for BeltMacCore<C>
62where
63    C: BlockCipher + BlockEncryptMut + Clone,
64{
65    type Inner = C;
66}
67
68impl<C> MacMarker for BeltMacCore<C> where C: BlockCipher + BlockEncryptMut + Clone {}
69
70impl<C> InnerInit for BeltMacCore<C>
71where
72    C: BlockCipher + BlockEncryptMut + Clone,
73{
74    #[inline]
75    fn inner_init(mut cipher: C) -> Self {
76        let state = Default::default();
77        let mut r = Default::default();
78        cipher.encrypt_block_mut(&mut r);
79        Self { cipher, state, r }
80    }
81}
82
83impl<C> BufferKindUser for BeltMacCore<C>
84where
85    C: BlockCipher + BlockEncryptMut + Clone,
86{
87    type BufferKind = Lazy;
88}
89
90impl<C> UpdateCore for BeltMacCore<C>
91where
92    C: BlockCipher + BlockEncryptMut + Clone,
93{
94    #[inline]
95    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
96        struct Ctx<'a, N: ArrayLength<u8>> {
97            state: &'a mut Block<Self>,
98            blocks: &'a [Block<Self>],
99        }
100
101        impl<'a, N: ArrayLength<u8>> BlockSizeUser for Ctx<'a, N> {
102            type BlockSize = N;
103        }
104
105        impl<'a, N: ArrayLength<u8>> BlockClosure for Ctx<'a, N> {
106            #[inline(always)]
107            fn call<B: BlockBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) {
108                for block in self.blocks {
109                    xor(self.state, block);
110                    backend.proc_block((self.state).into());
111                }
112            }
113        }
114
115        let Self { cipher, state, .. } = self;
116        cipher.encrypt_with_backend_mut(Ctx { state, blocks })
117    }
118}
119
120impl<C> Reset for BeltMacCore<C>
121where
122    C: BlockCipher + BlockEncryptMut + Clone,
123{
124    #[inline(always)]
125    fn reset(&mut self) {
126        self.state = Default::default();
127    }
128}
129
130impl<C> FixedOutputCore for BeltMacCore<C>
131where
132    C: BlockCipher + BlockEncryptMut + Clone,
133    C::BlockSize: IsLess<U256>,
134    Le<C::BlockSize, U256>: NonZero,
135{
136    #[inline]
137    fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
138        let pos = buffer.get_pos();
139        let buf = buffer.pad_with_zeros();
140
141        let cipher = &mut self.cipher;
142        let r = &self.r;
143        let bs = r.len();
144        let mut new_r = Block::<C>::default();
145        if pos == bs {
146            // phi1
147            let (h1, h2) = new_r.split_at_mut(bs - 4);
148            h1.copy_from_slice(&r[4..]);
149            for i in 0..4 {
150                h2[i] = r[i] ^ r[4 + i];
151            }
152        } else {
153            buf[pos] = 0x80;
154            // phi2
155            let (h1, h2) = new_r.split_at_mut(4);
156            for i in 0..4 {
157                h1[i] = r[i] ^ r[bs - 4 + i];
158            }
159            h2.copy_from_slice(&r[..bs - 4]);
160        }
161
162        let mut state = self.state.clone();
163        xor(&mut state, buf);
164        xor(&mut state, &new_r);
165        cipher.encrypt_block_b2b_mut(&state, out);
166    }
167}
168
169impl<C> AlgorithmName for BeltMacCore<C>
170where
171    C: BlockCipher + BlockEncryptMut + Clone + AlgorithmName,
172{
173    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        f.write_str("BeltMac<")?;
175        <C as AlgorithmName>::write_alg_name(f)?;
176        f.write_str(">")
177    }
178}
179
180impl<C> fmt::Debug for BeltMacCore<C>
181where
182    C: BlockCipher + BlockEncryptMut + Clone + AlgorithmName,
183{
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        f.write_str("BeltMacCore<")?;
186        <C as AlgorithmName>::write_alg_name(f)?;
187        f.write_str("> { ... }")
188    }
189}
190
191#[cfg(feature = "zeroize")]
192#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
193impl<C> Drop for BeltMacCore<C>
194where
195    C: BlockCipher + BlockEncryptMut + Clone,
196{
197    fn drop(&mut self) {
198        self.state.zeroize();
199    }
200}
201
202#[cfg(feature = "zeroize")]
203#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
204impl<C> ZeroizeOnDrop for BeltMacCore<C> where
205    C: BlockCipher + BlockEncryptMut + Clone + ZeroizeOnDrop
206{
207}
208
209#[inline(always)]
210fn xor<N: ArrayLength<u8>>(buf: &mut GenericArray<u8, N>, data: &GenericArray<u8, N>) {
211    for i in 0..N::USIZE {
212        buf[i] ^= data[i];
213    }
214}