1#[cfg(all(feature = "block-padding", feature = "alloc"))]
14use alloc::{vec, vec::Vec};
15use crypto_common::{Block, BlockSizeUser};
16use inout::{InOut, InOutBuf, NotEqualError};
17#[cfg(feature = "block-padding")]
18use inout::{
19 InOutBufReserved, PadError,
20 block_padding::{Padding, UnpadError},
21};
22
23mod backends;
24mod ctx;
25
26use ctx::{BlockCtx, BlocksCtx};
27
28pub use backends::{
29 BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherEncBackend, BlockCipherEncClosure,
30 BlockModeDecBackend, BlockModeDecClosure, BlockModeEncBackend, BlockModeEncClosure,
31};
32
33pub trait BlockCipherEncrypt: BlockSizeUser + Sized {
35 fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = Self::BlockSize>);
37
38 #[inline]
40 fn encrypt_block_inout(&self, block: InOut<'_, '_, Block<Self>>) {
41 self.encrypt_with_backend(BlockCtx { block });
42 }
43
44 #[inline]
46 fn encrypt_blocks_inout(&self, blocks: InOutBuf<'_, '_, Block<Self>>) {
47 self.encrypt_with_backend(BlocksCtx { blocks });
48 }
49
50 #[inline]
52 fn encrypt_block(&self, block: &mut Block<Self>) {
53 let block = block.into();
54 self.encrypt_with_backend(BlockCtx { block });
55 }
56
57 #[inline]
59 fn encrypt_block_b2b(&self, in_block: &Block<Self>, out_block: &mut Block<Self>) {
60 let block = (in_block, out_block).into();
61 self.encrypt_with_backend(BlockCtx { block });
62 }
63
64 #[inline]
66 fn encrypt_blocks(&self, blocks: &mut [Block<Self>]) {
67 let blocks = blocks.into();
68 self.encrypt_with_backend(BlocksCtx { blocks });
69 }
70
71 #[inline]
76 fn encrypt_blocks_b2b(
77 &self,
78 in_blocks: &[Block<Self>],
79 out_blocks: &mut [Block<Self>],
80 ) -> Result<(), NotEqualError> {
81 InOutBuf::new(in_blocks, out_blocks)
82 .map(|blocks| self.encrypt_with_backend(BlocksCtx { blocks }))
83 }
84
85 #[cfg(feature = "block-padding")]
89 #[inline]
90 fn encrypt_padded_inout<'out, P: Padding<Self::BlockSize>>(
91 &self,
92 data: InOutBufReserved<'_, 'out, u8>,
93 ) -> Result<&'out [u8], PadError> {
94 let mut buf = data.into_padded_blocks::<P, Self::BlockSize>()?;
95 self.encrypt_blocks_inout(buf.get_blocks());
96 if let Some(block) = buf.get_tail_block() {
97 self.encrypt_block_inout(block);
98 }
99 Ok(buf.into_out())
100 }
101
102 #[cfg(feature = "block-padding")]
106 #[inline]
107 fn encrypt_padded<'a, P: Padding<Self::BlockSize>>(
108 &self,
109 buf: &'a mut [u8],
110 msg_len: usize,
111 ) -> Result<&'a [u8], PadError> {
112 let buf = InOutBufReserved::from_mut_slice(buf, msg_len).map_err(|_| PadError)?;
113 self.encrypt_padded_inout::<P>(buf)
114 }
115
116 #[cfg(feature = "block-padding")]
120 #[inline]
121 fn encrypt_padded_b2b<'a, P: Padding<Self::BlockSize>>(
122 &self,
123 msg: &[u8],
124 out_buf: &'a mut [u8],
125 ) -> Result<&'a [u8], PadError> {
126 let buf = InOutBufReserved::from_slices(msg, out_buf).map_err(|_| PadError)?;
127 self.encrypt_padded_inout::<P>(buf)
128 }
129
130 #[cfg(all(feature = "block-padding", feature = "alloc"))]
132 #[inline]
133 fn encrypt_padded_vec<P: Padding<Self::BlockSize>>(&self, msg: &[u8]) -> Vec<u8> {
134 use crypto_common::typenum::Unsigned;
135 let bs = Self::BlockSize::USIZE;
136 let mut out = vec![0; bs * (msg.len() / bs + 1)];
137 let len = self
138 .encrypt_padded_b2b::<P>(msg, &mut out)
139 .expect("enough space for encrypting is allocated")
140 .len();
141 out.truncate(len);
142 out
143 }
144}
145
146pub trait BlockCipherDecrypt: BlockSizeUser {
148 fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = Self::BlockSize>);
150
151 #[inline]
153 fn decrypt_block_inout(&self, block: InOut<'_, '_, Block<Self>>) {
154 self.decrypt_with_backend(BlockCtx { block });
155 }
156
157 #[inline]
159 fn decrypt_blocks_inout(&self, blocks: InOutBuf<'_, '_, Block<Self>>) {
160 self.decrypt_with_backend(BlocksCtx { blocks });
161 }
162
163 #[inline]
165 fn decrypt_block(&self, block: &mut Block<Self>) {
166 let block = block.into();
167 self.decrypt_with_backend(BlockCtx { block });
168 }
169
170 #[inline]
172 fn decrypt_block_b2b(&self, in_block: &Block<Self>, out_block: &mut Block<Self>) {
173 let block = (in_block, out_block).into();
174 self.decrypt_with_backend(BlockCtx { block });
175 }
176
177 #[inline]
179 fn decrypt_blocks(&self, blocks: &mut [Block<Self>]) {
180 let blocks = blocks.into();
181 self.decrypt_with_backend(BlocksCtx { blocks });
182 }
183
184 #[inline]
189 fn decrypt_blocks_b2b(
190 &self,
191 in_blocks: &[Block<Self>],
192 out_blocks: &mut [Block<Self>],
193 ) -> Result<(), NotEqualError> {
194 InOutBuf::new(in_blocks, out_blocks)
195 .map(|blocks| self.decrypt_with_backend(BlocksCtx { blocks }))
196 }
197
198 #[cfg(feature = "block-padding")]
203 #[inline]
204 fn decrypt_padded_inout<'out, P: Padding<Self::BlockSize>>(
205 &self,
206 data: InOutBuf<'_, 'out, u8>,
207 ) -> Result<&'out [u8], UnpadError> {
208 let (mut blocks, tail) = data.into_chunks();
209 if !tail.is_empty() {
210 return Err(UnpadError);
211 }
212 self.decrypt_blocks_inout(blocks.reborrow());
213 P::unpad_blocks(blocks.into_out())
214 }
215
216 #[cfg(feature = "block-padding")]
221 #[inline]
222 fn decrypt_padded<'a, P: Padding<Self::BlockSize>>(
223 &self,
224 buf: &'a mut [u8],
225 ) -> Result<&'a [u8], UnpadError> {
226 self.decrypt_padded_inout::<P>(buf.into())
227 }
228
229 #[cfg(feature = "block-padding")]
235 #[inline]
236 fn decrypt_padded_b2b<'a, P: Padding<Self::BlockSize>>(
237 &self,
238 in_buf: &[u8],
239 out_buf: &'a mut [u8],
240 ) -> Result<&'a [u8], UnpadError> {
241 if out_buf.len() < in_buf.len() {
242 return Err(UnpadError);
243 }
244 let n = in_buf.len();
245 let buf = InOutBuf::new(in_buf, &mut out_buf[..n]).map_err(|_| UnpadError)?;
247 self.decrypt_padded_inout::<P>(buf)
248 }
249
250 #[cfg(all(feature = "block-padding", feature = "alloc"))]
256 #[inline]
257 fn decrypt_padded_vec<P: Padding<Self::BlockSize>>(
258 &self,
259 buf: &[u8],
260 ) -> Result<Vec<u8>, UnpadError> {
261 let mut out = vec![0; buf.len()];
262 let len = self.decrypt_padded_b2b::<P>(buf, &mut out)?.len();
263 out.truncate(len);
264 Ok(out)
265 }
266}
267
268impl<Alg: BlockCipherEncrypt> BlockCipherEncrypt for &Alg {
269 fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = Self::BlockSize>) {
270 Alg::encrypt_with_backend(self, f);
271 }
272}
273
274impl<Alg: BlockCipherDecrypt> BlockCipherDecrypt for &Alg {
275 fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = Self::BlockSize>) {
276 Alg::decrypt_with_backend(self, f);
277 }
278}
279
280pub trait BlockModeEncrypt: BlockSizeUser + Sized {
286 fn encrypt_with_backend(&mut self, f: impl BlockModeEncClosure<BlockSize = Self::BlockSize>);
288
289 #[inline]
291 fn encrypt_block_inout(&mut self, block: InOut<'_, '_, Block<Self>>) {
292 self.encrypt_with_backend(BlockCtx { block });
293 }
294
295 #[inline]
297 fn encrypt_blocks_inout(&mut self, blocks: InOutBuf<'_, '_, Block<Self>>) {
298 self.encrypt_with_backend(BlocksCtx { blocks });
299 }
300
301 #[inline]
303 fn encrypt_block(&mut self, block: &mut Block<Self>) {
304 let block = block.into();
305 self.encrypt_with_backend(BlockCtx { block });
306 }
307
308 #[inline]
310 fn encrypt_block_b2b(&mut self, in_block: &Block<Self>, out_block: &mut Block<Self>) {
311 let block = (in_block, out_block).into();
312 self.encrypt_with_backend(BlockCtx { block });
313 }
314
315 #[inline]
317 fn encrypt_blocks(&mut self, blocks: &mut [Block<Self>]) {
318 let blocks = blocks.into();
319 self.encrypt_with_backend(BlocksCtx { blocks });
320 }
321
322 #[inline]
327 fn encrypt_blocks_b2b(
328 &mut self,
329 in_blocks: &[Block<Self>],
330 out_blocks: &mut [Block<Self>],
331 ) -> Result<(), NotEqualError> {
332 InOutBuf::new(in_blocks, out_blocks)
333 .map(|blocks| self.encrypt_with_backend(BlocksCtx { blocks }))
334 }
335
336 #[cfg(feature = "block-padding")]
340 #[inline]
341 fn encrypt_padded_inout<'out, P: Padding<Self::BlockSize>>(
342 mut self,
343 data: InOutBufReserved<'_, 'out, u8>,
344 ) -> Result<&'out [u8], PadError> {
345 let mut buf = data.into_padded_blocks::<P, Self::BlockSize>()?;
346 self.encrypt_blocks_inout(buf.get_blocks());
347 if let Some(block) = buf.get_tail_block() {
348 self.encrypt_block_inout(block);
349 }
350 Ok(buf.into_out())
351 }
352
353 #[cfg(feature = "block-padding")]
357 #[inline]
358 fn encrypt_padded<P: Padding<Self::BlockSize>>(
359 self,
360 buf: &mut [u8],
361 msg_len: usize,
362 ) -> Result<&[u8], PadError> {
363 let buf = InOutBufReserved::from_mut_slice(buf, msg_len).map_err(|_| PadError)?;
364 self.encrypt_padded_inout::<P>(buf)
365 }
366
367 #[cfg(feature = "block-padding")]
371 #[inline]
372 fn encrypt_padded_b2b<'a, P: Padding<Self::BlockSize>>(
373 self,
374 msg: &[u8],
375 out_buf: &'a mut [u8],
376 ) -> Result<&'a [u8], PadError> {
377 let buf = InOutBufReserved::from_slices(msg, out_buf).map_err(|_| PadError)?;
378 self.encrypt_padded_inout::<P>(buf)
379 }
380
381 #[cfg(all(feature = "block-padding", feature = "alloc"))]
383 #[inline]
384 fn encrypt_padded_vec<P: Padding<Self::BlockSize>>(self, msg: &[u8]) -> Vec<u8> {
385 use crypto_common::typenum::Unsigned;
386 let bs = Self::BlockSize::USIZE;
387 let mut out = vec![0; bs * (msg.len() / bs + 1)];
388 let len = self
389 .encrypt_padded_b2b::<P>(msg, &mut out)
390 .expect("enough space for encrypting is allocated")
391 .len();
392 out.truncate(len);
393 out
394 }
395}
396
397pub trait BlockModeDecrypt: BlockSizeUser + Sized {
403 fn decrypt_with_backend(&mut self, f: impl BlockModeDecClosure<BlockSize = Self::BlockSize>);
405
406 #[inline]
408 fn decrypt_block_inout(&mut self, block: InOut<'_, '_, Block<Self>>) {
409 self.decrypt_with_backend(BlockCtx { block });
410 }
411
412 #[inline]
414 fn decrypt_blocks_inout(&mut self, blocks: InOutBuf<'_, '_, Block<Self>>) {
415 self.decrypt_with_backend(BlocksCtx { blocks });
416 }
417
418 #[inline]
420 fn decrypt_block(&mut self, block: &mut Block<Self>) {
421 let block = block.into();
422 self.decrypt_with_backend(BlockCtx { block });
423 }
424
425 #[inline]
427 fn decrypt_block_b2b(&mut self, in_block: &Block<Self>, out_block: &mut Block<Self>) {
428 let block = (in_block, out_block).into();
429 self.decrypt_with_backend(BlockCtx { block });
430 }
431
432 #[inline]
434 fn decrypt_blocks(&mut self, blocks: &mut [Block<Self>]) {
435 let blocks = blocks.into();
436 self.decrypt_with_backend(BlocksCtx { blocks });
437 }
438
439 #[inline]
444 fn decrypt_blocks_b2b(
445 &mut self,
446 in_blocks: &[Block<Self>],
447 out_blocks: &mut [Block<Self>],
448 ) -> Result<(), NotEqualError> {
449 InOutBuf::new(in_blocks, out_blocks)
450 .map(|blocks| self.decrypt_with_backend(BlocksCtx { blocks }))
451 }
452
453 #[cfg(feature = "block-padding")]
458 #[inline]
459 fn decrypt_padded_inout<'out, P: Padding<Self::BlockSize>>(
460 mut self,
461 data: InOutBuf<'_, 'out, u8>,
462 ) -> Result<&'out [u8], UnpadError> {
463 let (mut blocks, tail) = data.into_chunks();
464 if !tail.is_empty() {
465 return Err(UnpadError);
466 }
467 self.decrypt_blocks_inout(blocks.reborrow());
468 P::unpad_blocks(blocks.into_out())
469 }
470
471 #[cfg(feature = "block-padding")]
476 #[inline]
477 fn decrypt_padded<P: Padding<Self::BlockSize>>(
478 self,
479 buf: &mut [u8],
480 ) -> Result<&[u8], UnpadError> {
481 self.decrypt_padded_inout::<P>(buf.into())
482 }
483
484 #[cfg(feature = "block-padding")]
490 #[inline]
491 fn decrypt_padded_b2b<'a, P: Padding<Self::BlockSize>>(
492 self,
493 in_buf: &[u8],
494 out_buf: &'a mut [u8],
495 ) -> Result<&'a [u8], UnpadError> {
496 if out_buf.len() < in_buf.len() {
497 return Err(UnpadError);
498 }
499 let n = in_buf.len();
500 let buf = InOutBuf::new(in_buf, &mut out_buf[..n]).map_err(|_| UnpadError)?;
502 self.decrypt_padded_inout::<P>(buf)
503 }
504
505 #[cfg(all(feature = "block-padding", feature = "alloc"))]
511 #[inline]
512 fn decrypt_padded_vec<P: Padding<Self::BlockSize>>(
513 self,
514 buf: &[u8],
515 ) -> Result<Vec<u8>, UnpadError> {
516 let mut out = vec![0; buf.len()];
517 let len = self.decrypt_padded_b2b::<P>(buf, &mut out)?.len();
518 out.truncate(len);
519 Ok(out)
520 }
521}