block_modes/
pcbc.rs

1use crate::{
2    traits::{BlockMode, IvState},
3    utils::{xor, Block},
4};
5use block_padding::Padding;
6use cipher::{generic_array::GenericArray, BlockCipher, BlockDecrypt, BlockEncrypt};
7use core::marker::PhantomData;
8
9/// [Propagating Cipher Block Chaining][1] (PCBC) mode instance.
10///
11/// [1]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#PCBC
12#[derive(Clone)]
13pub struct Pcbc<C: BlockCipher + BlockEncrypt + BlockDecrypt, P: Padding> {
14    cipher: C,
15    iv: GenericArray<u8, C::BlockSize>,
16    _p: PhantomData<P>,
17}
18
19impl<C, P> Pcbc<C, P>
20where
21    C: BlockCipher + BlockEncrypt + BlockDecrypt,
22    P: Padding,
23{
24    /// Initialize PCBC
25    pub fn new(cipher: C, iv: &Block<C>) -> Self {
26        Self {
27            cipher,
28            iv: iv.clone(),
29            _p: Default::default(),
30        }
31    }
32}
33
34impl<C, P> BlockMode<C, P> for Pcbc<C, P>
35where
36    C: BlockCipher + BlockEncrypt + BlockDecrypt,
37    P: Padding,
38{
39    type IvSize = C::BlockSize;
40
41    fn new(cipher: C, iv: &GenericArray<u8, C::BlockSize>) -> Self {
42        Self {
43            cipher,
44            iv: iv.clone(),
45            _p: Default::default(),
46        }
47    }
48
49    fn encrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
50        for block in blocks {
51            let plaintext = block.clone();
52            xor(block, &self.iv);
53            self.cipher.encrypt_block(block);
54            self.iv = plaintext;
55            xor(&mut self.iv, block);
56        }
57    }
58
59    fn decrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
60        for block in blocks {
61            let ciphertext = block.clone();
62            self.cipher.decrypt_block(block);
63            xor(block, &self.iv);
64            self.iv = ciphertext;
65            xor(&mut self.iv, block);
66        }
67    }
68}
69
70impl<C, P> IvState<C, P> for Pcbc<C, P>
71where
72    C: BlockCipher + BlockEncrypt + BlockDecrypt,
73    P: Padding,
74{
75    fn iv_state(&self) -> GenericArray<u8, Self::IvSize> {
76        self.iv.clone()
77    }
78}