digest/core_api/
ct_variable.rs

1use super::{
2    AlgorithmName, Buffer, BufferKindUser, FixedOutputCore, Reset, TruncSide, UpdateCore,
3    VariableOutputCore,
4};
5use crate::HashMarker;
6#[cfg(feature = "mac")]
7use crate::MacMarker;
8#[cfg(feature = "oid")]
9use const_oid::{AssociatedOid, ObjectIdentifier};
10use core::{fmt, marker::PhantomData};
11use crypto_common::{
12    generic_array::{ArrayLength, GenericArray},
13    typenum::{IsLess, IsLessOrEqual, Le, LeEq, NonZero, U256},
14    Block, BlockSizeUser, OutputSizeUser,
15};
16
17/// Dummy type used with [`CtVariableCoreWrapper`] in cases when
18/// resulting hash does not have a known OID.
19#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
20pub struct NoOid;
21
22/// Wrapper around [`VariableOutputCore`] which selects output size
23/// at compile time.
24#[derive(Clone)]
25pub struct CtVariableCoreWrapper<T, OutSize, O = NoOid>
26where
27    T: VariableOutputCore,
28    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
29    LeEq<OutSize, T::OutputSize>: NonZero,
30    T::BlockSize: IsLess<U256>,
31    Le<T::BlockSize, U256>: NonZero,
32{
33    inner: T,
34    _out: PhantomData<(OutSize, O)>,
35}
36
37impl<T, OutSize, O> HashMarker for CtVariableCoreWrapper<T, OutSize, O>
38where
39    T: VariableOutputCore + HashMarker,
40    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
41    LeEq<OutSize, T::OutputSize>: NonZero,
42    T::BlockSize: IsLess<U256>,
43    Le<T::BlockSize, U256>: NonZero,
44{
45}
46
47#[cfg(feature = "mac")]
48impl<T, OutSize, O> MacMarker for CtVariableCoreWrapper<T, OutSize, O>
49where
50    T: VariableOutputCore + MacMarker,
51    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
52    LeEq<OutSize, T::OutputSize>: NonZero,
53    T::BlockSize: IsLess<U256>,
54    Le<T::BlockSize, U256>: NonZero,
55{
56}
57
58impl<T, OutSize, O> BlockSizeUser for CtVariableCoreWrapper<T, OutSize, O>
59where
60    T: VariableOutputCore,
61    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
62    LeEq<OutSize, T::OutputSize>: NonZero,
63    T::BlockSize: IsLess<U256>,
64    Le<T::BlockSize, U256>: NonZero,
65{
66    type BlockSize = T::BlockSize;
67}
68
69impl<T, OutSize, O> UpdateCore for CtVariableCoreWrapper<T, OutSize, O>
70where
71    T: VariableOutputCore,
72    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
73    LeEq<OutSize, T::OutputSize>: NonZero,
74    T::BlockSize: IsLess<U256>,
75    Le<T::BlockSize, U256>: NonZero,
76{
77    #[inline]
78    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
79        self.inner.update_blocks(blocks);
80    }
81}
82
83impl<T, OutSize, O> OutputSizeUser for CtVariableCoreWrapper<T, OutSize, O>
84where
85    T: VariableOutputCore,
86    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize> + 'static,
87    LeEq<OutSize, T::OutputSize>: NonZero,
88    T::BlockSize: IsLess<U256>,
89    Le<T::BlockSize, U256>: NonZero,
90{
91    type OutputSize = OutSize;
92}
93
94impl<T, OutSize, O> BufferKindUser for CtVariableCoreWrapper<T, OutSize, O>
95where
96    T: VariableOutputCore,
97    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
98    LeEq<OutSize, T::OutputSize>: NonZero,
99    T::BlockSize: IsLess<U256>,
100    Le<T::BlockSize, U256>: NonZero,
101{
102    type BufferKind = T::BufferKind;
103}
104
105impl<T, OutSize, O> FixedOutputCore for CtVariableCoreWrapper<T, OutSize, O>
106where
107    T: VariableOutputCore,
108    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize> + 'static,
109    LeEq<OutSize, T::OutputSize>: NonZero,
110    T::BlockSize: IsLess<U256>,
111    Le<T::BlockSize, U256>: NonZero,
112{
113    #[inline]
114    fn finalize_fixed_core(
115        &mut self,
116        buffer: &mut Buffer<Self>,
117        out: &mut GenericArray<u8, Self::OutputSize>,
118    ) {
119        let mut full_res = Default::default();
120        self.inner.finalize_variable_core(buffer, &mut full_res);
121        let n = out.len();
122        let m = full_res.len() - n;
123        match T::TRUNC_SIDE {
124            TruncSide::Left => out.copy_from_slice(&full_res[..n]),
125            TruncSide::Right => out.copy_from_slice(&full_res[m..]),
126        }
127    }
128}
129
130impl<T, OutSize, O> Default for CtVariableCoreWrapper<T, OutSize, O>
131where
132    T: VariableOutputCore,
133    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
134    LeEq<OutSize, T::OutputSize>: NonZero,
135    T::BlockSize: IsLess<U256>,
136    Le<T::BlockSize, U256>: NonZero,
137{
138    #[inline]
139    fn default() -> Self {
140        Self {
141            inner: T::new(OutSize::USIZE).unwrap(),
142            _out: PhantomData,
143        }
144    }
145}
146
147impl<T, OutSize, O> Reset for CtVariableCoreWrapper<T, OutSize, O>
148where
149    T: VariableOutputCore,
150    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
151    LeEq<OutSize, T::OutputSize>: NonZero,
152    T::BlockSize: IsLess<U256>,
153    Le<T::BlockSize, U256>: NonZero,
154{
155    #[inline]
156    fn reset(&mut self) {
157        *self = Default::default();
158    }
159}
160
161impl<T, OutSize, O> AlgorithmName for CtVariableCoreWrapper<T, OutSize, O>
162where
163    T: VariableOutputCore + AlgorithmName,
164    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
165    LeEq<OutSize, T::OutputSize>: NonZero,
166    T::BlockSize: IsLess<U256>,
167    Le<T::BlockSize, U256>: NonZero,
168{
169    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
170        T::write_alg_name(f)?;
171        f.write_str("_")?;
172        write!(f, "{}", OutSize::USIZE)
173    }
174}
175
176#[cfg(feature = "oid")]
177#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
178impl<T, OutSize, O> AssociatedOid for CtVariableCoreWrapper<T, OutSize, O>
179where
180    T: VariableOutputCore,
181    O: AssociatedOid,
182    OutSize: ArrayLength<u8> + IsLessOrEqual<T::OutputSize>,
183    LeEq<OutSize, T::OutputSize>: NonZero,
184    T::BlockSize: IsLess<U256>,
185    Le<T::BlockSize, U256>: NonZero,
186{
187    const OID: ObjectIdentifier = O::OID;
188}
189
190/// Implement dummy type with hidden docs which is used to "carry" hasher
191/// OID for [`CtVariableCoreWrapper`].
192#[macro_export]
193macro_rules! impl_oid_carrier {
194    ($name:ident, $oid:literal) => {
195        #[doc(hidden)]
196        #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
197        pub struct $name;
198
199        #[cfg(feature = "oid")]
200        impl AssociatedOid for $name {
201            const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap($oid);
202        }
203    };
204}