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#[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 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}