1use super::{
2 AlgorithmName, Buffer, BufferKindUser, ExtendableOutputCore, FixedOutputCore, OutputSizeUser,
3 Reset, UpdateCore, XofReaderCoreWrapper,
4};
5use crate::{
6 ExtendableOutput, ExtendableOutputReset, FixedOutput, FixedOutputReset, HashMarker, Update,
7};
8use block_buffer::BlockBuffer;
9use core::fmt;
10use crypto_common::{
11 typenum::{IsLess, Le, NonZero, U256},
12 BlockSizeUser, InvalidLength, Key, KeyInit, KeySizeUser, Output,
13};
14
15#[cfg(feature = "mac")]
16use crate::MacMarker;
17#[cfg(feature = "oid")]
18use 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)]
24pub struct CoreWrapper<T>
25where
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
34impl<T> HashMarker for CoreWrapper<T>
35where
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")))]
44impl<T> MacMarker for CoreWrapper<T>
45where
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
53impl<T> BlockSizeUser for CoreWrapper<T>
54where
55 T: BufferKindUser + HashMarker,
56 T::BlockSize: IsLess<U256>,
57 Le<T::BlockSize, U256>: NonZero,
58{
59 type BlockSize = T::BlockSize;
60}
61
62impl<T> CoreWrapper<T>
63where
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
83impl<T> KeySizeUser for CoreWrapper<T>
84where
85 T: BufferKindUser + KeySizeUser,
86 T::BlockSize: IsLess<U256>,
87 Le<T::BlockSize, U256>: NonZero,
88{
89 type KeySize = T::KeySize;
90}
91
92impl<T> KeyInit for CoreWrapper<T>
93where
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
115impl<T> fmt::Debug for CoreWrapper<T>
116where
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
128impl<T> Reset for CoreWrapper<T>
129where
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
141impl<T> Update for CoreWrapper<T>
142where
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
154impl<T> OutputSizeUser for CoreWrapper<T>
155where
156 T: BufferKindUser + OutputSizeUser,
157 T::BlockSize: IsLess<U256>,
158 Le<T::BlockSize, U256>: NonZero,
159{
160 type OutputSize = T::OutputSize;
161}
162
163impl<T> FixedOutput for CoreWrapper<T>
164where
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
176impl<T> FixedOutputReset for CoreWrapper<T>
177where
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
191impl<T> ExtendableOutput for CoreWrapper<T>
192where
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
210impl<T> ExtendableOutputReset for CoreWrapper<T>
211where
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")))]
234impl<T> AssociatedOid for CoreWrapper<T>
235where
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")))]
245impl<T> std::io::Write for CoreWrapper<T>
246where
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
266pub trait CoreProxy: sealed::Sealed {
267 /// Type wrapped by [`CoreWrapper`].
268 type Core;
269}
270
271mod sealed {
272 pub trait Sealed {}
273}
274
275impl<T> sealed::Sealed for CoreWrapper<T>
276where
277 T: BufferKindUser,
278 T::BlockSize: IsLess<U256>,
279 Le<T::BlockSize, U256>: NonZero,
280{
281}
282
283impl<T> CoreProxy for CoreWrapper<T>
284where
285 T: BufferKindUser,
286 T::BlockSize: IsLess<U256>,
287 Le<T::BlockSize, U256>: NonZero,
288{
289 type Core = T;
290}
291