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
18pub 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}