ssh_cipher/block_cipher/
encryptor.rs1use super::{BlockMode, State, sealed::BlockCipher};
4use crate::{Cipher, Error, Result};
5use ::cipher::{
6 Block, BlockCipherEncBackend, BlockCipherEncClosure, BlockModeEncBackend, BlockModeEncClosure,
7 BlockModeEncrypt,
8 common::{
9 BlockSizeUser, InnerUser, ParBlocksSizeUser,
10 array::{ArraySize, sizes::U1},
11 },
12 inout::InOut,
13};
14use core::fmt::{self, Debug};
15
16pub struct Encryptor<C: BlockCipher> {
19 cipher: C,
21
22 state: State<C::BlockSize>,
24}
25
26impl<C: BlockCipher> Encryptor<C> {
27 pub fn new(cipher: Cipher, key: &[u8], iv: &[u8]) -> Result<Self> {
36 if !C::is_supported(cipher) {
37 return Err(Error::UnsupportedCipher(cipher));
38 }
39
40 let mode = cipher.block_mode().ok_or(Error::Crypto)?;
41 let cipher = C::new_from_slice(key)?;
42 let state = State::new_from_slice(mode, iv)?;
43 Ok(Self { cipher, state })
44 }
45}
46
47impl<C: BlockCipher> BlockModeEncrypt for Encryptor<C> {
48 fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>) {
49 struct Closure<'a, BS, BC>
50 where
51 BS: ArraySize,
52 BC: BlockModeEncClosure<BlockSize = BS>,
53 {
54 state: &'a mut State<BS>,
55 f: BC,
56 }
57
58 impl<BS, BC> BlockSizeUser for Closure<'_, BS, BC>
59 where
60 BS: ArraySize,
61 BC: BlockModeEncClosure<BlockSize = BS>,
62 {
63 type BlockSize = BS;
64 }
65
66 impl<BS, BC> BlockCipherEncClosure for Closure<'_, BS, BC>
67 where
68 BS: ArraySize,
69 BC: BlockModeEncClosure<BlockSize = BS>,
70 {
71 #[inline(always)]
72 fn call<B: BlockCipherEncBackend<BlockSize = Self::BlockSize>>(
73 self,
74 cipher_backend: &B,
75 ) {
76 let Self { state, f } = self;
77 f.call(&mut Backend {
78 state,
79 cipher_backend,
80 });
81 }
82 }
83
84 let Self { cipher, state } = self;
85 cipher.encrypt_with_backend(Closure { state, f });
86 }
87}
88
89impl<C: BlockCipher> BlockSizeUser for Encryptor<C> {
90 type BlockSize = C::BlockSize;
91}
92
93impl<C: BlockCipher> Debug for Encryptor<C> {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 f.debug_struct("Encryptor").finish_non_exhaustive()
96 }
97}
98
99impl<C: BlockCipher> InnerUser for Encryptor<C> {
100 type Inner = C;
101}
102
103struct Backend<'a, BS, BK>
104where
105 BS: ArraySize,
106 BK: BlockCipherEncBackend<BlockSize = BS>,
107{
108 state: &'a mut State<BS>,
109 cipher_backend: &'a BK,
110}
111
112impl<BS, BK> BlockSizeUser for Backend<'_, BS, BK>
113where
114 BS: ArraySize,
115 BK: BlockCipherEncBackend<BlockSize = BS>,
116{
117 type BlockSize = BS;
118}
119
120impl<BS, BK> ParBlocksSizeUser for Backend<'_, BS, BK>
121where
122 BS: ArraySize,
123 BK: BlockCipherEncBackend<BlockSize = BS>,
124{
125 type ParBlocksSize = U1;
128}
129
130impl<BS, BK> BlockModeEncBackend for Backend<'_, BS, BK>
131where
132 BS: ArraySize,
133 BK: BlockCipherEncBackend<BlockSize = BS>,
134{
135 #[inline(always)]
136 fn encrypt_block(&mut self, mut block: InOut<'_, '_, Block<Self>>) {
137 let mut t = block.clone_in();
138
139 match self.state.mode() {
140 BlockMode::Cbc => {
141 self.state.xor_into(&mut t);
142 self.cipher_backend.encrypt_block(InOut::from(&mut t));
143 self.state.as_mut().copy_from_slice(&t);
144 }
145 BlockMode::Ctr => {
146 let mut pad = self.state.clone();
147 self.cipher_backend.encrypt_block(pad.as_mut().into());
148 pad.xor_into(&mut t);
149 self.state.increment_counter();
150 }
151 }
152
153 *block.get_out() = t;
154 }
155}