cbc/
encrypt.rs

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