1use crate::{Decrypt, Encrypt, Error, cbc_dec, cbc_enc, xor};
2use cipher::{
3 Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncBackend,
4 BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InnerIvInit, IvSizeUser,
5 array::{Array, ArraySize},
6 common::InnerUser,
7 inout::InOutBuf,
8 typenum::Unsigned,
9};
10
11#[derive(Debug)]
13pub struct CbcCs3<C: BlockSizeUser> {
14 cipher: C,
15 iv: Block<C>,
16}
17
18impl<C: BlockSizeUser> InnerUser for CbcCs3<C> {
19 type Inner = C;
20}
21
22impl<C: BlockSizeUser> IvSizeUser for CbcCs3<C> {
23 type IvSize = C::BlockSize;
24}
25
26impl<C: BlockSizeUser> InnerIvInit for CbcCs3<C> {
27 fn inner_iv_init(cipher: Self::Inner, iv: &cipher::Iv<Self>) -> Self {
28 Self {
29 cipher,
30 iv: iv.clone(),
31 }
32 }
33}
34
35impl<C: BlockCipherEncrypt> Encrypt for CbcCs3<C> {
36 fn encrypt_inout(self, buf: InOutBuf<'_, '_, u8>) -> Result<(), Error> {
37 if buf.len() < C::BlockSize::USIZE {
38 return Err(Error);
39 }
40 let Self { cipher, iv } = self;
41 cipher.encrypt_with_backend(Closure { iv, buf });
42 Ok(())
43 }
44}
45
46impl<C: BlockCipherDecrypt> Decrypt for CbcCs3<C> {
47 fn decrypt_inout(self, buf: InOutBuf<'_, '_, u8>) -> Result<(), Error> {
48 if buf.len() < C::BlockSize::USIZE {
49 return Err(Error);
50 }
51 let Self { cipher, iv } = self;
52 cipher.decrypt_with_backend(Closure { iv, buf });
53 Ok(())
54 }
55}
56
57struct Closure<'a, BS: ArraySize> {
58 iv: Array<u8, BS>,
59 buf: InOutBuf<'a, 'a, u8>,
60}
61
62impl<BS: ArraySize> BlockSizeUser for Closure<'_, BS> {
63 type BlockSize = BS;
64}
65
66impl<BS: ArraySize> BlockCipherEncClosure for Closure<'_, BS> {
67 fn call<B: BlockCipherEncBackend<BlockSize = BS>>(self, cipher: &B) {
68 let Self { mut iv, mut buf } = self;
69 let (mut blocks, mut tail) = buf.reborrow().into_chunks();
70
71 cbc_enc(cipher, &mut iv, blocks.reborrow());
72
73 if tail.is_empty() && blocks.len() > 1 {
74 let blocks = blocks.get_out();
75 let (last, rest) = blocks.split_last_mut().unwrap();
76 let (penultimate, _) = rest.split_last_mut().unwrap();
77 core::mem::swap(penultimate, last);
78 } else {
79 let mut block = Block::<B>::default();
80 block[..tail.len()].copy_from_slice(tail.get_in());
81 xor(&mut block, &iv);
82 cipher.encrypt_block_inplace(&mut block);
83
84 let penult_block = blocks.get_out().last_mut().unwrap();
85 let val = core::mem::replace(penult_block, block);
86
87 let tail_val = &val[..tail.len()];
88 tail.get_out().copy_from_slice(tail_val);
89 }
90 }
91}
92
93impl<BS: ArraySize> BlockCipherDecClosure for Closure<'_, BS> {
94 fn call<B: BlockCipherDecBackend<BlockSize = BS>>(self, cipher: &B) {
95 let Self { mut iv, buf } = self;
96
97 let bs = B::BlockSize::USIZE;
98 let blocks_len = buf.len().div_ceil(bs);
99 let main_blocks = blocks_len.saturating_sub(2);
100
101 let (blocks, mut tail) = buf.split_at(bs * main_blocks);
102 let (blocks, rem) = blocks.into_chunks();
103 debug_assert_eq!(rem.len(), 0);
104
105 cbc_dec(cipher, &mut iv, blocks);
106
107 let n = tail.len() - bs;
108 let mut block1: Block<B> = tail.get_in()[..bs].try_into().unwrap();
109 cipher.decrypt_block_inplace(&mut block1);
110
111 let mut block2 = Block::<B>::default();
112 block2[..n].copy_from_slice(&tail.get_in()[bs..]);
113 block2[n..].copy_from_slice(&block1[n..]);
114 xor(&mut block1, &block2);
115
116 cipher.decrypt_block_inplace(&mut block2);
117 xor(&mut block2, &iv);
118
119 let (l, r) = tail.get_out().split_at_mut(bs);
120 l.copy_from_slice(&block2);
121 r.copy_from_slice(&block1[..n]);
122 }
123}