1use cipher::{
2 consts::U1,
3 crypto_common::{InnerUser, IvSizeUser},
4 generic_array::{ArrayLength, GenericArray},
5 inout::InOut,
6 AlgorithmName, AsyncStreamCipher, Block, BlockBackend, BlockCipher, BlockClosure, BlockDecrypt,
7 BlockEncryptMut, BlockSizeUser, InnerIvInit, Iv, IvState, ParBlocksSizeUser, Unsigned,
8};
9use core::fmt;
10
11#[cfg(feature = "zeroize")]
12use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
13
14#[derive(Clone)]
16pub struct Encryptor<C>
17where
18 C: BlockEncryptMut + BlockCipher,
19{
20 cipher: C,
21 iv: Block<C>,
22}
23
24#[derive(Clone)]
26pub struct BufEncryptor<C>
27where
28 C: BlockEncryptMut + BlockCipher,
29{
30 cipher: C,
31 iv: Block<C>,
32 pos: usize,
33}
34
35impl<C> BufEncryptor<C>
36where
37 C: BlockEncryptMut + BlockCipher,
38{
39 pub fn encrypt(&mut self, mut data: &mut [u8]) {
41 let bs = C::BlockSize::USIZE;
42 let n = data.len();
43
44 if n < bs - self.pos {
45 xor_set1(data, &mut self.iv[self.pos..self.pos + n]);
46 self.pos += n;
47 return;
48 }
49
50 let (left, right) = { data }.split_at_mut(bs - self.pos);
51 data = right;
52 let mut iv = self.iv.clone();
53 xor_set1(left, &mut iv[self.pos..]);
54 self.cipher.encrypt_block_mut(&mut iv);
55
56 let mut chunks = data.chunks_exact_mut(bs);
57 for chunk in &mut chunks {
58 xor_set1(chunk, iv.as_mut_slice());
59 self.cipher.encrypt_block_mut(&mut iv);
60 }
61
62 let rem = chunks.into_remainder();
63 xor_set1(rem, iv.as_mut_slice());
64 self.pos = rem.len();
65 self.iv = iv;
66 }
67
68 pub fn get_state(&self) -> (&Block<C>, usize) {
70 (&self.iv, self.pos)
71 }
72
73 pub fn from_state(cipher: C, iv: &Block<C>, pos: usize) -> Self {
75 Self {
76 cipher,
77 iv: iv.clone(),
78 pos,
79 }
80 }
81}
82
83impl<C> BlockSizeUser for Encryptor<C>
84where
85 C: BlockEncryptMut + BlockCipher,
86{
87 type BlockSize = C::BlockSize;
88}
89
90impl<C> BlockEncryptMut for Encryptor<C>
91where
92 C: BlockEncryptMut + BlockCipher,
93{
94 fn encrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) {
95 let Self { cipher, iv } = self;
96 cipher.encrypt_with_backend_mut(Closure { iv, f })
97 }
98}
99
100impl<C> AsyncStreamCipher for Encryptor<C> where C: BlockEncryptMut + BlockCipher {}
101
102impl<C> InnerUser for Encryptor<C>
103where
104 C: BlockEncryptMut + BlockCipher,
105{
106 type Inner = C;
107}
108
109impl<C> InnerUser for BufEncryptor<C>
110where
111 C: BlockEncryptMut + BlockCipher,
112{
113 type Inner = C;
114}
115
116impl<C> IvSizeUser for Encryptor<C>
117where
118 C: BlockEncryptMut + BlockCipher,
119{
120 type IvSize = C::BlockSize;
121}
122
123impl<C> IvSizeUser for BufEncryptor<C>
124where
125 C: BlockEncryptMut + BlockCipher,
126{
127 type IvSize = C::BlockSize;
128}
129
130impl<C> InnerIvInit for Encryptor<C>
131where
132 C: BlockEncryptMut + BlockCipher,
133{
134 #[inline]
135 fn inner_iv_init(mut cipher: C, iv: &Iv<Self>) -> Self {
136 let mut iv = iv.clone();
137 cipher.encrypt_block_mut(&mut iv);
138 Self { cipher, iv }
139 }
140}
141
142impl<C> InnerIvInit for BufEncryptor<C>
143where
144 C: BlockEncryptMut + BlockCipher,
145{
146 #[inline]
147 fn inner_iv_init(mut cipher: C, iv: &Iv<Self>) -> Self {
148 let mut iv = iv.clone();
149 cipher.encrypt_block_mut(&mut iv);
150 Self { cipher, iv, pos: 0 }
151 }
152}
153
154impl<C> IvState for Encryptor<C>
155where
156 C: BlockEncryptMut + BlockDecrypt + BlockCipher,
157{
158 #[inline]
159 fn iv_state(&self) -> Iv<Self> {
160 let mut res = self.iv.clone();
161 self.cipher.decrypt_block(&mut res);
162 res
163 }
164}
165
166impl<C> AlgorithmName for BufEncryptor<C>
167where
168 C: BlockEncryptMut + BlockCipher + AlgorithmName,
169{
170 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 f.write_str("cfb::BufEncryptor<")?;
172 <C as AlgorithmName>::write_alg_name(f)?;
173 f.write_str(">")
174 }
175}
176
177impl<C> AlgorithmName for Encryptor<C>
178where
179 C: BlockEncryptMut + BlockCipher + AlgorithmName,
180{
181 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 f.write_str("cfb::Encryptor<")?;
183 <C as AlgorithmName>::write_alg_name(f)?;
184 f.write_str(">")
185 }
186}
187
188impl<C> fmt::Debug for Encryptor<C>
189where
190 C: BlockEncryptMut + BlockCipher + AlgorithmName,
191{
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 f.write_str("cfb::Encryptor<")?;
194 <C as AlgorithmName>::write_alg_name(f)?;
195 f.write_str("> { ... }")
196 }
197}
198
199impl<C> fmt::Debug for BufEncryptor<C>
200where
201 C: BlockEncryptMut + BlockCipher + AlgorithmName,
202{
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 f.write_str("cfb::BufEncryptor<")?;
205 <C as AlgorithmName>::write_alg_name(f)?;
206 f.write_str("> { ... }")
207 }
208}
209
210#[cfg(feature = "zeroize")]
211#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
212impl<C: BlockEncryptMut + BlockCipher> Drop for Encryptor<C> {
213 fn drop(&mut self) {
214 self.iv.zeroize();
215 }
216}
217
218#[cfg(feature = "zeroize")]
219#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
220impl<C: BlockEncryptMut + BlockCipher> Drop for BufEncryptor<C> {
221 fn drop(&mut self) {
222 self.iv.zeroize();
223 }
224}
225
226#[cfg(feature = "zeroize")]
227#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
228impl<C: BlockEncryptMut + BlockCipher + ZeroizeOnDrop> ZeroizeOnDrop for Encryptor<C> {}
229
230#[cfg(feature = "zeroize")]
231#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
232impl<C: BlockEncryptMut + BlockCipher + ZeroizeOnDrop> ZeroizeOnDrop for BufEncryptor<C> {}
233
234struct Closure<'a, BS, BC>
235where
236 BS: ArrayLength<u8>,
237 BC: BlockClosure<BlockSize = BS>,
238{
239 iv: &'a mut GenericArray<u8, BS>,
240 f: BC,
241}
242
243impl<'a, BS, BC> BlockSizeUser for Closure<'a, BS, BC>
244where
245 BS: ArrayLength<u8>,
246 BC: BlockClosure<BlockSize = BS>,
247{
248 type BlockSize = BS;
249}
250
251impl<'a, BS, BC> BlockClosure for Closure<'a, BS, BC>
252where
253 BS: ArrayLength<u8>,
254 BC: BlockClosure<BlockSize = BS>,
255{
256 #[inline(always)]
257 fn call<B: BlockBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B) {
258 let Self { iv, f } = self;
259 f.call(&mut Backend { iv, backend });
260 }
261}
262
263struct Backend<'a, BS, BK>
264where
265 BS: ArrayLength<u8>,
266 BK: BlockBackend<BlockSize = BS>,
267{
268 iv: &'a mut GenericArray<u8, BS>,
269 backend: &'a mut BK,
270}
271
272impl<'a, BS, BK> BlockSizeUser for Backend<'a, BS, BK>
273where
274 BS: ArrayLength<u8>,
275 BK: BlockBackend<BlockSize = BS>,
276{
277 type BlockSize = BS;
278}
279
280impl<'a, BS, BK> ParBlocksSizeUser for Backend<'a, BS, BK>
281where
282 BS: ArrayLength<u8>,
283 BK: BlockBackend<BlockSize = BS>,
284{
285 type ParBlocksSize = U1;
286}
287
288impl<'a, BS, BK> BlockBackend for Backend<'a, BS, BK>
289where
290 BS: ArrayLength<u8>,
291 BK: BlockBackend<BlockSize = BS>,
292{
293 #[inline(always)]
294 fn proc_block(&mut self, mut block: InOut<'_, '_, Block<Self>>) {
295 block.xor_in2out(self.iv);
296 let mut t = block.get_out().clone();
297 self.backend.proc_block((&mut t).into());
298 *self.iv = t;
299 }
300}
301
302#[inline(always)]
303fn xor_set1(buf1: &mut [u8], buf2: &mut [u8]) {
304 for (a, b) in buf1.iter_mut().zip(buf2) {
305 let t = *a ^ *b;
306 *a = t;
307 *b = t;
308 }
309}