1#[cfg(feature = "alloc")]
2pub use alloc::vec::Vec;
3
4use crate::{
5 errors::{BlockModeError, InvalidKeyIvLength},
6 utils::{to_blocks, Block, Key},
7};
8use block_padding::Padding;
9use cipher::{
10 generic_array::{typenum::Unsigned, ArrayLength, GenericArray},
11 BlockCipher, NewBlockCipher,
12};
13
14pub trait BlockMode<C: BlockCipher, P: Padding>: Sized {
17 type IvSize: ArrayLength<u8>;
19
20 fn new(cipher: C, iv: &GenericArray<u8, Self::IvSize>) -> Self;
22
23 fn new_fix(key: &Key<C>, iv: &GenericArray<u8, Self::IvSize>) -> Self
25 where
26 C: NewBlockCipher,
27 {
28 Self::new(C::new(key), iv)
29 }
30
31 fn new_from_slices(key: &[u8], iv: &[u8]) -> Result<Self, InvalidKeyIvLength>
35 where
36 C: NewBlockCipher,
37 {
38 if iv.len() != Self::IvSize::USIZE {
39 return Err(InvalidKeyIvLength);
40 }
41 let iv = GenericArray::from_slice(iv);
42 let cipher = C::new_from_slice(key).map_err(|_| InvalidKeyIvLength)?;
43 Ok(Self::new(cipher, iv))
44 }
45
46 fn encrypt_blocks(&mut self, blocks: &mut [Block<C>]);
48
49 fn decrypt_blocks(&mut self, blocks: &mut [Block<C>]);
51
52 fn encrypt(mut self, buffer: &mut [u8], pos: usize) -> Result<&[u8], BlockModeError> {
58 let bs = C::BlockSize::to_usize();
59 let buf = P::pad(buffer, pos, bs).map_err(|_| BlockModeError)?;
60 self.encrypt_blocks(to_blocks(buf));
61 Ok(buf)
62 }
63
64 fn decrypt(mut self, buffer: &mut [u8]) -> Result<&[u8], BlockModeError> {
69 let bs = C::BlockSize::to_usize();
70 if buffer.len() % bs != 0 {
71 return Err(BlockModeError);
72 }
73 self.decrypt_blocks(to_blocks(buffer));
74 P::unpad(buffer).map_err(|_| BlockModeError)
75 }
76
77 #[cfg(feature = "alloc")]
79 fn encrypt_vec(mut self, plaintext: &[u8]) -> Vec<u8> {
80 let bs = C::BlockSize::to_usize();
81 let pos = plaintext.len();
82 let n = pos + bs;
83 let mut buf = Vec::with_capacity(n);
84 buf.extend_from_slice(plaintext);
85 let block: Block<C> = Default::default();
87 buf.extend_from_slice(&block[..n - pos]);
88
89 let n = P::pad(&mut buf, pos, bs)
90 .expect("enough space for padding is allocated")
91 .len();
92 buf.truncate(n);
93 self.encrypt_blocks(to_blocks(&mut buf));
94 buf
95 }
96
97 #[cfg(feature = "alloc")]
99 fn decrypt_vec(mut self, ciphertext: &[u8]) -> Result<Vec<u8>, BlockModeError> {
100 let bs = C::BlockSize::to_usize();
101 if ciphertext.len() % bs != 0 {
102 return Err(BlockModeError);
103 }
104 let mut buf = ciphertext.to_vec();
105 self.decrypt_blocks(to_blocks(&mut buf));
106 let n = P::unpad(&buf).map_err(|_| BlockModeError)?.len();
107 buf.truncate(n);
108 Ok(buf)
109 }
110}
111
112pub trait IvState<C, P>: BlockMode<C, P>
121where
122 C: BlockCipher,
123 P: Padding,
124{
125 fn iv_state(&self) -> GenericArray<u8, Self::IvSize>;
128}