cfb_mode/
encrypt.rs

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/// CFB mode encryptor.
15#[derive(Clone)]
16pub struct Encryptor<C>
17where
18    C: BlockEncryptMut + BlockCipher,
19{
20    cipher: C,
21    iv: Block<C>,
22}
23
24/// CFB mode buffered encryptor.
25#[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    /// Encrypt a buffer in multiple parts.
40    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    /// Returns the current state (block and position) of the decryptor.
69    pub fn get_state(&self) -> (&Block<C>, usize) {
70        (&self.iv, self.pos)
71    }
72
73    /// Restore from the given state for resumption.
74    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}