block_modes/
ige.rs

1use crate::{
2    traits::{BlockMode, IvState},
3    utils::{xor, Block},
4};
5use block_padding::Padding;
6use cipher::{
7    generic_array::{
8        sequence::Concat,
9        typenum::{Sum, Unsigned},
10        ArrayLength, GenericArray,
11    },
12    BlockCipher, BlockDecrypt, BlockEncrypt,
13};
14use core::{marker::PhantomData, ops::Add};
15
16type IgeIvBlockSize<C> = Sum<<C as BlockCipher>::BlockSize, <C as BlockCipher>::BlockSize>;
17
18/// [Infinite Garble Extension][1] (IGE) block cipher mode instance.
19///
20/// [1]: https://www.links.org/files/openssl-ige.pdf
21pub struct Ige<C, P>
22where
23    C: BlockCipher + BlockEncrypt + BlockDecrypt,
24    P: Padding,
25    C::BlockSize: Add,
26    IgeIvBlockSize<C>: ArrayLength<u8>,
27{
28    cipher: C,
29    x: GenericArray<u8, C::BlockSize>,
30    y: GenericArray<u8, C::BlockSize>,
31    _p: PhantomData<P>,
32}
33
34impl<C, P> BlockMode<C, P> for Ige<C, P>
35where
36    C: BlockCipher + BlockEncrypt + BlockDecrypt,
37    P: Padding,
38    C::BlockSize: Add,
39    IgeIvBlockSize<C>: ArrayLength<u8>,
40{
41    type IvSize = IgeIvBlockSize<C>;
42
43    fn new(cipher: C, iv: &GenericArray<u8, Self::IvSize>) -> Self {
44        let (y, x) = iv.split_at(C::BlockSize::to_usize());
45        Ige {
46            cipher,
47            x: GenericArray::clone_from_slice(x),
48            y: GenericArray::clone_from_slice(y),
49            _p: Default::default(),
50        }
51    }
52
53    fn encrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
54        for block in blocks {
55            let t = block.clone();
56            xor(block, &self.y);
57            self.cipher.encrypt_block(block);
58            xor(block, &self.x);
59            self.x = t;
60            self.y = block.clone();
61        }
62    }
63
64    fn decrypt_blocks(&mut self, blocks: &mut [Block<C>]) {
65        for block in blocks {
66            let t = block.clone();
67            xor(block, &self.x);
68            self.cipher.decrypt_block(block);
69            xor(block, &self.y);
70            self.y = t;
71            self.x = block.clone();
72        }
73    }
74}
75
76impl<C, P> IvState<C, P> for Ige<C, P>
77where
78    C: BlockCipher + BlockEncrypt + BlockDecrypt,
79    P: Padding,
80    C::BlockSize: Add,
81    IgeIvBlockSize<C>: ArrayLength<u8>,
82{
83    fn iv_state(&self) -> GenericArray<u8, Self::IvSize> {
84        self.y.clone().concat(self.x.clone())
85    }
86}