block_modes/
cfb.rs

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/// [Cipher feedback][1] (CFB) block mode instance with a full block feedback.
13///
14/// [1]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_feedback_(CFB)
15#[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            // SAFETY: we have checked that `blocks` has enough elements
49            #[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            // Remember IV for trailing blocks
58            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    // SAFETY: assert checks that `blocks` is long enough
102    #[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}