Skip to main content

cfb_mode/encrypt/
buf.rs

1use super::xor_set1;
2use cipher::{
3    AlgorithmName, Block, BlockCipherEncrypt, InnerIvInit, Iv, IvSizeUser, common::InnerUser,
4    typenum::Unsigned,
5};
6use core::fmt;
7
8#[cfg(feature = "zeroize")]
9use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
10
11/// CFB mode buffered encryptor.
12pub struct BufEncryptor<C>
13where
14    C: BlockCipherEncrypt,
15{
16    cipher: C,
17    iv: Block<C>,
18    pos: usize,
19}
20
21impl<C> BufEncryptor<C>
22where
23    C: BlockCipherEncrypt,
24{
25    /// Encrypt a buffer in multiple parts.
26    pub fn encrypt(&mut self, mut data: &mut [u8]) {
27        let bs = C::BlockSize::USIZE;
28        let n = data.len();
29
30        if n < bs - self.pos {
31            xor_set1(data, &mut self.iv[self.pos..self.pos + n]);
32            self.pos += n;
33            return;
34        }
35
36        let (left, right) = { data }.split_at_mut(bs - self.pos);
37        data = right;
38        let mut iv = self.iv.clone();
39        xor_set1(left, &mut iv[self.pos..]);
40        self.cipher.encrypt_block(&mut iv);
41
42        let mut chunks = data.chunks_exact_mut(bs);
43        for chunk in &mut chunks {
44            xor_set1(chunk, iv.as_mut_slice());
45            self.cipher.encrypt_block(&mut iv);
46        }
47
48        let rem = chunks.into_remainder();
49        xor_set1(rem, iv.as_mut_slice());
50        self.pos = rem.len();
51        self.iv = iv;
52    }
53
54    /// Returns the current state (block and position) of the decryptor.
55    pub fn get_state(&self) -> (&Block<C>, usize) {
56        (&self.iv, self.pos)
57    }
58
59    /// Restore from the given state for resumption.
60    pub fn from_state(cipher: C, iv: &Block<C>, pos: usize) -> Self {
61        Self {
62            cipher,
63            iv: iv.clone(),
64            pos,
65        }
66    }
67}
68
69impl<C> InnerUser for BufEncryptor<C>
70where
71    C: BlockCipherEncrypt,
72{
73    type Inner = C;
74}
75
76impl<C> IvSizeUser for BufEncryptor<C>
77where
78    C: BlockCipherEncrypt,
79{
80    type IvSize = C::BlockSize;
81}
82
83impl<C> InnerIvInit for BufEncryptor<C>
84where
85    C: BlockCipherEncrypt,
86{
87    #[inline]
88    fn inner_iv_init(cipher: C, iv: &Iv<Self>) -> Self {
89        let mut iv = iv.clone();
90        cipher.encrypt_block(&mut iv);
91        Self { cipher, iv, pos: 0 }
92    }
93}
94
95impl<C> AlgorithmName for BufEncryptor<C>
96where
97    C: BlockCipherEncrypt + AlgorithmName,
98{
99    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        f.write_str("cfb::BufEncryptor<")?;
101        <C as AlgorithmName>::write_alg_name(f)?;
102        f.write_str(">")
103    }
104}
105
106impl<C> fmt::Debug for BufEncryptor<C>
107where
108    C: BlockCipherEncrypt + AlgorithmName,
109{
110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111        f.write_str("cfb::BufEncryptor<")?;
112        <C as AlgorithmName>::write_alg_name(f)?;
113        f.write_str("> { ... }")
114    }
115}
116
117impl<C: BlockCipherEncrypt> Drop for BufEncryptor<C> {
118    fn drop(&mut self) {
119        #[cfg(feature = "zeroize")]
120        self.iv.zeroize();
121    }
122}
123
124#[cfg(feature = "zeroize")]
125impl<C: BlockCipherEncrypt + ZeroizeOnDrop> ZeroizeOnDrop for BufEncryptor<C> {}