cbc/
decrypt.rs

1use crate::xor;
2use cipher::{
3    crypto_common::{InnerUser, IvSizeUser},
4    generic_array::{ArrayLength, GenericArray},
5    inout::InOut,
6    AlgorithmName, Block, BlockBackend, BlockCipher, BlockClosure, BlockDecryptMut, BlockSizeUser,
7    InnerIvInit, Iv, IvState, ParBlocks, ParBlocksSizeUser,
8};
9use core::fmt;
10
11#[cfg(feature = "zeroize")]
12use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
13
14/// CBC mode decryptor.
15#[derive(Clone)]
16pub struct Decryptor<C>
17where
18    C: BlockDecryptMut + BlockCipher,
19{
20    cipher: C,
21    iv: Block<C>,
22}
23
24impl<C> BlockSizeUser for Decryptor<C>
25where
26    C: BlockDecryptMut + BlockCipher,
27{
28    type BlockSize = C::BlockSize;
29}
30
31impl<C> BlockDecryptMut for Decryptor<C>
32where
33    C: BlockDecryptMut + BlockCipher,
34{
35    fn decrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) {
36        let Self { cipher, iv } = self;
37        cipher.decrypt_with_backend_mut(Closure { iv, f })
38    }
39}
40
41impl<C> InnerUser for Decryptor<C>
42where
43    C: BlockDecryptMut + BlockCipher,
44{
45    type Inner = C;
46}
47
48impl<C> IvSizeUser for Decryptor<C>
49where
50    C: BlockDecryptMut + BlockCipher,
51{
52    type IvSize = C::BlockSize;
53}
54
55impl<C> InnerIvInit for Decryptor<C>
56where
57    C: BlockDecryptMut + BlockCipher,
58{
59    #[inline]
60    fn inner_iv_init(cipher: C, iv: &Iv<Self>) -> Self {
61        Self {
62            cipher,
63            iv: iv.clone(),
64        }
65    }
66}
67
68impl<C> IvState for Decryptor<C>
69where
70    C: BlockDecryptMut + BlockCipher,
71{
72    #[inline]
73    fn iv_state(&self) -> Iv<Self> {
74        self.iv.clone()
75    }
76}
77
78impl<C> AlgorithmName for Decryptor<C>
79where
80    C: BlockDecryptMut + BlockCipher + AlgorithmName,
81{
82    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        f.write_str("cbc::Decryptor<")?;
84        <C as AlgorithmName>::write_alg_name(f)?;
85        f.write_str(">")
86    }
87}
88
89impl<C> fmt::Debug for Decryptor<C>
90where
91    C: BlockDecryptMut + BlockCipher + AlgorithmName,
92{
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        f.write_str("cbc::Decryptor<")?;
95        <C as AlgorithmName>::write_alg_name(f)?;
96        f.write_str("> { ... }")
97    }
98}
99
100#[cfg(feature = "zeroize")]
101#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
102impl<C: BlockDecryptMut + BlockCipher> Drop for Decryptor<C> {
103    fn drop(&mut self) {
104        self.iv.zeroize();
105    }
106}
107
108#[cfg(feature = "zeroize")]
109#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
110impl<C: BlockDecryptMut + BlockCipher + ZeroizeOnDrop> ZeroizeOnDrop for Decryptor<C> {}
111
112struct Closure<'a, BS, BC>
113where
114    BS: ArrayLength<u8>,
115    BC: BlockClosure<BlockSize = BS>,
116{
117    iv: &'a mut GenericArray<u8, BS>,
118    f: BC,
119}
120
121impl<'a, BS, BC> BlockSizeUser for Closure<'a, BS, BC>
122where
123    BS: ArrayLength<u8>,
124    BC: BlockClosure<BlockSize = BS>,
125{
126    type BlockSize = BS;
127}
128
129impl<'a, BS, BC> BlockClosure for Closure<'a, BS, BC>
130where
131    BS: ArrayLength<u8>,
132    BC: BlockClosure<BlockSize = BS>,
133{
134    #[inline(always)]
135    fn call<B: BlockBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) {
136        let Self { iv, f } = self;
137        f.call(&mut Backend { iv, backend });
138    }
139}
140
141struct Backend<'a, BS, BK>
142where
143    BS: ArrayLength<u8>,
144    BK: BlockBackend<BlockSize = BS>,
145{
146    iv: &'a mut GenericArray<u8, BS>,
147    backend: &'a mut BK,
148}
149
150impl<'a, BS, BK> BlockSizeUser for Backend<'a, BS, BK>
151where
152    BS: ArrayLength<u8>,
153    BK: BlockBackend<BlockSize = BS>,
154{
155    type BlockSize = BS;
156}
157
158impl<'a, BS, BK> ParBlocksSizeUser for Backend<'a, BS, BK>
159where
160    BS: ArrayLength<u8>,
161    BK: BlockBackend<BlockSize = BS>,
162{
163    type ParBlocksSize = BK::ParBlocksSize;
164}
165
166impl<'a, BS, BK> BlockBackend for Backend<'a, BS, BK>
167where
168    BS: ArrayLength<u8>,
169    BK: BlockBackend<BlockSize = BS>,
170{
171    #[inline(always)]
172    fn proc_block(&mut self, mut block: InOut<'_, '_, Block<Self>>) {
173        let in_block = block.clone_in();
174        let mut t = block.clone_in();
175        self.backend.proc_block((&mut t).into());
176        xor(&mut t, self.iv);
177        *block.get_out() = t;
178        *self.iv = in_block;
179    }
180
181    #[inline(always)]
182    fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, ParBlocks<Self>>) {
183        let in_blocks = blocks.clone_in();
184        let mut t = blocks.clone_in();
185
186        self.backend.proc_par_blocks((&mut t).into());
187        let n = t.len();
188        xor(&mut t[0], self.iv);
189        for i in 1..n {
190            xor(&mut t[i], &in_blocks[i - 1])
191        }
192        *blocks.get_out() = t;
193        *self.iv = in_blocks[n - 1].clone();
194    }
195}