hmac/
optim.rs

1use super::{get_der_key, IPAD, OPAD};
2use core::{fmt, slice};
3#[cfg(feature = "reset")]
4use digest::Reset;
5use digest::{
6    block_buffer::Eager,
7    core_api::{
8        AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreProxy, CoreWrapper,
9        FixedOutputCore, OutputSizeUser, UpdateCore,
10    },
11    crypto_common::{Key, KeySizeUser},
12    generic_array::typenum::{IsLess, Le, NonZero, U256},
13    HashMarker, InvalidLength, KeyInit, MacMarker, Output,
14};
15
16/// Generic HMAC instance.
17pub type Hmac<D> = CoreWrapper<HmacCore<D>>;
18
19/// Generic core HMAC instance, which operates over blocks.
20pub struct HmacCore<D>
21where
22    D: CoreProxy,
23    D::Core: HashMarker
24        + UpdateCore
25        + FixedOutputCore
26        + BufferKindUser<BufferKind = Eager>
27        + Default
28        + Clone,
29    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
30    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
31{
32    digest: D::Core,
33    opad_digest: D::Core,
34    #[cfg(feature = "reset")]
35    ipad_digest: D::Core,
36}
37
38impl<D> Clone for HmacCore<D>
39where
40    D: CoreProxy,
41    D::Core: HashMarker
42        + UpdateCore
43        + FixedOutputCore
44        + BufferKindUser<BufferKind = Eager>
45        + Default
46        + Clone,
47    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
48    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
49{
50    fn clone(&self) -> Self {
51        Self {
52            digest: self.digest.clone(),
53            opad_digest: self.opad_digest.clone(),
54            #[cfg(feature = "reset")]
55            ipad_digest: self.ipad_digest.clone(),
56        }
57    }
58}
59
60impl<D> MacMarker for HmacCore<D>
61where
62    D: CoreProxy,
63    D::Core: HashMarker
64        + UpdateCore
65        + FixedOutputCore
66        + BufferKindUser<BufferKind = Eager>
67        + Default
68        + Clone,
69    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
70    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
71{
72}
73
74impl<D> BufferKindUser for HmacCore<D>
75where
76    D: CoreProxy,
77    D::Core: HashMarker
78        + UpdateCore
79        + FixedOutputCore
80        + BufferKindUser<BufferKind = Eager>
81        + Default
82        + Clone,
83    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
84    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
85{
86    type BufferKind = Eager;
87}
88
89impl<D> KeySizeUser for HmacCore<D>
90where
91    D: CoreProxy,
92    D::Core: HashMarker
93        + UpdateCore
94        + FixedOutputCore
95        + BufferKindUser<BufferKind = Eager>
96        + Default
97        + Clone,
98    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
99    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
100{
101    type KeySize = <<D as CoreProxy>::Core as BlockSizeUser>::BlockSize;
102}
103
104impl<D> BlockSizeUser for HmacCore<D>
105where
106    D: CoreProxy,
107    D::Core: HashMarker
108        + UpdateCore
109        + FixedOutputCore
110        + BufferKindUser<BufferKind = Eager>
111        + Default
112        + Clone,
113    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
114    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
115{
116    type BlockSize = <<D as CoreProxy>::Core as BlockSizeUser>::BlockSize;
117}
118
119impl<D> OutputSizeUser for HmacCore<D>
120where
121    D: CoreProxy,
122    D::Core: HashMarker
123        + UpdateCore
124        + FixedOutputCore
125        + BufferKindUser<BufferKind = Eager>
126        + Default
127        + Clone,
128    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
129    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
130{
131    type OutputSize = <<D as CoreProxy>::Core as OutputSizeUser>::OutputSize;
132}
133
134impl<D> KeyInit for HmacCore<D>
135where
136    D: CoreProxy,
137    D::Core: HashMarker
138        + UpdateCore
139        + FixedOutputCore
140        + BufferKindUser<BufferKind = Eager>
141        + Default
142        + Clone,
143    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
144    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
145{
146    #[inline(always)]
147    fn new(key: &Key<Self>) -> Self {
148        Self::new_from_slice(key.as_slice()).unwrap()
149    }
150
151    #[inline(always)]
152    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
153        let mut buf = get_der_key::<CoreWrapper<D::Core>>(key);
154        for b in buf.iter_mut() {
155            *b ^= IPAD;
156        }
157        let mut digest = D::Core::default();
158        digest.update_blocks(slice::from_ref(&buf));
159
160        for b in buf.iter_mut() {
161            *b ^= IPAD ^ OPAD;
162        }
163
164        let mut opad_digest = D::Core::default();
165        opad_digest.update_blocks(slice::from_ref(&buf));
166
167        Ok(Self {
168            #[cfg(feature = "reset")]
169            ipad_digest: digest.clone(),
170            opad_digest,
171            digest,
172        })
173    }
174}
175
176impl<D> UpdateCore for HmacCore<D>
177where
178    D: CoreProxy,
179    D::Core: HashMarker
180        + UpdateCore
181        + FixedOutputCore
182        + BufferKindUser<BufferKind = Eager>
183        + Default
184        + Clone,
185    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
186    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
187{
188    #[inline(always)]
189    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
190        self.digest.update_blocks(blocks);
191    }
192}
193
194impl<D> FixedOutputCore for HmacCore<D>
195where
196    D: CoreProxy,
197    D::Core: HashMarker
198        + UpdateCore
199        + FixedOutputCore
200        + BufferKindUser<BufferKind = Eager>
201        + Default
202        + Clone,
203    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
204    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
205{
206    #[inline(always)]
207    fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
208        let mut hash = Output::<D::Core>::default();
209        self.digest.finalize_fixed_core(buffer, &mut hash);
210        // finalize_fixed_core should reset the buffer as well, but
211        // to be extra safe we reset it explicitly again.
212        buffer.reset();
213        #[cfg(not(feature = "reset"))]
214        let h = &mut self.opad_digest;
215        #[cfg(feature = "reset")]
216        let mut h = self.opad_digest.clone();
217        buffer.digest_blocks(&hash, |b| h.update_blocks(b));
218        h.finalize_fixed_core(buffer, out);
219    }
220}
221
222#[cfg(feature = "reset")]
223#[cfg_attr(docsrs, doc(cfg(feature = "reset")))]
224impl<D> Reset for HmacCore<D>
225where
226    D: CoreProxy,
227    D::Core: HashMarker
228        + UpdateCore
229        + FixedOutputCore
230        + BufferKindUser<BufferKind = Eager>
231        + Default
232        + Clone,
233    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
234    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
235{
236    #[inline(always)]
237    fn reset(&mut self) {
238        self.digest = self.ipad_digest.clone();
239    }
240}
241
242impl<D> AlgorithmName for HmacCore<D>
243where
244    D: CoreProxy,
245    D::Core: HashMarker
246        + AlgorithmName
247        + UpdateCore
248        + FixedOutputCore
249        + BufferKindUser<BufferKind = Eager>
250        + Default
251        + Clone,
252    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
253    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
254{
255    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
256        f.write_str("Hmac<")?;
257        <D::Core as AlgorithmName>::write_alg_name(f)?;
258        f.write_str(">")
259    }
260}
261
262impl<D> fmt::Debug for HmacCore<D>
263where
264    D: CoreProxy,
265    D::Core: HashMarker
266        + AlgorithmName
267        + UpdateCore
268        + FixedOutputCore
269        + BufferKindUser<BufferKind = Eager>
270        + Default
271        + Clone,
272    <D::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
273    Le<<D::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
274{
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        f.write_str("HmacCore<")?;
277        <D::Core as AlgorithmName>::write_alg_name(f)?;
278        f.write_str("> { ... }")
279    }
280}