Coverage Report

Created: 2025-11-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}