1use crate::{
2 traits::{BlockMode, IvState},
3 utils::{xor, Block, ParBlocks},
4};
5use block_padding::Padding;
6use cipher::{
7 generic_array::{typenum::Unsigned, GenericArray},
8 BlockCipher, BlockEncrypt,
9};
10use core::{marker::PhantomData, ptr};
11
12#[derive(Clone)]
16pub struct Cfb<C: BlockCipher + BlockEncrypt, P: Padding> {
17 cipher: C,
18 iv: GenericArray<u8, C::BlockSize>,
19 _p: PhantomData<P>,
20}
21
22impl<C, P> BlockMode<C, P> for Cfb<C, P>
23where
24 C: BlockCipher + BlockEncrypt,
25 P: Padding,
26{
27 type IvSize = C::BlockSize;
28
29 fn new(cipher: C, iv: &Block<C>) -> Self {
30 Self {
31 cipher,
32 iv: iv.clone(),
33 _p: Default::default(),
34 }
35 }
36
37 fn encrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
38 for block in blocks {
39 self.cipher.encrypt_block(&mut self.iv);
40 xor_set1(block, self.iv.as_mut_slice());
41 }
42 }
43
44 fn decrypt_blocks(&mut self, mut blocks: &mut [Block<C>]) {
45 let pb = C::ParBlocks::to_usize();
46
47 if blocks.len() > pb {
48 #[allow(unsafe_code)]
50 let mut par_iv = read_par_block::<C>(&blocks[..pb]);
51
52 let (b, r) = { blocks }.split_at_mut(1);
53 blocks = r;
54 self.cipher.encrypt_block(&mut self.iv);
55 xor(&mut b[0], &self.iv);
56
57 self.iv = blocks[blocks.len() - (blocks.len() % pb) - 1].clone();
59
60 while blocks.len() >= 2 * pb {
61 let next_par_iv = read_par_block::<C>(&blocks[pb - 1..2 * pb - 1]);
62 self.cipher.encrypt_blocks(&mut par_iv);
63 let (par_block, r) = { blocks }.split_at_mut(pb);
64 blocks = r;
65
66 for (a, b) in par_block.iter_mut().zip(par_iv.iter()) {
67 xor(a, b)
68 }
69 par_iv = next_par_iv;
70 }
71
72 self.cipher.encrypt_blocks(&mut par_iv);
73 let (par_block, r) = { blocks }.split_at_mut(pb);
74 blocks = r;
75
76 for (a, b) in par_block.iter_mut().zip(par_iv[..pb].iter()) {
77 xor(a, b)
78 }
79 }
80
81 for block in blocks {
82 self.cipher.encrypt_block(&mut self.iv);
83 xor_set2(block, self.iv.as_mut_slice());
84 }
85 }
86}
87
88impl<C, P> IvState<C, P> for Cfb<C, P>
89where
90 C: BlockCipher + BlockEncrypt,
91 P: Padding,
92{
93 fn iv_state(&self) -> GenericArray<u8, Self::IvSize> {
94 self.iv.clone()
95 }
96}
97
98#[inline(always)]
99fn read_par_block<C: BlockCipher>(blocks: &[Block<C>]) -> ParBlocks<C> {
100 assert!(blocks.len() >= C::ParBlocks::to_usize());
101 #[allow(unsafe_code)]
103 unsafe {
104 ptr::read(blocks.as_ptr() as *const ParBlocks<C>)
105 }
106}
107
108#[inline(always)]
109fn xor_set1(buf1: &mut [u8], buf2: &mut [u8]) {
110 for (a, b) in buf1.iter_mut().zip(buf2) {
111 let t = *a ^ *b;
112 *a = t;
113 *b = t;
114 }
115}
116
117#[inline(always)]
118fn xor_set2(buf1: &mut [u8], buf2: &mut [u8]) {
119 for (a, b) in buf1.iter_mut().zip(buf2) {
120 let t = *a;
121 *a ^= *b;
122 *b = t;
123 }
124}