block_modes/
cbc.rs

1use crate::traits::{BlockMode, IvState};
2use crate::utils::{get_par_blocks, xor, Block, ParBlocks};
3use block_padding::Padding;
4use cipher::generic_array::{typenum::Unsigned, GenericArray};
5use cipher::{BlockCipher, BlockDecrypt, BlockEncrypt};
6use core::marker::PhantomData;
7
8/// [Cipher Block Chaining][1] (CBC) block cipher mode instance.
9///
10/// [1]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#CBC
11#[derive(Clone)]
12pub struct Cbc<C: BlockCipher + BlockEncrypt + BlockDecrypt, P: Padding> {
13    cipher: C,
14    iv: GenericArray<u8, C::BlockSize>,
15    _p: PhantomData<P>,
16}
17
18impl<C, P> Cbc<C, P>
19where
20    C: BlockCipher + BlockEncrypt + BlockDecrypt,
21    P: Padding,
22{
23    #[inline(always)]
24    fn single_blocks_decrypt(&mut self, blocks: &mut [Block<C>]) {
25        let mut iv = self.iv.clone();
26        for block in blocks {
27            let block_copy = block.clone();
28            self.cipher.decrypt_block(block);
29            xor(block, iv.as_slice());
30            iv = block_copy;
31        }
32        self.iv = iv;
33    }
34}
35
36impl<C, P> BlockMode<C, P> for Cbc<C, P>
37where
38    C: BlockCipher + BlockEncrypt + BlockDecrypt,
39    P: Padding,
40{
41    type IvSize = C::BlockSize;
42
43    fn new(cipher: C, iv: &Block<C>) -> Self {
44        Self {
45            cipher,
46            iv: iv.clone(),
47            _p: Default::default(),
48        }
49    }
50
51    fn encrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
52        self.iv = {
53            let mut iv = &self.iv;
54            for block in blocks {
55                xor(block, &iv);
56                self.cipher.encrypt_block(block);
57                iv = block;
58            }
59            iv.clone()
60        };
61    }
62
63    fn decrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
64        let pbn = C::ParBlocks::to_usize();
65        if pbn != 1 {
66            let (par_blocks, leftover) = get_par_blocks::<C>(blocks);
67            let mut iv_buf = ParBlocks::<C>::default();
68            iv_buf[0] = self.iv.clone();
69            for pb in par_blocks {
70                iv_buf[1..].clone_from_slice(&pb[..pbn - 1]);
71                let next_iv = pb[pbn - 1].clone();
72                self.cipher.decrypt_blocks(pb);
73                pb.iter_mut()
74                    .zip(iv_buf.iter())
75                    .for_each(|(a, b)| xor(a, b));
76                iv_buf[0] = next_iv;
77            }
78            self.iv = iv_buf[0].clone();
79            self.single_blocks_decrypt(leftover);
80        } else {
81            self.single_blocks_decrypt(blocks);
82        }
83    }
84}
85
86impl<C, P> IvState<C, P> for Cbc<C, P>
87where
88    C: BlockCipher + BlockEncrypt + BlockDecrypt,
89    P: Padding,
90{
91    fn iv_state(&self) -> GenericArray<u8, <Self as BlockMode<C, P>>::IvSize> {
92        self.iv.clone()
93    }
94}