1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use crate::traits::BlockMode;
use crate::utils::{xor, Block};
use block_cipher::generic_array::GenericArray;
use block_cipher::{BlockCipher, NewBlockCipher};
use block_padding::Padding;
use core::marker::PhantomData;

/// [Output feedback][1] (CFB) block mode instance with a full block feedback.
///
/// [1]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_feedback_(CFB)
pub struct Ofb<C: BlockCipher + NewBlockCipher, P: Padding> {
    cipher: C,
    iv: GenericArray<u8, C::BlockSize>,
    _p: PhantomData<P>,
}

impl<C, P> BlockMode<C, P> for Ofb<C, P>
where
    C: BlockCipher + NewBlockCipher,
    P: Padding,
{
    fn new(cipher: C, iv: &Block<C>) -> Self {
        Self {
            cipher,
            iv: iv.clone(),
            _p: Default::default(),
        }
    }

    fn encrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
        for block in blocks.iter_mut() {
            self.cipher.encrypt_block(&mut self.iv);
            xor(block, &self.iv);
        }
    }

    fn decrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
        self.encrypt_blocks(blocks)
    }
}