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
16pub type Hmac<D> = CoreWrapper<HmacCore<D>>;
18
19pub 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 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}