/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.4.4/src/block.rs
Line | Count | Source |
1 | | //! Traits used to define functionality of [block ciphers][1] and [modes of operation][2]. |
2 | | //! |
3 | | //! # About block ciphers |
4 | | //! |
5 | | //! Block ciphers are keyed, deterministic permutations of a fixed-sized input |
6 | | //! "block" providing a reversible transformation to/from an encrypted output. |
7 | | //! They are one of the fundamental structural components of [symmetric cryptography][3]. |
8 | | //! |
9 | | //! [1]: https://en.wikipedia.org/wiki/Block_cipher |
10 | | //! [2]: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation |
11 | | //! [3]: https://en.wikipedia.org/wiki/Symmetric-key_algorithm |
12 | | |
13 | | use crate::{ParBlocks, ParBlocksSizeUser}; |
14 | | #[cfg(all(feature = "block-padding", feature = "alloc"))] |
15 | | use alloc::{vec, vec::Vec}; |
16 | | #[cfg(feature = "block-padding")] |
17 | | use inout::{ |
18 | | block_padding::{Padding, UnpadError}, |
19 | | InOutBufReserved, PadError, |
20 | | }; |
21 | | use inout::{InOut, InOutBuf, NotEqualError}; |
22 | | |
23 | | pub use crypto_common::{generic_array::ArrayLength, typenum::Unsigned, Block, BlockSizeUser}; |
24 | | |
25 | | /// Marker trait for block ciphers. |
26 | | pub trait BlockCipher: BlockSizeUser {} |
27 | | |
28 | | /// Trait implemented by block cipher encryption and decryption backends. |
29 | | pub trait BlockBackend: ParBlocksSizeUser { |
30 | | /// Process single inout block. |
31 | | fn proc_block(&mut self, block: InOut<'_, '_, Block<Self>>); |
32 | | |
33 | | /// Process inout blocks in parallel. |
34 | | #[inline(always)] |
35 | | fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, ParBlocks<Self>>) { |
36 | | for i in 0..Self::ParBlocksSize::USIZE { |
37 | | self.proc_block(blocks.get(i)); |
38 | | } |
39 | | } |
40 | | |
41 | | /// Process buffer of inout blocks. Length of the buffer MUST be smaller |
42 | | /// than `Self::ParBlocksSize`. |
43 | | #[inline(always)] |
44 | | fn proc_tail_blocks(&mut self, blocks: InOutBuf<'_, '_, Block<Self>>) { |
45 | | assert!(blocks.len() < Self::ParBlocksSize::USIZE); |
46 | | for block in blocks { |
47 | | self.proc_block(block); |
48 | | } |
49 | | } |
50 | | |
51 | | /// Process single block in-place. |
52 | | #[inline(always)] |
53 | | fn proc_block_inplace(&mut self, block: &mut Block<Self>) { |
54 | | self.proc_block(block.into()); |
55 | | } |
56 | | |
57 | | /// Process blocks in parallel in-place. |
58 | | #[inline(always)] |
59 | | fn proc_par_blocks_inplace(&mut self, blocks: &mut ParBlocks<Self>) { |
60 | | self.proc_par_blocks(blocks.into()); |
61 | | } |
62 | | |
63 | | /// Process buffer of blocks in-place. Length of the buffer MUST be smaller |
64 | | /// than `Self::ParBlocksSize`. |
65 | | #[inline(always)] |
66 | | fn proc_tail_blocks_inplace(&mut self, blocks: &mut [Block<Self>]) { |
67 | | self.proc_tail_blocks(blocks.into()); |
68 | | } |
69 | | } |
70 | | |
71 | | /// Trait for [`BlockBackend`] users. |
72 | | /// |
73 | | /// This trait is used to define rank-2 closures. |
74 | | pub trait BlockClosure: BlockSizeUser { |
75 | | /// Execute closure with the provided block cipher backend. |
76 | | fn call<B: BlockBackend<BlockSize = Self::BlockSize>>(self, backend: &mut B); |
77 | | } |
78 | | |
79 | | /// Encrypt-only functionality for block ciphers. |
80 | | pub trait BlockEncrypt: BlockSizeUser + Sized { |
81 | | /// Encrypt data using backend provided to the rank-2 closure. |
82 | | fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = Self::BlockSize>); |
83 | | |
84 | | /// Encrypt single `inout` block. |
85 | | #[inline] |
86 | | fn encrypt_block_inout(&self, block: InOut<'_, '_, Block<Self>>) { |
87 | | self.encrypt_with_backend(BlockCtx { block }); |
88 | | } |
89 | | |
90 | | /// Encrypt `inout` blocks. |
91 | | #[inline] |
92 | | fn encrypt_blocks_inout(&self, blocks: InOutBuf<'_, '_, Block<Self>>) { |
93 | | self.encrypt_with_backend(BlocksCtx { blocks }); |
94 | | } |
95 | | |
96 | | /// Encrypt single block in-place. |
97 | | #[inline] |
98 | 2.70k | fn encrypt_block(&self, block: &mut Block<Self>) { |
99 | 2.70k | let block = block.into(); |
100 | 2.70k | self.encrypt_with_backend(BlockCtx { block }); |
101 | 2.70k | } |
102 | | |
103 | | /// Encrypt `in_block` and write result to `out_block`. |
104 | | #[inline] |
105 | | fn encrypt_block_b2b(&self, in_block: &Block<Self>, out_block: &mut Block<Self>) { |
106 | | let block = (in_block, out_block).into(); |
107 | | self.encrypt_with_backend(BlockCtx { block }); |
108 | | } |
109 | | |
110 | | /// Encrypt blocks in-place. |
111 | | #[inline] |
112 | | fn encrypt_blocks(&self, blocks: &mut [Block<Self>]) { |
113 | | let blocks = blocks.into(); |
114 | | self.encrypt_with_backend(BlocksCtx { blocks }); |
115 | | } |
116 | | |
117 | | /// Encrypt blocks buffer-to-buffer. |
118 | | /// |
119 | | /// Returns [`NotEqualError`] if provided `in_blocks` and `out_blocks` |
120 | | /// have different lengths. |
121 | | #[inline] |
122 | | fn encrypt_blocks_b2b( |
123 | | &self, |
124 | | in_blocks: &[Block<Self>], |
125 | | out_blocks: &mut [Block<Self>], |
126 | | ) -> Result<(), NotEqualError> { |
127 | | InOutBuf::new(in_blocks, out_blocks) |
128 | | .map(|blocks| self.encrypt_with_backend(BlocksCtx { blocks })) |
129 | | } |
130 | | |
131 | | /// Pad input and encrypt. Returns resulting ciphertext slice. |
132 | | /// |
133 | | /// Returns [`PadError`] if length of output buffer is not sufficient. |
134 | | #[cfg(feature = "block-padding")] |
135 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
136 | | #[inline] |
137 | | fn encrypt_padded_inout<'inp, 'out, P: Padding<Self::BlockSize>>( |
138 | | &self, |
139 | | data: InOutBufReserved<'inp, 'out, u8>, |
140 | | ) -> Result<&'out [u8], PadError> { |
141 | | let mut buf = data.into_padded_blocks::<P, Self::BlockSize>()?; |
142 | | self.encrypt_blocks_inout(buf.get_blocks()); |
143 | | if let Some(block) = buf.get_tail_block() { |
144 | | self.encrypt_block_inout(block); |
145 | | } |
146 | | Ok(buf.into_out()) |
147 | | } |
148 | | |
149 | | /// Pad input and encrypt in-place. Returns resulting ciphertext slice. |
150 | | /// |
151 | | /// Returns [`PadError`] if length of output buffer is not sufficient. |
152 | | #[cfg(feature = "block-padding")] |
153 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
154 | | #[inline] |
155 | | fn encrypt_padded<'a, P: Padding<Self::BlockSize>>( |
156 | | &self, |
157 | | buf: &'a mut [u8], |
158 | | msg_len: usize, |
159 | | ) -> Result<&'a [u8], PadError> { |
160 | | let buf = InOutBufReserved::from_mut_slice(buf, msg_len).map_err(|_| PadError)?; |
161 | | self.encrypt_padded_inout::<P>(buf) |
162 | | } |
163 | | |
164 | | /// Pad input and encrypt buffer-to-buffer. Returns resulting ciphertext slice. |
165 | | /// |
166 | | /// Returns [`PadError`] if length of output buffer is not sufficient. |
167 | | #[cfg(feature = "block-padding")] |
168 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
169 | | #[inline] |
170 | | fn encrypt_padded_b2b<'a, P: Padding<Self::BlockSize>>( |
171 | | &self, |
172 | | msg: &[u8], |
173 | | out_buf: &'a mut [u8], |
174 | | ) -> Result<&'a [u8], PadError> { |
175 | | let buf = InOutBufReserved::from_slices(msg, out_buf).map_err(|_| PadError)?; |
176 | | self.encrypt_padded_inout::<P>(buf) |
177 | | } |
178 | | |
179 | | /// Pad input and encrypt into a newly allocated Vec. Returns resulting ciphertext Vec. |
180 | | #[cfg(all(feature = "block-padding", feature = "alloc"))] |
181 | | #[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))] |
182 | | #[inline] |
183 | | fn encrypt_padded_vec<P: Padding<Self::BlockSize>>(&self, msg: &[u8]) -> Vec<u8> { |
184 | | let mut out = allocate_out_vec::<Self>(msg.len()); |
185 | | let len = self |
186 | | .encrypt_padded_b2b::<P>(msg, &mut out) |
187 | | .expect("enough space for encrypting is allocated") |
188 | | .len(); |
189 | | out.truncate(len); |
190 | | out |
191 | | } |
192 | | } |
193 | | |
194 | | /// Decrypt-only functionality for block ciphers. |
195 | | pub trait BlockDecrypt: BlockSizeUser { |
196 | | /// Decrypt data using backend provided to the rank-2 closure. |
197 | | fn decrypt_with_backend(&self, f: impl BlockClosure<BlockSize = Self::BlockSize>); |
198 | | |
199 | | /// Decrypt single `inout` block. |
200 | | #[inline] |
201 | | fn decrypt_block_inout(&self, block: InOut<'_, '_, Block<Self>>) { |
202 | | self.decrypt_with_backend(BlockCtx { block }); |
203 | | } |
204 | | |
205 | | /// Decrypt `inout` blocks. |
206 | | #[inline] |
207 | | fn decrypt_blocks_inout(&self, blocks: InOutBuf<'_, '_, Block<Self>>) { |
208 | | self.decrypt_with_backend(BlocksCtx { blocks }); |
209 | | } |
210 | | |
211 | | /// Decrypt single block in-place. |
212 | | #[inline] |
213 | | fn decrypt_block(&self, block: &mut Block<Self>) { |
214 | | let block = block.into(); |
215 | | self.decrypt_with_backend(BlockCtx { block }); |
216 | | } |
217 | | |
218 | | /// Decrypt `in_block` and write result to `out_block`. |
219 | | #[inline] |
220 | | fn decrypt_block_b2b(&self, in_block: &Block<Self>, out_block: &mut Block<Self>) { |
221 | | let block = (in_block, out_block).into(); |
222 | | self.decrypt_with_backend(BlockCtx { block }); |
223 | | } |
224 | | |
225 | | /// Decrypt blocks in-place. |
226 | | #[inline] |
227 | | fn decrypt_blocks(&self, blocks: &mut [Block<Self>]) { |
228 | | let blocks = blocks.into(); |
229 | | self.decrypt_with_backend(BlocksCtx { blocks }); |
230 | | } |
231 | | |
232 | | /// Decrypt blocks buffer-to-buffer. |
233 | | /// |
234 | | /// Returns [`NotEqualError`] if provided `in_blocks` and `out_blocks` |
235 | | /// have different lengths. |
236 | | #[inline] |
237 | | fn decrypt_blocks_b2b( |
238 | | &self, |
239 | | in_blocks: &[Block<Self>], |
240 | | out_blocks: &mut [Block<Self>], |
241 | | ) -> Result<(), NotEqualError> { |
242 | | InOutBuf::new(in_blocks, out_blocks) |
243 | | .map(|blocks| self.decrypt_with_backend(BlocksCtx { blocks })) |
244 | | } |
245 | | |
246 | | /// Decrypt input and unpad it. Returns resulting ciphertext slice. |
247 | | /// |
248 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
249 | | /// not multiple of `Self::BlockSize`. |
250 | | #[cfg(feature = "block-padding")] |
251 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
252 | | #[inline] |
253 | | fn decrypt_padded_inout<'inp, 'out, P: Padding<Self::BlockSize>>( |
254 | | &self, |
255 | | data: InOutBuf<'inp, 'out, u8>, |
256 | | ) -> Result<&'out [u8], UnpadError> { |
257 | | let (mut blocks, tail) = data.into_chunks(); |
258 | | if !tail.is_empty() { |
259 | | return Err(UnpadError); |
260 | | } |
261 | | self.decrypt_blocks_inout(blocks.reborrow()); |
262 | | P::unpad_blocks(blocks.into_out()) |
263 | | } |
264 | | |
265 | | /// Decrypt input and unpad it in-place. Returns resulting ciphertext slice. |
266 | | /// |
267 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
268 | | /// not multiple of `Self::BlockSize`. |
269 | | #[cfg(feature = "block-padding")] |
270 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
271 | | #[inline] |
272 | | fn decrypt_padded<'a, P: Padding<Self::BlockSize>>( |
273 | | &self, |
274 | | buf: &'a mut [u8], |
275 | | ) -> Result<&'a [u8], UnpadError> { |
276 | | self.decrypt_padded_inout::<P>(buf.into()) |
277 | | } |
278 | | |
279 | | /// Decrypt input and unpad it buffer-to-buffer. Returns resulting |
280 | | /// ciphertext slice. |
281 | | /// |
282 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
283 | | /// not multiple of `Self::BlockSize`. |
284 | | #[cfg(feature = "block-padding")] |
285 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
286 | | #[inline] |
287 | | fn decrypt_padded_b2b<'a, P: Padding<Self::BlockSize>>( |
288 | | &self, |
289 | | in_buf: &[u8], |
290 | | out_buf: &'a mut [u8], |
291 | | ) -> Result<&'a [u8], UnpadError> { |
292 | | if out_buf.len() < in_buf.len() { |
293 | | return Err(UnpadError); |
294 | | } |
295 | | let n = in_buf.len(); |
296 | | // note: `new` always returns `Ok` here |
297 | | let buf = InOutBuf::new(in_buf, &mut out_buf[..n]).map_err(|_| UnpadError)?; |
298 | | self.decrypt_padded_inout::<P>(buf) |
299 | | } |
300 | | |
301 | | /// Decrypt input and unpad it in a newly allocated Vec. Returns resulting |
302 | | /// ciphertext Vec. |
303 | | /// |
304 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
305 | | /// not multiple of `Self::BlockSize`. |
306 | | #[cfg(all(feature = "block-padding", feature = "alloc"))] |
307 | | #[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))] |
308 | | #[inline] |
309 | | fn decrypt_padded_vec<P: Padding<Self::BlockSize>>( |
310 | | &self, |
311 | | buf: &[u8], |
312 | | ) -> Result<Vec<u8>, UnpadError> { |
313 | | let mut out = vec![0; buf.len()]; |
314 | | let len = self.decrypt_padded_b2b::<P>(buf, &mut out)?.len(); |
315 | | out.truncate(len); |
316 | | Ok(out) |
317 | | } |
318 | | } |
319 | | |
320 | | /// Encrypt-only functionality for block ciphers and modes with mutable access to `self`. |
321 | | /// |
322 | | /// The main use case for this trait is blocks modes, but it also can be used |
323 | | /// for hardware cryptographic engines which require `&mut self` access to an |
324 | | /// underlying hardware peripheral. |
325 | | pub trait BlockEncryptMut: BlockSizeUser + Sized { |
326 | | /// Encrypt data using backend provided to the rank-2 closure. |
327 | | fn encrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>); |
328 | | |
329 | | /// Encrypt single `inout` block. |
330 | | #[inline] |
331 | | fn encrypt_block_inout_mut(&mut self, block: InOut<'_, '_, Block<Self>>) { |
332 | | self.encrypt_with_backend_mut(BlockCtx { block }); |
333 | | } |
334 | | |
335 | | /// Encrypt `inout` blocks. |
336 | | #[inline] |
337 | | fn encrypt_blocks_inout_mut(&mut self, blocks: InOutBuf<'_, '_, Block<Self>>) { |
338 | | self.encrypt_with_backend_mut(BlocksCtx { blocks }); |
339 | | } |
340 | | |
341 | | /// Encrypt single block in-place. |
342 | | #[inline] |
343 | | fn encrypt_block_mut(&mut self, block: &mut Block<Self>) { |
344 | | let block = block.into(); |
345 | | self.encrypt_with_backend_mut(BlockCtx { block }); |
346 | | } |
347 | | |
348 | | /// Encrypt `in_block` and write result to `out_block`. |
349 | | #[inline] |
350 | | fn encrypt_block_b2b_mut(&mut self, in_block: &Block<Self>, out_block: &mut Block<Self>) { |
351 | | let block = (in_block, out_block).into(); |
352 | | self.encrypt_with_backend_mut(BlockCtx { block }); |
353 | | } |
354 | | |
355 | | /// Encrypt blocks in-place. |
356 | | #[inline] |
357 | | fn encrypt_blocks_mut(&mut self, blocks: &mut [Block<Self>]) { |
358 | | let blocks = blocks.into(); |
359 | | self.encrypt_with_backend_mut(BlocksCtx { blocks }); |
360 | | } |
361 | | |
362 | | /// Encrypt blocks buffer-to-buffer. |
363 | | /// |
364 | | /// Returns [`NotEqualError`] if provided `in_blocks` and `out_blocks` |
365 | | /// have different lengths. |
366 | | #[inline] |
367 | | fn encrypt_blocks_b2b_mut( |
368 | | &mut self, |
369 | | in_blocks: &[Block<Self>], |
370 | | out_blocks: &mut [Block<Self>], |
371 | | ) -> Result<(), NotEqualError> { |
372 | | InOutBuf::new(in_blocks, out_blocks) |
373 | | .map(|blocks| self.encrypt_with_backend_mut(BlocksCtx { blocks })) |
374 | | } |
375 | | |
376 | | /// Pad input and encrypt. Returns resulting ciphertext slice. |
377 | | /// |
378 | | /// Returns [`PadError`] if length of output buffer is not sufficient. |
379 | | #[cfg(feature = "block-padding")] |
380 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
381 | | #[inline] |
382 | | fn encrypt_padded_inout_mut<'inp, 'out, P: Padding<Self::BlockSize>>( |
383 | | mut self, |
384 | | data: InOutBufReserved<'inp, 'out, u8>, |
385 | | ) -> Result<&'out [u8], PadError> { |
386 | | let mut buf = data.into_padded_blocks::<P, Self::BlockSize>()?; |
387 | | self.encrypt_blocks_inout_mut(buf.get_blocks()); |
388 | | if let Some(block) = buf.get_tail_block() { |
389 | | self.encrypt_block_inout_mut(block); |
390 | | } |
391 | | Ok(buf.into_out()) |
392 | | } |
393 | | |
394 | | /// Pad input and encrypt in-place. Returns resulting ciphertext slice. |
395 | | /// |
396 | | /// Returns [`PadError`] if length of output buffer is not sufficient. |
397 | | #[cfg(feature = "block-padding")] |
398 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
399 | | #[inline] |
400 | | fn encrypt_padded_mut<P: Padding<Self::BlockSize>>( |
401 | | self, |
402 | | buf: &mut [u8], |
403 | | msg_len: usize, |
404 | | ) -> Result<&[u8], PadError> { |
405 | | let buf = InOutBufReserved::from_mut_slice(buf, msg_len).map_err(|_| PadError)?; |
406 | | self.encrypt_padded_inout_mut::<P>(buf) |
407 | | } |
408 | | |
409 | | /// Pad input and encrypt buffer-to-buffer. Returns resulting ciphertext slice. |
410 | | /// |
411 | | /// Returns [`PadError`] if length of output buffer is not sufficient. |
412 | | #[cfg(feature = "block-padding")] |
413 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
414 | | #[inline] |
415 | | fn encrypt_padded_b2b_mut<'a, P: Padding<Self::BlockSize>>( |
416 | | self, |
417 | | msg: &[u8], |
418 | | out_buf: &'a mut [u8], |
419 | | ) -> Result<&'a [u8], PadError> { |
420 | | let buf = InOutBufReserved::from_slices(msg, out_buf).map_err(|_| PadError)?; |
421 | | self.encrypt_padded_inout_mut::<P>(buf) |
422 | | } |
423 | | |
424 | | /// Pad input and encrypt into a newly allocated Vec. Returns resulting ciphertext Vec. |
425 | | #[cfg(all(feature = "block-padding", feature = "alloc"))] |
426 | | #[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))] |
427 | | #[inline] |
428 | | fn encrypt_padded_vec_mut<P: Padding<Self::BlockSize>>(self, msg: &[u8]) -> Vec<u8> { |
429 | | let mut out = allocate_out_vec::<Self>(msg.len()); |
430 | | let len = self |
431 | | .encrypt_padded_b2b_mut::<P>(msg, &mut out) |
432 | | .expect("enough space for encrypting is allocated") |
433 | | .len(); |
434 | | out.truncate(len); |
435 | | out |
436 | | } |
437 | | } |
438 | | |
439 | | /// Decrypt-only functionality for block ciphers and modes with mutable access to `self`. |
440 | | /// |
441 | | /// The main use case for this trait is blocks modes, but it also can be used |
442 | | /// for hardware cryptographic engines which require `&mut self` access to an |
443 | | /// underlying hardware peripheral. |
444 | | pub trait BlockDecryptMut: BlockSizeUser + Sized { |
445 | | /// Decrypt data using backend provided to the rank-2 closure. |
446 | | fn decrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>); |
447 | | |
448 | | /// Decrypt single `inout` block. |
449 | | #[inline] |
450 | | fn decrypt_block_inout_mut(&mut self, block: InOut<'_, '_, Block<Self>>) { |
451 | | self.decrypt_with_backend_mut(BlockCtx { block }); |
452 | | } |
453 | | |
454 | | /// Decrypt `inout` blocks. |
455 | | #[inline] |
456 | | fn decrypt_blocks_inout_mut(&mut self, blocks: InOutBuf<'_, '_, Block<Self>>) { |
457 | | self.decrypt_with_backend_mut(BlocksCtx { blocks }); |
458 | | } |
459 | | |
460 | | /// Decrypt single block in-place. |
461 | | #[inline] |
462 | | fn decrypt_block_mut(&mut self, block: &mut Block<Self>) { |
463 | | let block = block.into(); |
464 | | self.decrypt_with_backend_mut(BlockCtx { block }); |
465 | | } |
466 | | |
467 | | /// Decrypt `in_block` and write result to `out_block`. |
468 | | #[inline] |
469 | | fn decrypt_block_b2b_mut(&mut self, in_block: &Block<Self>, out_block: &mut Block<Self>) { |
470 | | let block = (in_block, out_block).into(); |
471 | | self.decrypt_with_backend_mut(BlockCtx { block }); |
472 | | } |
473 | | |
474 | | /// Decrypt blocks in-place. |
475 | | #[inline] |
476 | | fn decrypt_blocks_mut(&mut self, blocks: &mut [Block<Self>]) { |
477 | | let blocks = blocks.into(); |
478 | | self.decrypt_with_backend_mut(BlocksCtx { blocks }); |
479 | | } |
480 | | |
481 | | /// Decrypt blocks buffer-to-buffer. |
482 | | /// |
483 | | /// Returns [`NotEqualError`] if provided `in_blocks` and `out_blocks` |
484 | | /// have different lengths. |
485 | | #[inline] |
486 | | fn decrypt_blocks_b2b_mut( |
487 | | &mut self, |
488 | | in_blocks: &[Block<Self>], |
489 | | out_blocks: &mut [Block<Self>], |
490 | | ) -> Result<(), NotEqualError> { |
491 | | InOutBuf::new(in_blocks, out_blocks) |
492 | | .map(|blocks| self.decrypt_with_backend_mut(BlocksCtx { blocks })) |
493 | | } |
494 | | |
495 | | /// Decrypt input and unpad it. Returns resulting ciphertext slice. |
496 | | /// |
497 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
498 | | /// not multiple of `Self::BlockSize`. |
499 | | #[cfg(feature = "block-padding")] |
500 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
501 | | #[inline] |
502 | | fn decrypt_padded_inout_mut<'inp, 'out, P: Padding<Self::BlockSize>>( |
503 | | mut self, |
504 | | data: InOutBuf<'inp, 'out, u8>, |
505 | | ) -> Result<&'out [u8], UnpadError> { |
506 | | let (mut blocks, tail) = data.into_chunks(); |
507 | | if !tail.is_empty() { |
508 | | return Err(UnpadError); |
509 | | } |
510 | | self.decrypt_blocks_inout_mut(blocks.reborrow()); |
511 | | P::unpad_blocks(blocks.into_out()) |
512 | | } |
513 | | |
514 | | /// Decrypt input and unpad it in-place. Returns resulting ciphertext slice. |
515 | | /// |
516 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
517 | | /// not multiple of `Self::BlockSize`. |
518 | | #[cfg(feature = "block-padding")] |
519 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
520 | | #[inline] |
521 | | fn decrypt_padded_mut<P: Padding<Self::BlockSize>>( |
522 | | self, |
523 | | buf: &mut [u8], |
524 | | ) -> Result<&[u8], UnpadError> { |
525 | | self.decrypt_padded_inout_mut::<P>(buf.into()) |
526 | | } |
527 | | |
528 | | /// Decrypt input and unpad it buffer-to-buffer. Returns resulting |
529 | | /// ciphertext slice. |
530 | | /// |
531 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
532 | | /// not multiple of `Self::BlockSize`. |
533 | | #[cfg(feature = "block-padding")] |
534 | | #[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))] |
535 | | #[inline] |
536 | | fn decrypt_padded_b2b_mut<'a, P: Padding<Self::BlockSize>>( |
537 | | self, |
538 | | in_buf: &[u8], |
539 | | out_buf: &'a mut [u8], |
540 | | ) -> Result<&'a [u8], UnpadError> { |
541 | | if out_buf.len() < in_buf.len() { |
542 | | return Err(UnpadError); |
543 | | } |
544 | | let n = in_buf.len(); |
545 | | // note: `new` always returns `Ok` here |
546 | | let buf = InOutBuf::new(in_buf, &mut out_buf[..n]).map_err(|_| UnpadError)?; |
547 | | self.decrypt_padded_inout_mut::<P>(buf) |
548 | | } |
549 | | |
550 | | /// Decrypt input and unpad it in a newly allocated Vec. Returns resulting |
551 | | /// ciphertext Vec. |
552 | | /// |
553 | | /// Returns [`UnpadError`] if padding is malformed or if input length is |
554 | | /// not multiple of `Self::BlockSize`. |
555 | | #[cfg(all(feature = "block-padding", feature = "alloc"))] |
556 | | #[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))] |
557 | | #[inline] |
558 | | fn decrypt_padded_vec_mut<P: Padding<Self::BlockSize>>( |
559 | | self, |
560 | | buf: &[u8], |
561 | | ) -> Result<Vec<u8>, UnpadError> { |
562 | | let mut out = vec![0; buf.len()]; |
563 | | let len = self.decrypt_padded_b2b_mut::<P>(buf, &mut out)?.len(); |
564 | | out.truncate(len); |
565 | | Ok(out) |
566 | | } |
567 | | } |
568 | | |
569 | | impl<Alg: BlockEncrypt> BlockEncryptMut for Alg { |
570 | 2.09k | fn encrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { |
571 | 2.09k | self.encrypt_with_backend(f); |
572 | 2.09k | } <&aes::autodetect::Aes128 as cipher::block::BlockEncryptMut>::encrypt_with_backend_mut::<ctr::backend::Closure<ctr::flavors::ctr32::Ctr32BE, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, cipher::stream_core::WriteBlockCtx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>>>> Line | Count | Source | 570 | 1.21k | fn encrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { | 571 | 1.21k | self.encrypt_with_backend(f); | 572 | 1.21k | } |
<&aes::autodetect::Aes128 as cipher::block::BlockEncryptMut>::encrypt_with_backend_mut::<ctr::backend::Closure<ctr::flavors::ctr32::Ctr32BE, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, cipher::stream_core::ApplyBlocksCtx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>>>> Line | Count | Source | 570 | 878 | fn encrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { | 571 | 878 | self.encrypt_with_backend(f); | 572 | 878 | } |
|
573 | | } |
574 | | |
575 | | impl<Alg: BlockDecrypt> BlockDecryptMut for Alg { |
576 | | fn decrypt_with_backend_mut(&mut self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { |
577 | | self.decrypt_with_backend(f); |
578 | | } |
579 | | } |
580 | | |
581 | | impl<Alg: BlockCipher> BlockCipher for &Alg {} |
582 | | |
583 | | impl<Alg: BlockEncrypt> BlockEncrypt for &Alg { |
584 | 2.09k | fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { |
585 | 2.09k | Alg::encrypt_with_backend(self, f); |
586 | 2.09k | } <&aes::autodetect::Aes128 as cipher::block::BlockEncrypt>::encrypt_with_backend::<ctr::backend::Closure<ctr::flavors::ctr32::Ctr32BE, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, cipher::stream_core::WriteBlockCtx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>>>> Line | Count | Source | 584 | 1.21k | fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { | 585 | 1.21k | Alg::encrypt_with_backend(self, f); | 586 | 1.21k | } |
<&aes::autodetect::Aes128 as cipher::block::BlockEncrypt>::encrypt_with_backend::<ctr::backend::Closure<ctr::flavors::ctr32::Ctr32BE, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, cipher::stream_core::ApplyBlocksCtx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>>>> Line | Count | Source | 584 | 878 | fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { | 585 | 878 | Alg::encrypt_with_backend(self, f); | 586 | 878 | } |
|
587 | | } |
588 | | |
589 | | impl<Alg: BlockDecrypt> BlockDecrypt for &Alg { |
590 | | fn decrypt_with_backend(&self, f: impl BlockClosure<BlockSize = Self::BlockSize>) { |
591 | | Alg::decrypt_with_backend(self, f); |
592 | | } |
593 | | } |
594 | | |
595 | | /// Closure used in methods which operate over separate blocks. |
596 | | struct BlockCtx<'inp, 'out, BS: ArrayLength<u8>> { |
597 | | block: InOut<'inp, 'out, Block<Self>>, |
598 | | } |
599 | | |
600 | | impl<'inp, 'out, BS: ArrayLength<u8>> BlockSizeUser for BlockCtx<'inp, 'out, BS> { |
601 | | type BlockSize = BS; |
602 | | } |
603 | | |
604 | | impl<'inp, 'out, BS: ArrayLength<u8>> BlockClosure for BlockCtx<'inp, 'out, BS> { |
605 | | #[inline(always)] |
606 | 2.70k | fn call<B: BlockBackend<BlockSize = BS>>(self, backend: &mut B) { |
607 | 2.70k | backend.proc_block(self.block); |
608 | 2.70k | } <cipher::block::BlockCtx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>> as cipher::block::BlockClosure>::call::<aes::ni::Aes128BackEnc> Line | Count | Source | 606 | 2.70k | fn call<B: BlockBackend<BlockSize = BS>>(self, backend: &mut B) { | 607 | 2.70k | backend.proc_block(self.block); | 608 | 2.70k | } |
Unexecuted instantiation: <cipher::block::BlockCtx<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>, typenum::bit::B0>> as cipher::block::BlockClosure>::call::<aes::soft::Aes128BackEnc> |
609 | | } |
610 | | |
611 | | /// Closure used in methods which operate over slice of blocks. |
612 | | struct BlocksCtx<'inp, 'out, BS: ArrayLength<u8>> { |
613 | | blocks: InOutBuf<'inp, 'out, Block<Self>>, |
614 | | } |
615 | | |
616 | | impl<'inp, 'out, BS: ArrayLength<u8>> BlockSizeUser for BlocksCtx<'inp, 'out, BS> { |
617 | | type BlockSize = BS; |
618 | | } |
619 | | |
620 | | impl<'inp, 'out, BS: ArrayLength<u8>> BlockClosure for BlocksCtx<'inp, 'out, BS> { |
621 | | #[inline(always)] |
622 | | fn call<B: BlockBackend<BlockSize = BS>>(self, backend: &mut B) { |
623 | | if B::ParBlocksSize::USIZE > 1 { |
624 | | let (chunks, tail) = self.blocks.into_chunks(); |
625 | | for chunk in chunks { |
626 | | backend.proc_par_blocks(chunk); |
627 | | } |
628 | | backend.proc_tail_blocks(tail); |
629 | | } else { |
630 | | for block in self.blocks { |
631 | | backend.proc_block(block); |
632 | | } |
633 | | } |
634 | | } |
635 | | } |
636 | | |
637 | | #[cfg(all(feature = "block-padding", feature = "alloc"))] |
638 | | fn allocate_out_vec<BS: BlockSizeUser>(len: usize) -> Vec<u8> { |
639 | | let bs = BS::BlockSize::USIZE; |
640 | | vec![0; bs * (len / bs + 1)] |
641 | | } |
642 | | |
643 | | /// Implement simple block backend |
644 | | #[macro_export] |
645 | | macro_rules! impl_simple_block_encdec { |
646 | | ( |
647 | | <$($N:ident$(:$b0:ident$(+$b:ident)*)?),*> |
648 | | $cipher:ident, $block_size:ty, $state:ident, $block:ident, |
649 | | encrypt: $enc_block:block |
650 | | decrypt: $dec_block:block |
651 | | ) => { |
652 | | impl<$($N$(:$b0$(+$b)*)?),*> $crate::BlockSizeUser for $cipher<$($N),*> { |
653 | | type BlockSize = $block_size; |
654 | | } |
655 | | |
656 | | impl<$($N$(:$b0$(+$b)*)?),*> $crate::BlockEncrypt for $cipher<$($N),*> { |
657 | | fn encrypt_with_backend(&self, f: impl $crate::BlockClosure<BlockSize = $block_size>) { |
658 | | struct EncBack<'a, $($N$(:$b0$(+$b)*)?),* >(&'a $cipher<$($N),*>); |
659 | | |
660 | | impl<'a, $($N$(:$b0$(+$b)*)?),* > $crate::BlockSizeUser for EncBack<'a, $($N),*> { |
661 | | type BlockSize = $block_size; |
662 | | } |
663 | | |
664 | | impl<'a, $($N$(:$b0$(+$b)*)?),* > $crate::ParBlocksSizeUser for EncBack<'a, $($N),*> { |
665 | | type ParBlocksSize = $crate::consts::U1; |
666 | | } |
667 | | |
668 | | impl<'a, $($N$(:$b0$(+$b)*)?),* > $crate::BlockBackend for EncBack<'a, $($N),*> { |
669 | | #[inline(always)] |
670 | | fn proc_block( |
671 | | &mut self, |
672 | | mut $block: $crate::inout::InOut<'_, '_, $crate::Block<Self>> |
673 | | ) { |
674 | | let $state: &$cipher<$($N),*> = self.0; |
675 | | $enc_block |
676 | | } |
677 | | } |
678 | | |
679 | | f.call(&mut EncBack(self)) |
680 | | } |
681 | | } |
682 | | |
683 | | impl<$($N$(:$b0$(+$b)*)?),*> $crate::BlockDecrypt for $cipher<$($N),*> { |
684 | | fn decrypt_with_backend(&self, f: impl $crate::BlockClosure<BlockSize = $block_size>) { |
685 | | struct DecBack<'a, $($N$(:$b0$(+$b)*)?),* >(&'a $cipher<$($N),*>); |
686 | | |
687 | | impl<'a, $($N$(:$b0$(+$b)*)?),* > $crate::BlockSizeUser for DecBack<'a, $($N),*> { |
688 | | type BlockSize = $block_size; |
689 | | } |
690 | | |
691 | | impl<'a, $($N$(:$b0$(+$b)*)?),* > $crate::ParBlocksSizeUser for DecBack<'a, $($N),*> { |
692 | | type ParBlocksSize = $crate::consts::U1; |
693 | | } |
694 | | |
695 | | impl<'a, $($N$(:$b0$(+$b)*)?),* > $crate::BlockBackend for DecBack<'a, $($N),*> { |
696 | | #[inline(always)] |
697 | | fn proc_block( |
698 | | &mut self, |
699 | | mut $block: $crate::inout::InOut<'_, '_, $crate::Block<Self>> |
700 | | ) { |
701 | | let $state: &$cipher<$($N),*> = self.0; |
702 | | $dec_block |
703 | | } |
704 | | } |
705 | | |
706 | | f.call(&mut DecBack(self)) |
707 | | } |
708 | | } |
709 | | }; |
710 | | ( |
711 | | $cipher:ident, $block_size:ty, $state:ident, $block:ident, |
712 | | encrypt: $enc_block:block |
713 | | decrypt: $dec_block:block |
714 | | ) => { |
715 | | $crate::impl_simple_block_encdec!( |
716 | | <> $cipher, $block_size, $state, $block, |
717 | | encrypt: $enc_block |
718 | | decrypt: $dec_block |
719 | | ); |
720 | | }; |
721 | | } |