digest/core_api/
wrapper.rs

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 = 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, buffer } = 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(" { .. }")
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, buffer } = self;
150        buffer.digest_blocks(input, |blocks| 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, buffer } = &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, buffer } = 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, mut buffer) = self.decompose();
204        let core = core.finalize_xof_core(&mut buffer);
205        let buffer = 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, buffer } = self;
221        let reader_core = core.finalize_xof_core(buffer);
222        core.reset();
223        buffer.reset();
224        let buffer = 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, 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}