Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

digest/block_api/
ct_variable.rs

1use super::{
2    AlgorithmName, Buffer, BufferKindUser, FixedOutputCore, Reset, TruncSide, UpdateCore,
3    VariableOutputCore, VariableOutputCoreCustomized,
4};
5#[cfg(feature = "mac")]
6use crate::MacMarker;
7use crate::{CollisionResistance, CustomizedInit, HashMarker};
8use common::{
9    Block, BlockSizeUser, OutputSizeUser,
10    array::{Array, ArraySize},
11    hazmat::{DeserializeStateError, SerializableState, SerializedState},
12    typenum::{IsLessOrEqual, True},
13};
14use core::{fmt, marker::PhantomData};
15
16/// Wrapper around [`VariableOutputCore`] which selects output size at compile time.
17#[derive(Clone)]
18pub struct CtOutWrapper<T, OutSize>
19where
20    T: VariableOutputCore,
21    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
22{
23    inner: T,
24    _out: PhantomData<OutSize>,
25}
26
27impl<T, OutSize> HashMarker for CtOutWrapper<T, OutSize>
28where
29    T: VariableOutputCore + HashMarker,
30    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
31{
32}
33
34#[cfg(feature = "mac")]
35impl<T, OutSize> MacMarker for CtOutWrapper<T, OutSize>
36where
37    T: VariableOutputCore + MacMarker,
38    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
39{
40}
41
42impl<T, OutSize> CollisionResistance for CtOutWrapper<T, OutSize>
43where
44    T: VariableOutputCore + CollisionResistance,
45    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
46{
47    type CollisionResistance = T::CollisionResistance;
48}
49
50impl<T, OutSize> BlockSizeUser for CtOutWrapper<T, OutSize>
51where
52    T: VariableOutputCore,
53    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
54{
55    type BlockSize = T::BlockSize;
56}
57
58impl<T, OutSize> UpdateCore for CtOutWrapper<T, OutSize>
59where
60    T: VariableOutputCore,
61    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
62{
63    #[inline]
64    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
65        self.inner.update_blocks(blocks);
66    }
67}
68
69impl<T, OutSize> OutputSizeUser for CtOutWrapper<T, OutSize>
70where
71    T: VariableOutputCore,
72    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
73{
74    type OutputSize = OutSize;
75}
76
77impl<T, OutSize> BufferKindUser for CtOutWrapper<T, OutSize>
78where
79    T: VariableOutputCore,
80    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
81{
82    type BufferKind = T::BufferKind;
83}
84
85impl<T, OutSize> FixedOutputCore for CtOutWrapper<T, OutSize>
86where
87    T: VariableOutputCore,
88    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
89{
90    #[inline]
91    fn finalize_fixed_core(
92        &mut self,
93        buffer: &mut Buffer<Self>,
94        out: &mut Array<u8, Self::OutputSize>,
95    ) {
96        let mut full_res = Default::default();
97        self.inner.finalize_variable_core(buffer, &mut full_res);
98        let n = out.len();
99        let m = full_res.len() - n;
100        match T::TRUNC_SIDE {
101            TruncSide::Left => out.copy_from_slice(&full_res[..n]),
102            TruncSide::Right => out.copy_from_slice(&full_res[m..]),
103        }
104    }
105}
106
107impl<T, OutSize> Default for CtOutWrapper<T, OutSize>
108where
109    T: VariableOutputCore,
110    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
111{
112    #[inline]
113    fn default() -> Self {
114        Self {
115            inner: T::new(OutSize::USIZE).unwrap(),
116            _out: PhantomData,
117        }
118    }
119}
120
121impl<T, OutSize> CustomizedInit for CtOutWrapper<T, OutSize>
122where
123    T: VariableOutputCoreCustomized,
124    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
125{
126    #[inline]
127    fn new_customized(customization: &[u8]) -> Self {
128        Self {
129            inner: T::new_customized(customization, OutSize::USIZE),
130            _out: PhantomData,
131        }
132    }
133}
134
135impl<T, OutSize> Reset for CtOutWrapper<T, OutSize>
136where
137    T: VariableOutputCore,
138    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
139{
140    #[inline]
141    fn reset(&mut self) {
142        *self = Default::default();
143    }
144}
145
146impl<T, OutSize> AlgorithmName for CtOutWrapper<T, OutSize>
147where
148    T: VariableOutputCore + AlgorithmName,
149    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
150{
151    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        T::write_alg_name(f)?;
153        f.write_str("_")?;
154        write!(f, "{}", OutSize::USIZE)
155    }
156}
157
158#[cfg(feature = "zeroize")]
159impl<T, OutSize> zeroize::ZeroizeOnDrop for CtOutWrapper<T, OutSize>
160where
161    T: VariableOutputCore + zeroize::ZeroizeOnDrop,
162    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
163{
164}
165
166impl<T, OutSize> fmt::Debug for CtOutWrapper<T, OutSize>
167where
168    T: VariableOutputCore + AlgorithmName,
169    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
170{
171    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172        Self::write_alg_name(f)
173    }
174}
175
176impl<T, OutSize> SerializableState for CtOutWrapper<T, OutSize>
177where
178    T: VariableOutputCore + SerializableState,
179    OutSize: ArraySize + IsLessOrEqual<T::OutputSize, Output = True>,
180{
181    type SerializedStateSize = <T as SerializableState>::SerializedStateSize;
182
183    fn serialize(&self) -> SerializedState<Self> {
184        self.inner.serialize()
185    }
186
187    fn deserialize(
188        serialized_state: &SerializedState<Self>,
189    ) -> Result<Self, DeserializeStateError> {
190        let _out = PhantomData;
191        T::deserialize(serialized_state).map(|inner| Self { inner, _out })
192    }
193}