1 | use super::{ |
2 | AlgorithmName, Buffer, BufferKindUser, ExtendableOutputCore, FixedOutputCore, OutputSizeUser, |
3 | Reset, UpdateCore, XofReaderCoreWrapper, |
4 | }; |
5 | use crate::{ |
6 | ExtendableOutput, ExtendableOutputReset, FixedOutput, FixedOutputReset, HashMarker, Update, |
7 | }; |
8 | use block_buffer::BlockBuffer; |
9 | use core::fmt; |
10 | use crypto_common::{ |
11 | typenum::{IsLess, Le, NonZero, U256}, |
12 | BlockSizeUser, InvalidLength, Key, KeyInit, KeySizeUser, Output, |
13 | }; |
14 | |
15 | #[cfg (feature = "mac" )] |
16 | use crate::MacMarker; |
17 | #[cfg (feature = "oid" )] |
18 | use const_oid::{AssociatedOid, ObjectIdentifier}; |
19 | |
20 | /// Wrapper around [`BufferKindUser`]. |
21 | /// |
22 | /// It handles data buffering and implements the slice-based traits. |
23 | #[derive (Clone, Default)] |
24 | pub struct CoreWrapper<T> |
25 | where |
26 | T: BufferKindUser, |
27 | T::BlockSize: IsLess<U256>, |
28 | Le<T::BlockSize, U256>: NonZero, |
29 | { |
30 | core: T, |
31 | buffer: BlockBuffer<T::BlockSize, T::BufferKind>, |
32 | } |
33 | |
34 | impl<T> HashMarker for CoreWrapper<T> |
35 | where |
36 | T: BufferKindUser + HashMarker, |
37 | T::BlockSize: IsLess<U256>, |
38 | Le<T::BlockSize, U256>: NonZero, |
39 | { |
40 | } |
41 | |
42 | #[cfg (feature = "mac" )] |
43 | #[cfg_attr (docsrs, doc(cfg(feature = "mac" )))] |
44 | impl<T> MacMarker for CoreWrapper<T> |
45 | where |
46 | T: BufferKindUser + MacMarker, |
47 | T::BlockSize: IsLess<U256>, |
48 | Le<T::BlockSize, U256>: NonZero, |
49 | { |
50 | } |
51 | |
52 | // this blanket impl is needed for HMAC |
53 | impl<T> BlockSizeUser for CoreWrapper<T> |
54 | where |
55 | T: BufferKindUser + HashMarker, |
56 | T::BlockSize: IsLess<U256>, |
57 | Le<T::BlockSize, U256>: NonZero, |
58 | { |
59 | type BlockSize = T::BlockSize; |
60 | } |
61 | |
62 | impl<T> CoreWrapper<T> |
63 | where |
64 | T: BufferKindUser, |
65 | T::BlockSize: IsLess<U256>, |
66 | Le<T::BlockSize, U256>: NonZero, |
67 | { |
68 | /// Create new wrapper from `core`. |
69 | #[inline ] |
70 | pub fn from_core(core: T) -> Self { |
71 | let buffer: BlockBuffer<::BlockSize, …> = Default::default(); |
72 | Self { core, buffer } |
73 | } |
74 | |
75 | /// Decompose wrapper into inner parts. |
76 | #[inline ] |
77 | pub fn decompose(self) -> (T, Buffer<T>) { |
78 | let Self { core: T, buffer: BlockBuffer<::BlockSize, …> } = self; |
79 | (core, buffer) |
80 | } |
81 | } |
82 | |
83 | impl<T> KeySizeUser for CoreWrapper<T> |
84 | where |
85 | T: BufferKindUser + KeySizeUser, |
86 | T::BlockSize: IsLess<U256>, |
87 | Le<T::BlockSize, U256>: NonZero, |
88 | { |
89 | type KeySize = T::KeySize; |
90 | } |
91 | |
92 | impl<T> KeyInit for CoreWrapper<T> |
93 | where |
94 | T: BufferKindUser + KeyInit, |
95 | T::BlockSize: IsLess<U256>, |
96 | Le<T::BlockSize, U256>: NonZero, |
97 | { |
98 | #[inline ] |
99 | fn new(key: &Key<Self>) -> Self { |
100 | Self { |
101 | core: T::new(key), |
102 | buffer: Default::default(), |
103 | } |
104 | } |
105 | |
106 | #[inline ] |
107 | fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> { |
108 | Ok(Self { |
109 | core: T::new_from_slice(key)?, |
110 | buffer: Default::default(), |
111 | }) |
112 | } |
113 | } |
114 | |
115 | impl<T> fmt::Debug for CoreWrapper<T> |
116 | where |
117 | T: BufferKindUser + AlgorithmName, |
118 | T::BlockSize: IsLess<U256>, |
119 | Le<T::BlockSize, U256>: NonZero, |
120 | { |
121 | #[inline ] |
122 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
123 | T::write_alg_name(f)?; |
124 | f.write_str(data:" { .. }" ) |
125 | } |
126 | } |
127 | |
128 | impl<T> Reset for CoreWrapper<T> |
129 | where |
130 | T: BufferKindUser + Reset, |
131 | T::BlockSize: IsLess<U256>, |
132 | Le<T::BlockSize, U256>: NonZero, |
133 | { |
134 | #[inline ] |
135 | fn reset(&mut self) { |
136 | self.core.reset(); |
137 | self.buffer.reset(); |
138 | } |
139 | } |
140 | |
141 | impl<T> Update for CoreWrapper<T> |
142 | where |
143 | T: BufferKindUser + UpdateCore, |
144 | T::BlockSize: IsLess<U256>, |
145 | Le<T::BlockSize, U256>: NonZero, |
146 | { |
147 | #[inline ] |
148 | fn update(&mut self, input: &[u8]) { |
149 | let Self { core: &mut T, buffer: &mut BlockBuffer<::BlockSize, …> } = self; |
150 | buffer.digest_blocks(input, |blocks: &[GenericArray::BlockSize>]| core.update_blocks(blocks)); |
151 | } |
152 | } |
153 | |
154 | impl<T> OutputSizeUser for CoreWrapper<T> |
155 | where |
156 | T: BufferKindUser + OutputSizeUser, |
157 | T::BlockSize: IsLess<U256>, |
158 | Le<T::BlockSize, U256>: NonZero, |
159 | { |
160 | type OutputSize = T::OutputSize; |
161 | } |
162 | |
163 | impl<T> FixedOutput for CoreWrapper<T> |
164 | where |
165 | T: FixedOutputCore, |
166 | T::BlockSize: IsLess<U256>, |
167 | Le<T::BlockSize, U256>: NonZero, |
168 | { |
169 | #[inline ] |
170 | fn finalize_into(mut self, out: &mut Output<Self>) { |
171 | let Self { core: &mut T, buffer: &mut BlockBuffer<::BlockSize, …> } = &mut self; |
172 | core.finalize_fixed_core(buffer, out); |
173 | } |
174 | } |
175 | |
176 | impl<T> FixedOutputReset for CoreWrapper<T> |
177 | where |
178 | T: FixedOutputCore + Reset, |
179 | T::BlockSize: IsLess<U256>, |
180 | Le<T::BlockSize, U256>: NonZero, |
181 | { |
182 | #[inline ] |
183 | fn finalize_into_reset(&mut self, out: &mut Output<Self>) { |
184 | let Self { core: &mut T, buffer: &mut BlockBuffer<::BlockSize, …> } = self; |
185 | core.finalize_fixed_core(buffer, out); |
186 | core.reset(); |
187 | buffer.reset(); |
188 | } |
189 | } |
190 | |
191 | impl<T> ExtendableOutput for CoreWrapper<T> |
192 | where |
193 | T: ExtendableOutputCore, |
194 | T::BlockSize: IsLess<U256>, |
195 | Le<T::BlockSize, U256>: NonZero, |
196 | <T::ReaderCore as BlockSizeUser>::BlockSize: IsLess<U256>, |
197 | Le<<T::ReaderCore as BlockSizeUser>::BlockSize, U256>: NonZero, |
198 | { |
199 | type Reader = XofReaderCoreWrapper<T::ReaderCore>; |
200 | |
201 | #[inline ] |
202 | fn finalize_xof(self) -> Self::Reader { |
203 | let (mut core: T, mut buffer: BlockBuffer<::BlockSize, …>) = self.decompose(); |
204 | let core: ::ReaderCore = core.finalize_xof_core(&mut buffer); |
205 | let buffer: BlockBuffer<<::ReaderCore as BlockSizeUser>::BlockSize, …> = Default::default(); |
206 | Self::Reader { core, buffer } |
207 | } |
208 | } |
209 | |
210 | impl<T> ExtendableOutputReset for CoreWrapper<T> |
211 | where |
212 | T: ExtendableOutputCore + Reset, |
213 | T::BlockSize: IsLess<U256>, |
214 | Le<T::BlockSize, U256>: NonZero, |
215 | <T::ReaderCore as BlockSizeUser>::BlockSize: IsLess<U256>, |
216 | Le<<T::ReaderCore as BlockSizeUser>::BlockSize, U256>: NonZero, |
217 | { |
218 | #[inline ] |
219 | fn finalize_xof_reset(&mut self) -> Self::Reader { |
220 | let Self { core: &mut T, buffer: &mut BlockBuffer<::BlockSize, …> } = self; |
221 | let reader_core: ::ReaderCore = core.finalize_xof_core(buffer); |
222 | core.reset(); |
223 | buffer.reset(); |
224 | let buffer: BlockBuffer<<::ReaderCore as BlockSizeUser>::BlockSize, …> = Default::default(); |
225 | Self::Reader { |
226 | core: reader_core, |
227 | buffer, |
228 | } |
229 | } |
230 | } |
231 | |
232 | #[cfg (feature = "oid" )] |
233 | #[cfg_attr (docsrs, doc(cfg(feature = "oid" )))] |
234 | impl<T> AssociatedOid for CoreWrapper<T> |
235 | where |
236 | T: BufferKindUser + AssociatedOid, |
237 | T::BlockSize: IsLess<U256>, |
238 | Le<T::BlockSize, U256>: NonZero, |
239 | { |
240 | const OID: ObjectIdentifier = T::OID; |
241 | } |
242 | |
243 | #[cfg (feature = "std" )] |
244 | #[cfg_attr (docsrs, doc(cfg(feature = "std" )))] |
245 | impl<T> std::io::Write for CoreWrapper<T> |
246 | where |
247 | T: BufferKindUser + UpdateCore, |
248 | T::BlockSize: IsLess<U256>, |
249 | Le<T::BlockSize, U256>: NonZero, |
250 | { |
251 | #[inline ] |
252 | fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { |
253 | Update::update(self, data:buf); |
254 | Ok(buf.len()) |
255 | } |
256 | |
257 | #[inline ] |
258 | fn flush(&mut self) -> std::io::Result<()> { |
259 | Ok(()) |
260 | } |
261 | } |
262 | |
263 | /// A proxy trait to a core type implemented by [`CoreWrapper`] |
264 | // TODO: replace with an inherent associated type on stabilization: |
265 | // https://github.com/rust-lang/rust/issues/8995 |
266 | pub trait CoreProxy: sealed::Sealed { |
267 | /// Type wrapped by [`CoreWrapper`]. |
268 | type Core; |
269 | } |
270 | |
271 | mod sealed { |
272 | pub trait Sealed {} |
273 | } |
274 | |
275 | impl<T> sealed::Sealed for CoreWrapper<T> |
276 | where |
277 | T: BufferKindUser, |
278 | T::BlockSize: IsLess<U256>, |
279 | Le<T::BlockSize, U256>: NonZero, |
280 | { |
281 | } |
282 | |
283 | impl<T> CoreProxy for CoreWrapper<T> |
284 | where |
285 | T: BufferKindUser, |
286 | T::BlockSize: IsLess<U256>, |
287 | Le<T::BlockSize, U256>: NonZero, |
288 | { |
289 | type Core = T; |
290 | } |
291 | |