Skip to main content

cocoon_tpm_crypto/pure_rust/symcipher/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2023-2025 SUSE LLC
3// Author: Nicolai Stange <nstange@suse.de>
4
5//! Pure Rust, RustCrypto based backend for symmetric block ciphers.
6
7// Lifetimes are not obvious at first sight here, make the explicit.
8#![allow(clippy::needless_lifetimes)]
9
10extern crate alloc;
11use alloc::boxed::Box;
12
13#[cfg(feature = "aes")]
14use crate::symcipher::SymBlockCipherAesKeySize;
15#[cfg(feature = "camellia")]
16use crate::symcipher::SymBlockCipherCamelliaKeySize;
17#[cfg(feature = "sm4")]
18use crate::symcipher::SymBlockCipherSm4KeySize;
19use crate::symcipher::{SymBlockCipherAlg, transform_next_blocks, transform_next_blocks_in_place};
20use crate::{
21    CryptoError,
22    io_slices::{CryptoPeekableIoSlicesMutIter, CryptoWalkableIoSlicesIter, CryptoWalkableIoSlicesMutIter},
23};
24use crate::{
25    tpm2_interface,
26    utils_common::{alloc::box_try_new_with, zeroize},
27};
28use core::{convert, ops::Deref as _};
29
30use cipher::{BlockDecryptMut as _, BlockEncryptMut as _, IvState as _};
31#[allow(unused_imports)]
32use crypto_common::{
33    self, BlockSizeUser as _, InnerInit as _, InnerIvInit as _, IvSizeUser as _, KeyInit as _, KeySizeUser as _,
34};
35use generic_array::typenum::Unsigned as _;
36
37#[cfg(feature = "ctr")]
38mod ctr_impl;
39
40/// Map pair of (symbolic block cipher, key size) to the block length.
41macro_rules! block_cipher_to_block_len {
42    (Aes, 128) => {
43        16
44    };
45    (Aes, 192) => {
46        16
47    };
48    (Aes, 256) => {
49        16
50    };
51    (Camellia, 128) => {
52        16
53    };
54    (Camellia, 192) => {
55        16
56    };
57    (Camellia, 256) => {
58        16
59    };
60    (Sm4, 128) => {
61        16
62    };
63}
64
65/// Generate a `match {}` on SymBlockCipherAlg and invoke a macro in the body of
66/// each match arm.
67///
68/// The supplied macro `m` gets invoked with (`$args`, symbolic block cipher,
69/// key size) for each arm.
70macro_rules! gen_match_on_block_cipher_alg {
71    ($block_cipher_alg_value:expr, $m:ident $(, $($args:tt),*)?) => {
72        match $block_cipher_alg_value {
73            #[cfg(feature = "aes")]
74            SymBlockCipherAlg::Aes(key_size) => {
75                match key_size {
76                    SymBlockCipherAesKeySize::Aes128 => {
77                        $m!($($($args),*,)? Aes, 128)
78                    },
79                    SymBlockCipherAesKeySize::Aes192 => {
80                        $m!($($($args),*,)? Aes, 192)
81                    },
82                    SymBlockCipherAesKeySize::Aes256 => {
83                        $m!($($($args),*,)? Aes, 256)
84                    },
85                }
86            },
87            #[cfg(feature = "camellia")]
88            SymBlockCipherAlg::Camellia(key_size) => {
89                match key_size {
90                    SymBlockCipherCamelliaKeySize::Camellia128 => {
91                        $m!($($($args),*,)? Camellia, 128)
92                    },
93                    SymBlockCipherCamelliaKeySize::Camellia192 => {
94                        $m!($($($args),*,)? Camellia, 192)
95                    },
96                    SymBlockCipherCamelliaKeySize::Camellia256 => {
97                        $m!($($($args),*,)? Camellia, 256)
98                    },
99                }
100            },
101            #[cfg(feature = "sm4")]
102            SymBlockCipherAlg::Sm4(key_size) => {
103                match key_size {
104                    SymBlockCipherSm4KeySize::Sm4_128 => {
105                        $m!($($($args),*,)? Sm4, 128)
106                    },
107                }
108            },
109        }
110    };
111}
112
113/// Map a pair of (symbolic block cipher alg, key size) to a variant of
114/// SymBlockCipherAlg.
115macro_rules! block_cipher_to_sym_block_cipher_alg_variant {
116    (Aes, 128) => {
117        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128)
118    };
119    (Aes, 192) => {
120        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192)
121    };
122    (Aes, 256) => {
123        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256)
124    };
125    (Camellia, 128) => {
126        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128)
127    };
128    (Camellia, 192) => {
129        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192)
130    };
131    (Camellia, 256) => {
132        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256)
133    };
134    (Sm4, 128) => {
135        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128)
136    };
137}
138
139macro_rules! gen_match_on_tpmi_alg_cipher_mode {
140    ($mode_value:expr, $m:ident $(, $($args:tt),*)?) => {
141        match $mode_value {
142            #[cfg(feature = "ctr")]
143            tpm2_interface::TpmiAlgCipherMode::Ctr => {
144                $m!($($($args),*,)? Ctr)
145            },
146            #[cfg(feature = "ofb")]
147            tpm2_interface::TpmiAlgCipherMode::Ofb => {
148                $m!($($($args),*,)? Ofb)
149            },
150            #[cfg(feature = "cbc")]
151            tpm2_interface::TpmiAlgCipherMode::Cbc => {
152                $m!($($($args),*,)? Cbc)
153            },
154            #[cfg(feature = "cfb")]
155            tpm2_interface::TpmiAlgCipherMode::Cfb => {
156                $m!($($($args),*,)? Cfb)
157            },
158            #[cfg(feature = "ecb")]
159            tpm2_interface::TpmiAlgCipherMode::Ecb => {
160                $m!($($($args),*,)? Ecb)
161            },
162        }
163    };
164}
165
166// Convert a symbolic mode to the corresponding TpmiAlgCipherMode variant.
167macro_rules! mode_to_tpmi_alg_cipher_mode {
168    (Ctr) => {
169        tpm2_interface::TpmiAlgCipherMode::Ctr
170    };
171    (Ofb) => {
172        tpm2_interface::TpmiAlgCipherMode::Ofb
173    };
174    (Cbc) => {
175        tpm2_interface::TpmiAlgCipherMode::Cbc
176    };
177    (Cfb) => {
178        tpm2_interface::TpmiAlgCipherMode::Cfb
179    };
180    (Ecb) => {
181        tpm2_interface::TpmiAlgCipherMode::Ecb
182    };
183}
184
185// This gets invoked with the symbolic mode identifier appended to the args.
186macro_rules! __gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg {
187    ($block_cipher_alg_value:tt, $m:ident, $($args_and_mode_id:tt),*) => {
188        gen_match_on_block_cipher_alg!($block_cipher_alg_value, $m, $($args_and_mode_id),*)
189    };
190}
191
192/// Generated a nested `match {}` on a pair of
193/// [`TpmiAlgCipherMode`](tpm2_interface::TpmiAlgCipherMode) and
194/// [`SymBlockCipherAlg`]. The macro `$m` will get invoked within each match arm
195/// with the `$args` passed through and extended by a triplet of (symbolic mode,
196/// symbolic block cipher, key size) at the tail.
197macro_rules! gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg {
198    ($mode_value:expr, $block_cipher_alg_value:expr, $m:ident $(, $($args:tt),*)?) => {
199        gen_match_on_tpmi_alg_cipher_mode!(
200            $mode_value,
201            __gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg, $block_cipher_alg_value, $m $(,$($args),*)?
202        )
203    };
204}
205
206/// Map a triplet of (symbolic mode, symbolic block cipher, key size) to the IV
207/// length.
208macro_rules! mode_and_block_cipher_to_iv_len {
209    (Ctr, $block_alg_id:ident, $key_size:tt) => {
210        block_cipher_to_block_len!($block_alg_id, $key_size)
211    };
212    (Ofb, $block_alg_id:ident, $key_size:tt) => {
213        block_cipher_to_block_len!($block_alg_id, $key_size)
214    };
215    (Cbc, $block_alg_id:ident, $key_size:tt) => {
216        block_cipher_to_block_len!($block_alg_id, $key_size)
217    };
218    (Cfb, $block_alg_id:ident, $key_size:tt) => {
219        block_cipher_to_block_len!($block_alg_id, $key_size)
220    };
221    (Ecb, $_block_alg_id:ident, $_key_size:tt) => {
222        0
223    };
224}
225
226macro_rules! mode_supports_partial_last_block {
227    (Ctr) => {
228        true
229    };
230    (Ofb) => {
231        true
232    };
233    (Cbc) => {
234        false
235    };
236    (Cfb) => {
237        true
238    };
239    (Ecb) => {
240        false
241    };
242}
243
244// Used internally from multiple functions of
245// SymBlockCipherModeEncryptionInstanceState
246// and SymBlockCipherModeDecryptionInstanceState.
247macro_rules! sym_block_cipher_mode_instance_gen_transform {
248    ($gen_mode_transform_new_impl_instance_snippet:ident,
249     $gen_mode_block_transform_cb_snippet:ident,
250     $gen_mode_transform_grab_iv_snippet:ident,
251     $dst_io_slices:ident,
252     $src_io_slices:ident,
253     $iv:ident, $iv_out_opt:ident,
254     $mode_id:ident, $block_alg_id:ident, $key_size:tt, $block_cipher_instance:ident) => {{
255        const MODE_SUPPORTS_PARTIAL_LAST_BLOCK: bool = mode_supports_partial_last_block!($mode_id);
256        const BLOCK_LEN: usize = block_cipher_to_block_len!($block_alg_id, $key_size);
257        let dst_len = $dst_io_slices.total_len()?;
258        if dst_len % BLOCK_LEN != 0 {
259            if !MODE_SUPPORTS_PARTIAL_LAST_BLOCK {
260                return Err(CryptoError::InvalidMessageLength);
261            } else if $iv_out_opt.is_some() {
262                // Don't allow iv_out retrieval for partial last blocks.
263                return Err(CryptoError::Internal);
264            }
265        }
266        if $src_io_slices.total_len()? != dst_len {
267            return Err(CryptoError::Internal);
268        }
269
270        let mut mode_transform_impl_instance = $gen_mode_transform_new_impl_instance_snippet!(
271            $mode_id,
272            $block_alg_id,
273            $key_size,
274            $block_cipher_instance,
275            $iv,
276            $iv_out_opt,
277        );
278
279        let mut scratch_block_buf = zeroize::Zeroizing::from([0u8; BLOCK_LEN]);
280
281        loop {
282            if !transform_next_blocks::<MODE_SUPPORTS_PARTIAL_LAST_BLOCK, _>(
283                $dst_io_slices,
284                $src_io_slices,
285                $gen_mode_block_transform_cb_snippet!(mode_transform_impl_instance),
286                BLOCK_LEN,
287                scratch_block_buf.as_mut_slice(),
288            )? {
289                break;
290            }
291        }
292
293        $gen_mode_transform_grab_iv_snippet!(
294            $mode_id,
295            $block_alg_id,
296            $key_size,
297            mode_transform_impl_instance,
298            $iv_out_opt
299        );
300    }};
301}
302
303// Used internally from multiple functions of
304// SymBlockCipherModeEncryptionInstanceState
305// and SymBlockCipherModeDecryptionInstanceState.
306macro_rules! sym_block_cipher_mode_instance_gen_transform_in_place {
307    ($gen_mode_transform_new_impl_instance_snippet:ident,
308     $gen_mode_block_transform_cb_snippet:ident,
309     $gen_mode_transform_grab_iv_snippet:ident,
310     $dst_io_slices:ident,
311     $iv:ident, $iv_out_opt:ident,
312     $mode_id:ident, $block_alg_id:ident, $key_size:tt, $block_cipher_instance:ident) => {{
313        const MODE_SUPPORTS_PARTIAL_LAST_BLOCK: bool = mode_supports_partial_last_block!($mode_id);
314        const BLOCK_LEN: usize = block_cipher_to_block_len!($block_alg_id, $key_size);
315        let dst_len = $dst_io_slices.total_len()?;
316        if dst_len % BLOCK_LEN != 0 {
317            if !MODE_SUPPORTS_PARTIAL_LAST_BLOCK {
318                return Err(CryptoError::InvalidMessageLength);
319            } else if $iv_out_opt.is_some() {
320                // Don't allow iv_out retrieval for partial last blocks.
321                return Err(CryptoError::Internal);
322            }
323        }
324        let mut mode_transform_impl_instance = $gen_mode_transform_new_impl_instance_snippet!(
325            $mode_id,
326            $block_alg_id,
327            $key_size,
328            $block_cipher_instance,
329            $iv,
330            $iv_out_opt,
331        );
332
333        let mut scratch_block_buf = zeroize::Zeroizing::from([0u8; BLOCK_LEN]);
334
335        loop {
336            if !transform_next_blocks_in_place::<MODE_SUPPORTS_PARTIAL_LAST_BLOCK, _, _>(
337                &mut $dst_io_slices,
338                $gen_mode_block_transform_cb_snippet!(mode_transform_impl_instance),
339                BLOCK_LEN,
340                scratch_block_buf.as_mut_slice(),
341            )? {
342                break;
343            }
344        }
345
346        $gen_mode_transform_grab_iv_snippet!(
347            $mode_id,
348            $block_alg_id,
349            $key_size,
350            mode_transform_impl_instance,
351            $iv_out_opt
352        );
353    }};
354}
355
356pub struct SymBlockCipherModeEncryptionInstance {
357    state: Box<SymBlockCipherModeEncryptionInstanceState>,
358}
359
360impl SymBlockCipherModeEncryptionInstance {
361    /// Instantiate a `SymBlockCipherModeEncryptionInstance` from a triplet of
362    /// [block cipher mode identifier](tpm2_interface::TpmiAlgCipherMode),
363    /// [symmetric block cipher algorithm identifier](SymBlockCipherAlg) and
364    /// a raw key byte slice.
365    ///
366    /// # Arguments:
367    ///
368    /// * `mode_id`  - The [block cipher
369    ///   mode](tpm2_interface::TpmiAlgCipherMode) to use.
370    /// * `alg_id` - The [symmetric block cipher algorithm](SymBlockCipherAlg)
371    ///   to be used for this instance.
372    /// * `key` - The raw key bytes. It's length must match the [expected key
373    ///   length](SymBlockCipherAlg::key_len) for `alg` or an error will get
374    ///   returned.
375    #[inline(never)]
376    pub fn new(
377        mode_id: tpm2_interface::TpmiAlgCipherMode,
378        alg_id: &SymBlockCipherAlg,
379        key: &[u8],
380    ) -> Result<Self, CryptoError> {
381        Ok(Self {
382            state: SymBlockCipherModeEncryptionInstanceState::new(mode_id, alg_id, key)?,
383        })
384    }
385
386    /// Try to clone a `SymBlockModeCipherEncryptionInstance`.
387    #[inline(never)]
388    pub fn try_clone(&self) -> Result<Self, CryptoError> {
389        Ok(Self {
390            state: box_try_new_with(
391                || -> Result<SymBlockCipherModeEncryptionInstanceState, convert::Infallible> {
392                    Ok(self.state.deref().clone())
393                },
394            )?,
395        })
396    }
397
398    /// Obtain the instance's associated block cipher algorithm's block length.
399    ///
400    /// Equivalent to
401    /// [`SymBlockCipherAlg::block_len()`](SymBlockCipherAlg::block_len).
402    pub fn block_cipher_block_len(&self) -> usize {
403        self.state.block_cipher_block_len()
404    }
405
406    /// Determine the IV length for use with
407    /// `SymBlockCipherModeEncryptionInstance`.
408    ///
409    /// Equivalent to
410    /// [`SymBlockCipherAlg::iv_len_for_mode()`](SymBlockCipherAlg::iv_len_for_mode).
411    pub fn iv_len(&self) -> usize {
412        self.state.iv_len()
413    }
414
415    /// Encrypt data from buffer to buffer.
416    ///
417    /// The source and destination buffers must be equal in length or an error
418    /// will get returned. Depending on the block cipher mode, their lengths
419    /// must perhaps be aligned to the [block cipher block
420    /// length](Self::block_cipher_block_len), an error will get returned
421    /// otherwise. No padding will get inserted.
422    ///
423    /// Processing a request does not alter `self`'s state -- in particular the
424    /// IV must get provided for each new requst anew.
425    ///
426    /// # Arguments:
427    ///
428    /// * `iv` - The IV to use. Its length must match the expected [IV
429    ///   length](Self::iv_len).
430    /// * `dst` - The destination buffers to write the encrypted message to.
431    /// * `src` - The source buffers holding the cleartext message to encrypt.
432    /// * `iv_out` - Optional buffer receiving the final IV as ouput from the
433    ///   block cipher mode. Attempting to retrieve the final IV when the to be
434    ///   encrypted data's length is not an integral multiple of the [block
435    ///   cipher block size ](Self::block_cipher_block_len) is ill-defined and
436    ///   considered an error.
437    pub fn encrypt<'a, 'b, DI: CryptoWalkableIoSlicesMutIter<'a>, SI: CryptoWalkableIoSlicesIter<'b>>(
438        &self,
439        iv: &[u8],
440        mut dst: DI,
441        mut src: SI,
442        iv_out: Option<&mut [u8]>,
443    ) -> Result<(), CryptoError> {
444        self.state.encrypt(iv, &mut dst, &mut src, iv_out)
445    }
446
447    /// Encrypt data in place.
448    ///
449    /// Depending on the block cipher mode, the source/destination buffer's
450    /// length must perhaps be aligned to the [block cipher block
451    /// length](Self::block_cipher_block_len), an error will get returned
452    /// otherwise. No padding will get inserted.
453    ///
454    /// Processing a request does not alter `self`'s state -- in particular the
455    /// IV must get provided for each new requst anew.
456    ///
457    /// <div class="warning">
458    ///
459    /// Unlike it's the case with [`encrypt()`](Self::encrypt), the
460    /// source/destination buffer's generic `DI` type is not `dyn`
461    /// compatible. The compiler will emit a separate instance for each
462    /// individual `DI` `encrypt_in_place()` gets invoked with. Be vigilant
463    /// of template bloat, prefer [`encrypt()`](Self::encrypt) if feasible and
464    /// try to not use too exotic types for `DI` here otherwise.
465    ///
466    /// </div>
467    ///
468    /// # Arguments:
469    ///
470    /// * `iv` - The IV to use. Its length must match the expected [IV
471    ///   length](Self::iv_len).
472    /// * `dst` - The source/destination buffers initially holding the cleartext
473    ///   message and receiving the encrypted result.
474    /// * `iv_out` - Optional buffer receiving the final IV as ouput from the
475    ///   block cipher mode. Attempting to retrieve the final IV when the to be
476    ///   encrypted data's length is not an integral multiple of the [block
477    ///   cipher block size ](Self::block_cipher_block_len) is ill-defined and
478    ///   considered an error.
479    pub fn encrypt_in_place<'a, 'b, DI: CryptoPeekableIoSlicesMutIter<'a>>(
480        &self,
481        iv: &[u8],
482        dst: DI,
483        iv_out: Option<&mut [u8]>,
484    ) -> Result<(), CryptoError> {
485        self.state.encrypt_in_place(iv, dst, iv_out)
486    }
487}
488
489// All supported block cipher implementations possibly wrapped implement
490// ZeroizeOnDrop.
491#[cfg(feature = "zeroize")]
492impl zeroize::ZeroizeOnDrop for SymBlockCipherModeEncryptionInstance {}
493
494/// Map a triplet of (mode, block cipher, key length) to a block cipher
495/// implementation suitable for encryption with that mode.
496macro_rules! enc_mode_and_block_cipher_to_block_cipher_impl {
497    (Ctr, Aes, 128) => {
498        aes::Aes128Enc
499    };
500    (Ctr, Aes, 192) => {
501        aes::Aes192Enc
502    };
503    (Ctr, Aes, 256) => {
504        aes::Aes256Enc
505    };
506    (Ctr, Camellia, 128) => {
507        // No differentiation between encryptor/decryptor made in camellia crate.
508        camellia::Camellia128
509    };
510    (Ctr, Camellia, 192) => {
511        // No differentiation between encryptor/decryptor made in camellia crate.
512        camellia::Camellia192
513    };
514    (Ctr, Camellia, 256) => {
515        // No differentiation between encryptor/decryptor made in camellia crate.
516        camellia::Camellia256
517    };
518    (Ctr, Sm4, 128) => {
519        // No differentiation between encryptor/decryptor made in sm4 crate.
520        sm4::Sm4
521    };
522
523    (Ofb, Aes, 128) => {
524        aes::Aes128Enc
525    };
526    (Ofb, Aes, 192) => {
527        aes::Aes192Enc
528    };
529    (Ofb, Aes, 256) => {
530        aes::Aes256Enc
531    };
532    (Ofb, Camellia, 128) => {
533        // No differentiation between encryptor/decryptor made in camellia crate.
534        camellia::Camellia128
535    };
536    (Ofb, Camellia, 192) => {
537        // No differentiation between encryptor/decryptor made in camellia crate.
538        camellia::Camellia192
539    };
540    (Ofb, Camellia, 256) => {
541        // No differentiation between encryptor/decryptor made in camellia crate.
542        camellia::Camellia256
543    };
544    (Ofb, Sm4, 128) => {
545        // No differentiation between encryptor/decryptor made in sm4 crate.
546        sm4::Sm4
547    };
548
549    (Cbc, Aes, 128) => {
550        aes::Aes128Enc
551    };
552    (Cbc, Aes, 192) => {
553        aes::Aes192Enc
554    };
555    (Cbc, Aes, 256) => {
556        aes::Aes256Enc
557    };
558    (Cbc, Camellia, 128) => {
559        // No differentiation between encryptor/decryptor made in camellia crate.
560        camellia::Camellia128
561    };
562    (Cbc, Camellia, 192) => {
563        // No differentiation between encryptor/decryptor made in camellia crate.
564        camellia::Camellia192
565    };
566    (Cbc, Camellia, 256) => {
567        // No differentiation between encryptor/decryptor made in camellia crate.
568        camellia::Camellia256
569    };
570    (Cbc, Sm4, 128) => {
571        // No differentiation between encryptor/decryptor made in sm4 crate.
572        sm4::Sm4
573    };
574
575    (Cfb, Aes, 128) => {
576        // cfb_mode needs a Decryptor to impl IvState.
577        aes::Aes128
578    };
579    (Cfb, Aes, 192) => {
580        // cfb_mode needs a Decryptor to impl IvState.
581        aes::Aes192
582    };
583    (Cfb, Aes, 256) => {
584        // cfb_mode needs a Decryptor to impl IvState.
585        aes::Aes256
586    };
587    (Cfb, Camellia, 128) => {
588        // No differentiation between encryptor/decryptor made in camellia crate.
589        camellia::Camellia128
590    };
591    (Cfb, Camellia, 192) => {
592        // No differentiation between encryptor/decryptor made in camellia crate.
593        camellia::Camellia192
594    };
595    (Cfb, Camellia, 256) => {
596        // No differentiation between encryptor/decryptor made in camellia crate.
597        camellia::Camellia256
598    };
599    (Cfb, Sm4, 128) => {
600        // No differentiation between encryptor/decryptor made in sm4 crate.
601        sm4::Sm4
602    };
603
604    (Ecb, Aes, 128) => {
605        aes::Aes128Enc
606    };
607    (Ecb, Aes, 192) => {
608        aes::Aes192Enc
609    };
610    (Ecb, Aes, 256) => {
611        aes::Aes256Enc
612    };
613    (Ecb, Camellia, 128) => {
614        // No differentiation between encryptor/decryptor made in camellia crate.
615        camellia::Camellia128
616    };
617    (Ecb, Camellia, 192) => {
618        // No differentiation between encryptor/decryptor made in camellia crate.
619        camellia::Camellia192
620    };
621    (Ecb, Camellia, 256) => {
622        // No differentiation between encryptor/decryptor made in camellia crate.
623        camellia::Camellia256
624    };
625    (Ecb, Sm4, 128) => {
626        // No differentiation between encryptor/decryptor made in sm4 crate.
627        sm4::Sm4
628    };
629}
630
631#[derive(Clone)]
632enum SymBlockCipherModeEncryptionInstanceState {
633    #[cfg(all(feature = "ctr", feature = "aes"))]
634    CtrAes128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Aes, 128)),
635    #[cfg(all(feature = "ctr", feature = "aes"))]
636    CtrAes192(enc_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Aes, 192)),
637    #[cfg(all(feature = "ctr", feature = "aes"))]
638    CtrAes256(enc_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Aes, 256)),
639    #[cfg(all(feature = "ctr", feature = "camellia"))]
640    CtrCamellia128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Camellia, 128)),
641    #[cfg(all(feature = "ctr", feature = "camellia"))]
642    CtrCamellia192(enc_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Camellia, 192)),
643    #[cfg(all(feature = "ctr", feature = "camellia"))]
644    CtrCamellia256(enc_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Camellia, 256)),
645    #[cfg(all(feature = "ctr", feature = "sm4"))]
646    CtrSm4_128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Sm4, 128)),
647
648    #[cfg(all(feature = "ofb", feature = "aes"))]
649    OfbAes128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Aes, 128)),
650    #[cfg(all(feature = "ofb", feature = "aes"))]
651    OfbAes192(enc_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Aes, 192)),
652    #[cfg(all(feature = "ofb", feature = "aes"))]
653    OfbAes256(enc_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Aes, 256)),
654    #[cfg(all(feature = "ofb", feature = "camellia"))]
655    OfbCamellia128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Camellia, 128)),
656    #[cfg(all(feature = "ofb", feature = "camellia"))]
657    OfbCamellia192(enc_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Camellia, 192)),
658    #[cfg(all(feature = "ofb", feature = "camellia"))]
659    OfbCamellia256(enc_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Camellia, 256)),
660    #[cfg(all(feature = "ofb", feature = "sm4"))]
661    OfbSm4_128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Sm4, 128)),
662
663    #[cfg(all(feature = "cbc", feature = "aes"))]
664    CbcAes128(enc_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Aes, 128)),
665    #[cfg(all(feature = "cbc", feature = "aes"))]
666    CbcAes192(enc_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Aes, 192)),
667    #[cfg(all(feature = "cbc", feature = "aes"))]
668    CbcAes256(enc_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Aes, 256)),
669    #[cfg(all(feature = "cbc", feature = "camellia"))]
670    CbcCamellia128(enc_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Camellia, 128)),
671    #[cfg(all(feature = "cbc", feature = "camellia"))]
672    CbcCamellia192(enc_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Camellia, 192)),
673    #[cfg(all(feature = "cbc", feature = "camellia"))]
674    CbcCamellia256(enc_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Camellia, 256)),
675    #[cfg(all(feature = "cbc", feature = "sm4"))]
676    CbcSm4_128(enc_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Sm4, 128)),
677
678    #[cfg(all(feature = "cfb", feature = "aes"))]
679    CfbAes128(enc_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Aes, 128)),
680    #[cfg(all(feature = "cfb", feature = "aes"))]
681    CfbAes192(enc_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Aes, 192)),
682    #[cfg(all(feature = "cfb", feature = "aes"))]
683    CfbAes256(enc_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Aes, 256)),
684    #[cfg(all(feature = "cfb", feature = "camellia"))]
685    CfbCamellia128(enc_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Camellia, 128)),
686    #[cfg(all(feature = "cfb", feature = "camellia"))]
687    CfbCamellia192(enc_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Camellia, 192)),
688    #[cfg(all(feature = "cfb", feature = "camellia"))]
689    CfbCamellia256(enc_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Camellia, 256)),
690    #[cfg(all(feature = "cfb", feature = "sm4"))]
691    CfbSm4_128(enc_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Sm4, 128)),
692
693    #[cfg(all(feature = "ecb", feature = "aes"))]
694    EcbAes128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Aes, 128)),
695    #[cfg(all(feature = "ecb", feature = "aes"))]
696    EcbAes192(enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Aes, 192)),
697    #[cfg(all(feature = "ecb", feature = "aes"))]
698    EcbAes256(enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Aes, 256)),
699    #[cfg(all(feature = "ecb", feature = "camellia"))]
700    EcbCamellia128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Camellia, 128)),
701    #[cfg(all(feature = "ecb", feature = "camellia"))]
702    EcbCamellia192(enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Camellia, 192)),
703    #[cfg(all(feature = "ecb", feature = "camellia"))]
704    EcbCamellia256(enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Camellia, 256)),
705    #[cfg(all(feature = "ecb", feature = "sm4"))]
706    EcbSm4_128(enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Sm4, 128)),
707}
708
709/// Generate a `match {}` on SymBlockCipherModeEncryptionInstanceState and
710/// invoke a macro in the body of each match arm.
711///
712/// The supplied macro `m` gets invoked with (`$args`, symbolic mode, symbolic
713/// block cipher, key size, `$block_cipher_instance`) for each arm, where
714/// identifier `$block_cipher_instance` is bound to the variant's respective
715/// block cipher implementation instance member.
716macro_rules! gen_match_on_block_cipher_mode_encryption_instance {
717    ($block_cipher_mode_instance_value:expr, $m:ident, $block_cipher_instance:ident $(, $($args:tt),*)?) => {
718        match $block_cipher_mode_instance_value {
719            #[cfg(all(feature = "ctr", feature = "aes"))]
720            SymBlockCipherModeEncryptionInstanceState::CtrAes128($block_cipher_instance) => {
721                $m!($($($args),*,)? Ctr, Aes, 128, $block_cipher_instance)
722            },
723            #[cfg(all(feature = "ctr", feature = "aes"))]
724            SymBlockCipherModeEncryptionInstanceState::CtrAes192($block_cipher_instance) => {
725                $m!($($($args),*,)? Ctr, Aes, 192, $block_cipher_instance)
726            },
727            #[cfg(all(feature = "ctr", feature = "aes"))]
728            SymBlockCipherModeEncryptionInstanceState::CtrAes256($block_cipher_instance) => {
729                $m!($($($args),*,)? Ctr, Aes, 256, $block_cipher_instance)
730            },
731            #[cfg(all(feature = "ctr", feature = "camellia"))]
732            SymBlockCipherModeEncryptionInstanceState::CtrCamellia128($block_cipher_instance) => {
733                $m!($($($args),*,)? Ctr, Camellia, 128, $block_cipher_instance)
734            },
735            #[cfg(all(feature = "ctr", feature = "camellia"))]
736            SymBlockCipherModeEncryptionInstanceState::CtrCamellia192($block_cipher_instance) => {
737                $m!($($($args),*,)? Ctr, Camellia, 192, $block_cipher_instance)
738            },
739            #[cfg(all(feature = "ctr", feature = "camellia"))]
740            SymBlockCipherModeEncryptionInstanceState::CtrCamellia256($block_cipher_instance) => {
741                $m!($($($args),*,)? Ctr, Camellia, 256, $block_cipher_instance)
742            },
743            #[cfg(all(feature = "ctr", feature = "sm4"))]
744            SymBlockCipherModeEncryptionInstanceState::CtrSm4_128($block_cipher_instance) => {
745                $m!($($($args),*,)? Ctr, Sm4, 128, $block_cipher_instance)
746            },
747
748            #[cfg(all(feature = "ofb", feature = "aes"))]
749            SymBlockCipherModeEncryptionInstanceState::OfbAes128($block_cipher_instance) => {
750                $m!($($($args),*,)? Ofb, Aes, 128, $block_cipher_instance)
751            },
752            #[cfg(all(feature = "ofb", feature = "aes"))]
753            SymBlockCipherModeEncryptionInstanceState::OfbAes192($block_cipher_instance) => {
754                $m!($($($args),*,)? Ofb, Aes, 192, $block_cipher_instance)
755            },
756            #[cfg(all(feature = "ofb", feature = "aes"))]
757            SymBlockCipherModeEncryptionInstanceState::OfbAes256($block_cipher_instance) => {
758                $m!($($($args),*,)? Ofb, Aes, 256, $block_cipher_instance)
759            },
760            #[cfg(all(feature = "ofb", feature = "camellia"))]
761            SymBlockCipherModeEncryptionInstanceState::OfbCamellia128($block_cipher_instance) => {
762                $m!($($($args),*,)? Ofb, Camellia, 128, $block_cipher_instance)
763            },
764            #[cfg(all(feature = "ofb", feature = "camellia"))]
765            SymBlockCipherModeEncryptionInstanceState::OfbCamellia192($block_cipher_instance) => {
766                $m!($($($args),*,)? Ofb, Camellia, 192, $block_cipher_instance)
767            },
768            #[cfg(all(feature = "ofb", feature = "camellia"))]
769            SymBlockCipherModeEncryptionInstanceState::OfbCamellia256($block_cipher_instance) => {
770                $m!($($($args),*,)? Ofb, Camellia, 256, $block_cipher_instance)
771            },
772            #[cfg(all(feature = "ofb", feature = "sm4"))]
773            SymBlockCipherModeEncryptionInstanceState::OfbSm4_128($block_cipher_instance) => {
774                $m!($($($args),*,)? Ofb, Sm4, 128, $block_cipher_instance)
775            },
776
777            #[cfg(all(feature = "cbc", feature = "aes"))]
778            SymBlockCipherModeEncryptionInstanceState::CbcAes128($block_cipher_instance) => {
779                $m!($($($args),*,)? Cbc, Aes, 128, $block_cipher_instance)
780            },
781            #[cfg(all(feature = "cbc", feature = "aes"))]
782            SymBlockCipherModeEncryptionInstanceState::CbcAes192($block_cipher_instance) => {
783                $m!($($($args),*,)? Cbc, Aes, 192, $block_cipher_instance)
784            },
785            #[cfg(all(feature = "cbc", feature = "aes"))]
786            SymBlockCipherModeEncryptionInstanceState::CbcAes256($block_cipher_instance) => {
787                $m!($($($args),*,)? Cbc, Aes, 256, $block_cipher_instance)
788            },
789            #[cfg(all(feature = "cbc", feature = "camellia"))]
790            SymBlockCipherModeEncryptionInstanceState::CbcCamellia128($block_cipher_instance) => {
791                $m!($($($args),*,)? Cbc, Camellia, 128, $block_cipher_instance)
792            },
793            #[cfg(all(feature = "cbc", feature = "camellia"))]
794            SymBlockCipherModeEncryptionInstanceState::CbcCamellia192($block_cipher_instance) => {
795                $m!($($($args),*,)? Cbc, Camellia, 192, $block_cipher_instance)
796            },
797            #[cfg(all(feature = "cbc", feature = "camellia"))]
798            SymBlockCipherModeEncryptionInstanceState::CbcCamellia256($block_cipher_instance) => {
799                $m!($($($args),*,)? Cbc, Camellia, 256, $block_cipher_instance)
800            },
801            #[cfg(all(feature = "cbc", feature = "sm4"))]
802            SymBlockCipherModeEncryptionInstanceState::CbcSm4_128($block_cipher_instance) => {
803                $m!($($($args),*,)? Cbc, Sm4, 128, $block_cipher_instance)
804            },
805
806            #[cfg(all(feature = "cfb", feature = "aes"))]
807            SymBlockCipherModeEncryptionInstanceState::CfbAes128($block_cipher_instance) => {
808                $m!($($($args),*,)? Cfb, Aes, 128, $block_cipher_instance)
809            },
810            #[cfg(all(feature = "cfb", feature = "aes"))]
811            SymBlockCipherModeEncryptionInstanceState::CfbAes192($block_cipher_instance) => {
812                $m!($($($args),*,)? Cfb, Aes, 192, $block_cipher_instance)
813            },
814            #[cfg(all(feature = "cfb", feature = "aes"))]
815            SymBlockCipherModeEncryptionInstanceState::CfbAes256($block_cipher_instance) => {
816                $m!($($($args),*,)? Cfb, Aes, 256, $block_cipher_instance)
817            },
818            #[cfg(all(feature = "cfb", feature = "camellia"))]
819            SymBlockCipherModeEncryptionInstanceState::CfbCamellia128($block_cipher_instance) => {
820                $m!($($($args),*,)? Cfb, Camellia, 128, $block_cipher_instance)
821            },
822            #[cfg(all(feature = "cfb", feature = "camellia"))]
823            SymBlockCipherModeEncryptionInstanceState::CfbCamellia192($block_cipher_instance) => {
824                $m!($($($args),*,)? Cfb, Camellia, 192, $block_cipher_instance)
825            },
826            #[cfg(all(feature = "cfb", feature = "camellia"))]
827            SymBlockCipherModeEncryptionInstanceState::CfbCamellia256($block_cipher_instance) => {
828                $m!($($($args),*,)? Cfb, Camellia, 256, $block_cipher_instance)
829            },
830            #[cfg(all(feature = "cfb", feature = "sm4"))]
831            SymBlockCipherModeEncryptionInstanceState::CfbSm4_128($block_cipher_instance) => {
832                $m!($($($args),*,)? Cfb, Sm4, 128, $block_cipher_instance)
833            },
834
835            #[cfg(all(feature = "ecb", feature = "aes"))]
836            SymBlockCipherModeEncryptionInstanceState::EcbAes128($block_cipher_instance) => {
837                $m!($($($args),*,)? Ecb, Aes, 128, $block_cipher_instance)
838            },
839            #[cfg(all(feature = "ecb", feature = "aes"))]
840            SymBlockCipherModeEncryptionInstanceState::EcbAes192($block_cipher_instance) => {
841                $m!($($($args),*,)? Ecb, Aes, 192, $block_cipher_instance)
842            },
843            #[cfg(all(feature = "ecb", feature = "aes"))]
844            SymBlockCipherModeEncryptionInstanceState::EcbAes256($block_cipher_instance) => {
845                $m!($($($args),*,)? Ecb, Aes, 256, $block_cipher_instance)
846            },
847            #[cfg(all(feature = "ecb", feature = "camellia"))]
848            SymBlockCipherModeEncryptionInstanceState::EcbCamellia128($block_cipher_instance) => {
849                $m!($($($args),*,)? Ecb, Camellia, 128, $block_cipher_instance)
850            },
851            #[cfg(all(feature = "ecb", feature = "camellia"))]
852            SymBlockCipherModeEncryptionInstanceState::EcbCamellia192($block_cipher_instance) => {
853                $m!($($($args),*,)? Ecb, Camellia, 192, $block_cipher_instance)
854            },
855            #[cfg(all(feature = "ecb", feature = "camellia"))]
856            SymBlockCipherModeEncryptionInstanceState::EcbCamellia256($block_cipher_instance) => {
857                $m!($($($args),*,)? Ecb, Camellia, 256, $block_cipher_instance)
858            },
859            #[cfg(all(feature = "ecb", feature = "sm4"))]
860            SymBlockCipherModeEncryptionInstanceState::EcbSm4_128($block_cipher_instance) => {
861                $m!($($($args),*,)? Ecb, Sm4, 128, $block_cipher_instance)
862            },
863        }
864    };
865}
866
867/// Map a triplet of (symbolic mode, symbolic block cipher, key size) to a
868/// variant of SymBlockCipherModeEncryptionInstanceState.
869macro_rules! mode_and_block_cipher_to_block_cipher_mode_encryption_instance_variant {
870    (Ctr, Aes, 128) => {
871        SymBlockCipherModeEncryptionInstanceState::CtrAes128
872    };
873    (Ctr, Aes, 192) => {
874        SymBlockCipherModeEncryptionInstanceState::CtrAes192
875    };
876    (Ctr, Aes, 256) => {
877        SymBlockCipherModeEncryptionInstanceState::CtrAes256
878    };
879    (Ctr, Camellia, 128) => {
880        SymBlockCipherModeEncryptionInstanceState::CtrCamellia128
881    };
882    (Ctr, Camellia, 192) => {
883        SymBlockCipherModeEncryptionInstanceState::CtrCamellia192
884    };
885    (Ctr, Camellia, 256) => {
886        SymBlockCipherModeEncryptionInstanceState::CtrCamellia256
887    };
888    (Ctr, Sm4, 128) => {
889        SymBlockCipherModeEncryptionInstanceState::CtrSm4_128
890    };
891
892    (Ofb, Aes, 128) => {
893        SymBlockCipherModeEncryptionInstanceState::OfbAes128
894    };
895    (Ofb, Aes, 192) => {
896        SymBlockCipherModeEncryptionInstanceState::OfbAes192
897    };
898    (Ofb, Aes, 256) => {
899        SymBlockCipherModeEncryptionInstanceState::OfbAes256
900    };
901    (Ofb, Camellia, 128) => {
902        SymBlockCipherModeEncryptionInstanceState::OfbCamellia128
903    };
904    (Ofb, Camellia, 192) => {
905        SymBlockCipherModeEncryptionInstanceState::OfbCamellia192
906    };
907    (Ofb, Camellia, 256) => {
908        SymBlockCipherModeEncryptionInstanceState::OfbCamellia256
909    };
910    (Ofb, Sm4, 128) => {
911        SymBlockCipherModeEncryptionInstanceState::OfbSm4_128
912    };
913
914    (Cbc, Aes, 128) => {
915        SymBlockCipherModeEncryptionInstanceState::CbcAes128
916    };
917    (Cbc, Aes, 192) => {
918        SymBlockCipherModeEncryptionInstanceState::CbcAes192
919    };
920    (Cbc, Aes, 256) => {
921        SymBlockCipherModeEncryptionInstanceState::CbcAes256
922    };
923    (Cbc, Camellia, 128) => {
924        SymBlockCipherModeEncryptionInstanceState::CbcCamellia128
925    };
926    (Cbc, Camellia, 192) => {
927        SymBlockCipherModeEncryptionInstanceState::CbcCamellia192
928    };
929    (Cbc, Camellia, 256) => {
930        SymBlockCipherModeEncryptionInstanceState::CbcCamellia256
931    };
932    (Cbc, Sm4, 128) => {
933        SymBlockCipherModeEncryptionInstanceState::CbcSm4_128
934    };
935
936    (Cfb, Aes, 128) => {
937        SymBlockCipherModeEncryptionInstanceState::CfbAes128
938    };
939    (Cfb, Aes, 192) => {
940        SymBlockCipherModeEncryptionInstanceState::CfbAes192
941    };
942    (Cfb, Aes, 256) => {
943        SymBlockCipherModeEncryptionInstanceState::CfbAes256
944    };
945    (Cfb, Camellia, 128) => {
946        SymBlockCipherModeEncryptionInstanceState::CfbCamellia128
947    };
948    (Cfb, Camellia, 192) => {
949        SymBlockCipherModeEncryptionInstanceState::CfbCamellia192
950    };
951    (Cfb, Camellia, 256) => {
952        SymBlockCipherModeEncryptionInstanceState::CfbCamellia256
953    };
954    (Cfb, Sm4, 128) => {
955        SymBlockCipherModeEncryptionInstanceState::CfbSm4_128
956    };
957
958    (Ecb, Aes, 128) => {
959        SymBlockCipherModeEncryptionInstanceState::EcbAes128
960    };
961    (Ecb, Aes, 192) => {
962        SymBlockCipherModeEncryptionInstanceState::EcbAes192
963    };
964    (Ecb, Aes, 256) => {
965        SymBlockCipherModeEncryptionInstanceState::EcbAes256
966    };
967    (Ecb, Camellia, 128) => {
968        SymBlockCipherModeEncryptionInstanceState::EcbCamellia128
969    };
970    (Ecb, Camellia, 192) => {
971        SymBlockCipherModeEncryptionInstanceState::EcbCamellia192
972    };
973    (Ecb, Camellia, 256) => {
974        SymBlockCipherModeEncryptionInstanceState::EcbCamellia256
975    };
976    (Ecb, Sm4, 128) => {
977        SymBlockCipherModeEncryptionInstanceState::EcbSm4_128
978    };
979}
980
981macro_rules! mode_to_enc_impl {
982    (Ctr, $block_cipher_impl:ty) => {
983        ctr_impl::Encryptor::<&$block_cipher_impl>
984    };
985    (Ofb, $block_cipher_impl:ty) => {
986        ofb::OfbCore::<&$block_cipher_impl>
987    };
988    (Cbc, $block_cipher_impl:ty) => {
989        cbc::Encryptor::<&$block_cipher_impl>
990    };
991    (Cfb, $block_cipher_impl:ty) => {
992        cfb_mode::Encryptor::<&$block_cipher_impl>
993    };
994    (Ecb, $block_cipher_impl:ty) => {
995        ecb::Encryptor::<&$block_cipher_impl>
996    };
997}
998
999// Instantiate a block cipher mode implementation wrapping a block cipher
1000// instance. Used from SymBlockCipherModeEncryptionInstanceState::encrypt() and
1001// SymBlockCipherModeEncryptionInstanceState::encrypt_in_place().
1002macro_rules! gen_mode_encryptor_impl_new_instance_snippet {
1003    (Ecb,
1004     $block_alg_id:ident,
1005     $key_size:tt,
1006     $block_cipher_instance:ident,
1007     $iv:ident,
1008     $iv_out_opt:ident,
1009    ) => {{
1010        if $iv.len() != 0 {
1011            return Err(CryptoError::InvalidIV);
1012        } else if !$iv_out_opt.as_ref().map(|iv_out| iv_out.is_empty()).unwrap_or(true) {
1013            return Err(CryptoError::Internal);
1014        }
1015
1016        // Note that the block cipher instance is a reference, which implements
1017        // crypto_common's BlockEncrypt, hence BlockEncryptMut. This reduces the
1018        // mode instance's size on the stack significantly. Also, all (possibly
1019        // external) block cipher mode implementations impl ZeroizeOnDrop.
1020        <mode_to_enc_impl!(
1021            Ecb,
1022            enc_mode_and_block_cipher_to_block_cipher_impl!(Ecb, $block_alg_id, $key_size)
1023        )>::inner_init($block_cipher_instance)
1024    }};
1025    ($mode_id:ident,
1026     $block_alg_id:ident,
1027     $key_size:tt,
1028     $block_cipher_instance:ident,
1029     $iv:ident,
1030     $iv_out_opt:ident,
1031    ) => {{
1032        let expected_iv_len = mode_and_block_cipher_to_iv_len!($mode_id, $block_alg_id, $key_size);
1033        if $iv.len() != expected_iv_len {
1034            return Err(CryptoError::InvalidIV);
1035        } else if $iv_out_opt
1036            .as_ref()
1037            .map(|iv_out| iv_out.len() != expected_iv_len)
1038            .unwrap_or(false)
1039        {
1040            return Err(CryptoError::Internal);
1041        }
1042
1043        let iv = crypto_common::Iv::<
1044            mode_to_enc_impl!(
1045                $mode_id,
1046                enc_mode_and_block_cipher_to_block_cipher_impl!($mode_id, $block_alg_id, $key_size)
1047            ),
1048        >::from_slice($iv);
1049
1050        // Note that the block cipher instance is a reference, which implements
1051        // crypto_common's BlockEncrypt, hence BlockEncryptMut. This reduces the
1052        // mode instance's size on the stack significantly. Also, all (possibly
1053        // external) block cipher mode implementations impl ZeroizeOnDrop.
1054        <mode_to_enc_impl!(
1055            $mode_id,
1056            enc_mode_and_block_cipher_to_block_cipher_impl!($mode_id, $block_alg_id, $key_size)
1057        )>::inner_iv_init($block_cipher_instance, iv)
1058    }};
1059}
1060
1061// Generate code snippet for obtaining the IV from for (external) mode
1062// implementations.
1063//
1064// Common to SymBlockCipherModeEncryptionInstanceState::encrypt()/
1065// ::encrypt_in_place() and
1066// SymBlockCipherModeDecryptionInstanceState::decrypt()/ ::decrypt_in_place().
1067macro_rules! gen_mode_transform_grab_iv_snippet {
1068    (Ecb, $_block_alg_id:ident, $_key_size:tt, $_mode_transform_impl_instance:ident, $iv_out_opt:ident) => {{
1069        debug_assert!($iv_out_opt.map(|iv_out| iv_out.is_empty()).unwrap_or(true));
1070    }};
1071    ($_mode_id:ident, $_block_alg_id:ident, $_key_size:tt, $mode_transform_impl_instance:ident, $iv_out_opt:ident) => {{
1072        if let Some(iv_out) = $iv_out_opt {
1073            iv_out.copy_from_slice($mode_transform_impl_instance.iv_state().deref());
1074        }
1075    }};
1076}
1077
1078impl SymBlockCipherModeEncryptionInstanceState {
1079    fn new(
1080        mode: tpm2_interface::TpmiAlgCipherMode,
1081        alg: &SymBlockCipherAlg,
1082        key: &[u8],
1083    ) -> Result<Box<Self>, CryptoError> {
1084        macro_rules! gen_instantiate {
1085            ($mode_id:ident, $block_alg_id:ident, $key_size:tt) => {{
1086                // Don't use crypto_common's convenience KeyInit::from_slice() for instantiating
1087                // the cipher, but wrap the key explictly first to have all possible
1088                // error paths out of the way, thereby enabling a zero copy construction
1089                // right into the Box' memory.
1090                let expected_key_len = <enc_mode_and_block_cipher_to_block_cipher_impl!(
1091                    $mode_id,
1092                    $block_alg_id,
1093                    $key_size
1094                ) as crypto_common::KeySizeUser>::KeySize::to_usize();
1095                debug_assert_eq!(8 * expected_key_len, $key_size);
1096                if key.len() != expected_key_len {
1097                    return Err(CryptoError::KeySize);
1098                }
1099
1100                let key = crypto_common::Key::<
1101                    enc_mode_and_block_cipher_to_block_cipher_impl!($mode_id, $block_alg_id, $key_size),
1102                >::from_slice(key);
1103
1104                box_try_new_with(|| -> Result<Self, convert::Infallible> {
1105                    Ok(
1106                        mode_and_block_cipher_to_block_cipher_mode_encryption_instance_variant!(
1107                            $mode_id,
1108                            $block_alg_id,
1109                            $key_size
1110                        )(<enc_mode_and_block_cipher_to_block_cipher_impl!(
1111                            $mode_id,
1112                            $block_alg_id,
1113                            $key_size
1114                        )>::new(key)),
1115                    )
1116                })?
1117            }};
1118        }
1119
1120        Ok(gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg!(
1121            mode,
1122            alg,
1123            gen_instantiate
1124        ))
1125    }
1126
1127    fn block_cipher_block_len(&self) -> usize {
1128        macro_rules! gen_block_cipher_block_len {
1129            ($_mode_id:ident, $block_cipher_alg_id:ident, $key_size:tt, $_block_cipher_instance:ident) => {
1130                block_cipher_to_block_len!($block_cipher_alg_id, $key_size)
1131            };
1132        }
1133        gen_match_on_block_cipher_mode_encryption_instance!(self, gen_block_cipher_block_len, _block_cipher_instance)
1134    }
1135
1136    fn iv_len(&self) -> usize {
1137        macro_rules! gen_iv_len_for_mode_and_block_cipher {
1138            ($mode_id:ident,
1139              $block_alg_id:ident,
1140              $key_size:tt,
1141              $_block_cipher_instance:ident) => {
1142                mode_and_block_cipher_to_iv_len!($mode_id, $block_alg_id, $key_size)
1143            };
1144        }
1145        gen_match_on_block_cipher_mode_encryption_instance!(
1146            self,
1147            gen_iv_len_for_mode_and_block_cipher,
1148            _block_cipher_instance
1149        )
1150    }
1151
1152    #[inline(never)]
1153    fn encrypt<'a, 'b>(
1154        &self,
1155        iv: &[u8],
1156        dst: &mut dyn CryptoWalkableIoSlicesMutIter<'a>,
1157        src: &mut dyn CryptoWalkableIoSlicesIter<'b>,
1158        iv_out: Option<&mut [u8]>,
1159    ) -> Result<(), CryptoError> {
1160        // Generate code snippet for the block transform callback passed to
1161        // transform_next_blocks() for (external) mode encryption
1162        // implementations implementing the cipher::BlockEncryptMut trait.
1163        macro_rules! gen_block_encrypt_trait_mode_block_encrypt_transform_cb_snippet {
1164            ($mode_transform_impl_instance:ident) => {
1165                |dst_blocks: &mut [u8], src_blocks: Option<&[u8]>| {
1166                    if let Some(src_blocks) = src_blocks {
1167                        $mode_transform_impl_instance.encrypt_block_b2b_mut(src_blocks.into(), dst_blocks.into());
1168                    } else {
1169                        $mode_transform_impl_instance.encrypt_block_mut(dst_blocks.into());
1170                    }
1171                }
1172            };
1173        }
1174
1175        gen_match_on_block_cipher_mode_encryption_instance!(
1176            self,
1177            sym_block_cipher_mode_instance_gen_transform,
1178            block_cipher_instance,
1179            gen_mode_encryptor_impl_new_instance_snippet,
1180            gen_block_encrypt_trait_mode_block_encrypt_transform_cb_snippet,
1181            gen_mode_transform_grab_iv_snippet,
1182            dst,
1183            src,
1184            iv,
1185            iv_out
1186        );
1187
1188        Ok(())
1189    }
1190
1191    #[inline(never)]
1192    fn encrypt_in_place<'a, DI: CryptoPeekableIoSlicesMutIter<'a>>(
1193        &self,
1194        iv: &[u8],
1195        mut dst: DI,
1196        iv_out: Option<&mut [u8]>,
1197    ) -> Result<(), CryptoError> {
1198        // Generate code snippet for the block transform callback passed to
1199        // transform_next_blocks() for (external) mode encryption
1200        // implementations implementing the cipher::BlockEncryptMut trait.
1201        macro_rules! gen_block_encrypt_trait_mode_block_encrypt_transform_cb_snippet {
1202            ($mode_transform_impl_instance:ident) => {
1203                |dst_blocks: &mut [u8]| {
1204                    $mode_transform_impl_instance.encrypt_block_mut(dst_blocks.into());
1205                }
1206            };
1207        }
1208
1209        gen_match_on_block_cipher_mode_encryption_instance!(
1210            self,
1211            sym_block_cipher_mode_instance_gen_transform_in_place,
1212            block_cipher_instance,
1213            gen_mode_encryptor_impl_new_instance_snippet,
1214            gen_block_encrypt_trait_mode_block_encrypt_transform_cb_snippet,
1215            gen_mode_transform_grab_iv_snippet,
1216            dst,
1217            iv,
1218            iv_out
1219        );
1220
1221        Ok(())
1222    }
1223}
1224
1225impl convert::From<&SymBlockCipherModeEncryptionInstance> for SymBlockCipherAlg {
1226    fn from(value: &SymBlockCipherModeEncryptionInstance) -> Self {
1227        macro_rules! gen_block_cipher_to_block_cipher_alg {
1228            ($_mode_id:ident,
1229             $block_alg_id:ident,
1230             $key_size:tt,
1231             $_block_cipher_instance:ident) => {
1232                block_cipher_to_sym_block_cipher_alg_variant!($block_alg_id, $key_size)
1233            };
1234        }
1235        gen_match_on_block_cipher_mode_encryption_instance!(
1236            &*value.state,
1237            gen_block_cipher_to_block_cipher_alg,
1238            _block_cipher_instance
1239        )
1240    }
1241}
1242
1243impl convert::From<&SymBlockCipherModeEncryptionInstance> for tpm2_interface::TpmiAlgCipherMode {
1244    fn from(value: &SymBlockCipherModeEncryptionInstance) -> Self {
1245        macro_rules! gen_block_cipher_to_tpmi_alg_cipher_mode {
1246            ($mode_id:ident,
1247             $_block_alg_id:ident,
1248             $_key_size:tt,
1249             $_block_cipher_instance:ident) => {
1250                mode_to_tpmi_alg_cipher_mode!($mode_id)
1251            };
1252        }
1253        gen_match_on_block_cipher_mode_encryption_instance!(
1254            &*value.state,
1255            gen_block_cipher_to_tpmi_alg_cipher_mode,
1256            _block_cipher_instance
1257        )
1258    }
1259}
1260
1261pub struct SymBlockCipherModeDecryptionInstance {
1262    state: Box<SymBlockCipherModeDecryptionInstanceState>,
1263}
1264
1265impl SymBlockCipherModeDecryptionInstance {
1266    /// Instantiate a `SymBlockCipherModeDecryptionInstance` from a triplet of
1267    /// [block cipher mode identifier](tpm2_interface::TpmiAlgCipherMode),
1268    /// [symmetric block cipher algorithm identifier](SymBlockCipherAlg) and
1269    /// a raw key byte slice.
1270    ///
1271    /// # Arguments:
1272    ///
1273    /// * `mode_id`  - The [block cipher
1274    ///   mode](tpm2_interface::TpmiAlgCipherMode) to use.
1275    /// * `alg_id` - The [symmetric block cipher algorithm](SymBlockCipherAlg)
1276    ///   to be used for this instance.
1277    /// * `key` - The raw key bytes. It's length must match the [expected key
1278    ///   length](SymBlockCipherAlg::key_len) for `alg` or an error will get
1279    ///   returned.
1280    #[inline(never)]
1281    pub fn new(
1282        mode_id: tpm2_interface::TpmiAlgCipherMode,
1283        alg_id: &SymBlockCipherAlg,
1284        key: &[u8],
1285    ) -> Result<Self, CryptoError> {
1286        Ok(Self {
1287            state: SymBlockCipherModeDecryptionInstanceState::new(mode_id, alg_id, key)?,
1288        })
1289    }
1290
1291    /// Try to clone a `SymBlockCipherDecryptionInstance`.
1292    #[inline(never)]
1293    pub fn try_clone(&self) -> Result<Self, CryptoError> {
1294        Ok(Self {
1295            state: box_try_new_with(
1296                || -> Result<SymBlockCipherModeDecryptionInstanceState, convert::Infallible> {
1297                    Ok(self.state.deref().clone())
1298                },
1299            )?,
1300        })
1301    }
1302
1303    /// Obtain the instance's associated block cipher algorithm's block length.
1304    ///
1305    /// Equivalent to
1306    /// [`SymBlockCipherAlg::block_len()`](SymBlockCipherAlg::block_len).
1307    pub fn block_cipher_block_len(&self) -> usize {
1308        self.state.block_cipher_block_len()
1309    }
1310
1311    /// Determine the IV length for use with
1312    /// `SymBlockCipherModeDecryptionInstance`.
1313    ///
1314    /// Equivalent to
1315    /// [`SymBlockCipherAlg::iv_len_for_mode()`](SymBlockCipherAlg::iv_len_for_mode).
1316    pub fn iv_len(&self) -> usize {
1317        self.state.iv_len()
1318    }
1319
1320    /// Decrypt data from buffer to buffer.
1321    ///
1322    /// The source and destination buffers must be equal in length or an error
1323    /// will get returned. Depending on the block cipher mode, their lengths
1324    /// must perhaps be aligned to the [block cipher block
1325    /// length](Self::block_cipher_block_len), an error will get returned
1326    /// otherwise. No padding format verification will be done.
1327    ///
1328    /// Processing a request does not alter `self`'s state -- in particular the
1329    /// IV must get provided for each new requst anew.
1330    ///
1331    /// # Arguments:
1332    ///
1333    /// * `iv` - The IV to use. Its length must match the expected [IV
1334    ///   length](Self::iv_len).
1335    /// * `dst` - The destination buffers to write the decrypted message to.
1336    /// * `src` - The source buffers holding the encrypted message.
1337    /// * `iv_out` - Optional buffer receiving the final IV as ouput from the
1338    ///   block cipher mode. Attempting to retrieve the final IV when the to be
1339    ///   encrypted data's length is not an integral multiple of the [block
1340    ///   cipher block size ](Self::block_cipher_block_len) is ill-defined and
1341    ///   considered an error.
1342    pub fn decrypt<'a, 'b, DI: CryptoWalkableIoSlicesMutIter<'a>, SI: CryptoWalkableIoSlicesIter<'b>>(
1343        &self,
1344        iv: &[u8],
1345        mut dst: DI,
1346        mut src: SI,
1347        iv_out: Option<&mut [u8]>,
1348    ) -> Result<(), CryptoError> {
1349        self.state.decrypt(iv, &mut dst, &mut src, iv_out)
1350    }
1351
1352    /// Decrypt data in place.
1353    ///
1354    /// Depending on the block cipher mode, the source/destination buffer's
1355    /// length must perhaps be aligned to the [block cipher block
1356    /// length](Self::block_cipher_block_len), an error will get
1357    /// returned otherwise. . No padding format verification will be done.
1358    ///
1359    /// Processing a request does not alter `self`'s state -- in particular the
1360    /// IV must get provided for each new requst anew.
1361    ///
1362    /// <div class="warning">
1363    ///
1364    /// Unlike it's the case with [`decrypt()`](Self::decrypt), the
1365    /// source/destination buffer's generic `DI` type is not `dyn`
1366    /// compatible. The compiler will emit a separate instance for each
1367    /// individual `DI` `decrypt_in_place()` gets invoked with. Be vigilant
1368    /// of template bloat, prefer [`decrypt()`](Self::decrypt) if feasible and
1369    /// try to not use too exotic types for `DI` here otherwise.
1370    ///
1371    /// </div>
1372    ///
1373    /// # Arguments:
1374    ///
1375    /// * `iv` - The IV to use. Its length must match the expected [IV
1376    ///   length](Self::iv_len).
1377    /// * `dst` - The source/destination buffers initially holding the encryted
1378    ///   message and receiving the decrypted cleartext result.
1379    /// * `iv_out` - Optional buffer receiving the final IV as ouput from the
1380    ///   block cipher mode. Attempting to retrieve the final IV when the to be
1381    ///   encrypted data's length is not an integral multiple of the [block
1382    ///   cipher block size ](Self::block_cipher_block_len) is ill-defined and
1383    ///   considered an error.
1384    pub fn decrypt_in_place<'a, 'b, DI: CryptoPeekableIoSlicesMutIter<'a>>(
1385        &self,
1386        iv: &[u8],
1387        dst: DI,
1388        iv_out: Option<&mut [u8]>,
1389    ) -> Result<(), CryptoError> {
1390        self.state.decrypt_in_place(iv, dst, iv_out)
1391    }
1392}
1393
1394// All supported block cipher implementations possibly wrapped implement
1395// ZeroizeOnDrop.
1396#[cfg(feature = "zeroize")]
1397impl zeroize::ZeroizeOnDrop for SymBlockCipherModeDecryptionInstance {}
1398
1399/// Map a triplet of (symbolic mode, symbolic block cipher, key length) to a
1400/// block cipher implementation suitable for decryption with that mode.
1401macro_rules! dec_mode_and_block_cipher_to_block_cipher_impl {
1402    (Ctr, Aes, 128) => {
1403        aes::Aes128Enc
1404    };
1405    (Ctr, Aes, 192) => {
1406        aes::Aes192Enc
1407    };
1408    (Ctr, Aes, 256) => {
1409        aes::Aes256Enc
1410    };
1411    (Ctr, Camellia, 128) => {
1412        // No differentiation between encryptor/decryptor made in camellia crate.
1413        camellia::Camellia128
1414    };
1415    (Ctr, Camellia, 192) => {
1416        // No differentiation between encryptor/decryptor made in camellia crate.
1417        camellia::Camellia192
1418    };
1419    (Ctr, Camellia, 256) => {
1420        // No differentiation between encryptor/decryptor made in camellia crate.
1421        camellia::Camellia256
1422    };
1423    (Ctr, Sm4, 128) => {
1424        // No differentiation between encryptor/decryptor made in sm4 crate.
1425        sm4::Sm4
1426    };
1427
1428    (Ofb, Aes, 128) => {
1429        aes::Aes128Enc
1430    };
1431    (Ofb, Aes, 192) => {
1432        aes::Aes192Enc
1433    };
1434    (Ofb, Aes, 256) => {
1435        aes::Aes256Enc
1436    };
1437    (Ofb, Camellia, 128) => {
1438        // No differentiation between encryptor/decryptor made in camellia crate.
1439        camellia::Camellia128
1440    };
1441    (Ofb, Camellia, 192) => {
1442        // No differentiation between encryptor/decryptor made in camellia crate.
1443        camellia::Camellia192
1444    };
1445    (Ofb, Camellia, 256) => {
1446        // No differentiation between encryptor/decryptor made in camellia crate.
1447        camellia::Camellia256
1448    };
1449    (Ofb, Sm4, 128) => {
1450        // No differentiation between encryptor/decryptor made in sm4 crate.
1451        sm4::Sm4
1452    };
1453
1454    (Cbc, Aes, 128) => {
1455        aes::Aes128Dec
1456    };
1457    (Cbc, Aes, 192) => {
1458        aes::Aes192Dec
1459    };
1460    (Cbc, Aes, 256) => {
1461        aes::Aes256Dec
1462    };
1463    (Cbc, Camellia, 128) => {
1464        // No differentiation between encryptor/decryptor made in camellia crate.
1465        camellia::Camellia128
1466    };
1467    (Cbc, Camellia, 192) => {
1468        // No differentiation between encryptor/decryptor made in camellia crate.
1469        camellia::Camellia192
1470    };
1471    (Cbc, Camellia, 256) => {
1472        // No differentiation between encryptor/decryptor made in camellia crate.
1473        camellia::Camellia256
1474    };
1475    (Cbc, Sm4, 128) => {
1476        // No differentiation between encryptor/decryptor made in sm4 crate.
1477        sm4::Sm4
1478    };
1479
1480    (Cfb, Aes, 128) => {
1481        // cfb_mode needs a Decryptor to impl IvState.
1482        aes::Aes128
1483    };
1484    (Cfb, Aes, 192) => {
1485        // cfb_mode needs a Decryptor to impl IvState.
1486        aes::Aes192
1487    };
1488    (Cfb, Aes, 256) => {
1489        // cfb_mode needs a Decryptor to impl IvState.
1490        aes::Aes256
1491    };
1492    (Cfb, Camellia, 128) => {
1493        // No differentiation between encryptor/decryptor made in camellia crate.
1494        camellia::Camellia128
1495    };
1496    (Cfb, Camellia, 192) => {
1497        // No differentiation between encryptor/decryptor made in camellia crate.
1498        camellia::Camellia192
1499    };
1500    (Cfb, Camellia, 256) => {
1501        // No differentiation between encryptor/decryptor made in camellia crate.
1502        camellia::Camellia256
1503    };
1504    (Cfb, Sm4, 128) => {
1505        // No differentiation between encryptor/decryptor made in sm4 crate.
1506        sm4::Sm4
1507    };
1508
1509    (Ecb, Aes, 128) => {
1510        aes::Aes128Dec
1511    };
1512    (Ecb, Aes, 192) => {
1513        aes::Aes192Dec
1514    };
1515    (Ecb, Aes, 256) => {
1516        aes::Aes256Dec
1517    };
1518    (Ecb, Camellia, 128) => {
1519        // No differentiation between encryptor/decryptor made in camellia crate.
1520        camellia::Camellia128
1521    };
1522    (Ecb, Camellia, 192) => {
1523        // No differentiation between encryptor/decryptor made in camellia crate.
1524        camellia::Camellia192
1525    };
1526    (Ecb, Camellia, 256) => {
1527        // No differentiation between encryptor/decryptor made in camellia crate.
1528        camellia::Camellia256
1529    };
1530    (Ecb, Sm4, 128) => {
1531        // No differentiation between encryptor/decryptor made in sm4 crate.
1532        sm4::Sm4
1533    };
1534}
1535
1536#[derive(Clone)]
1537enum SymBlockCipherModeDecryptionInstanceState {
1538    #[cfg(all(feature = "ctr", feature = "aes"))]
1539    CtrAes128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Aes, 128)),
1540    #[cfg(all(feature = "ctr", feature = "aes"))]
1541    CtrAes192(dec_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Aes, 192)),
1542    #[cfg(all(feature = "ctr", feature = "aes"))]
1543    CtrAes256(dec_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Aes, 256)),
1544    #[cfg(all(feature = "ctr", feature = "camellia"))]
1545    CtrCamellia128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Camellia, 128)),
1546    #[cfg(all(feature = "ctr", feature = "camellia"))]
1547    CtrCamellia192(dec_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Camellia, 192)),
1548    #[cfg(all(feature = "ctr", feature = "camellia"))]
1549    CtrCamellia256(dec_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Camellia, 256)),
1550    #[cfg(all(feature = "ctr", feature = "sm4"))]
1551    CtrSm4_128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ctr, Sm4, 128)),
1552
1553    #[cfg(all(feature = "ofb", feature = "aes"))]
1554    OfbAes128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Aes, 128)),
1555    #[cfg(all(feature = "ofb", feature = "aes"))]
1556    OfbAes192(dec_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Aes, 192)),
1557    #[cfg(all(feature = "ofb", feature = "aes"))]
1558    OfbAes256(dec_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Aes, 256)),
1559    #[cfg(all(feature = "ofb", feature = "camellia"))]
1560    OfbCamellia128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Camellia, 128)),
1561    #[cfg(all(feature = "ofb", feature = "camellia"))]
1562    OfbCamellia192(dec_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Camellia, 192)),
1563    #[cfg(all(feature = "ofb", feature = "camellia"))]
1564    OfbCamellia256(dec_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Camellia, 256)),
1565    #[cfg(all(feature = "ofb", feature = "sm4"))]
1566    OfbSm4_128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ofb, Sm4, 128)),
1567
1568    #[cfg(all(feature = "cbc", feature = "aes"))]
1569    CbcAes128(dec_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Aes, 128)),
1570    #[cfg(all(feature = "cbc", feature = "aes"))]
1571    CbcAes192(dec_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Aes, 192)),
1572    #[cfg(all(feature = "cbc", feature = "aes"))]
1573    CbcAes256(dec_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Aes, 256)),
1574    #[cfg(all(feature = "cbc", feature = "camellia"))]
1575    CbcCamellia128(dec_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Camellia, 128)),
1576    #[cfg(all(feature = "cbc", feature = "camellia"))]
1577    CbcCamellia192(dec_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Camellia, 192)),
1578    #[cfg(all(feature = "cbc", feature = "camellia"))]
1579    CbcCamellia256(dec_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Camellia, 256)),
1580    #[cfg(all(feature = "cbc", feature = "sm4"))]
1581    CbcSm4_128(dec_mode_and_block_cipher_to_block_cipher_impl!(Cbc, Sm4, 128)),
1582
1583    #[cfg(all(feature = "cfb", feature = "aes"))]
1584    CfbAes128(dec_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Aes, 128)),
1585    #[cfg(all(feature = "cfb", feature = "aes"))]
1586    CfbAes192(dec_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Aes, 192)),
1587    #[cfg(all(feature = "cfb", feature = "aes"))]
1588    CfbAes256(dec_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Aes, 256)),
1589    #[cfg(all(feature = "cfb", feature = "camellia"))]
1590    CfbCamellia128(dec_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Camellia, 128)),
1591    #[cfg(all(feature = "cfb", feature = "camellia"))]
1592    CfbCamellia192(dec_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Camellia, 192)),
1593    #[cfg(all(feature = "cfb", feature = "camellia"))]
1594    CfbCamellia256(dec_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Camellia, 256)),
1595    #[cfg(all(feature = "cfb", feature = "sm4"))]
1596    CfbSm4_128(dec_mode_and_block_cipher_to_block_cipher_impl!(Cfb, Sm4, 128)),
1597
1598    #[cfg(all(feature = "ecb", feature = "aes"))]
1599    EcbAes128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Aes, 128)),
1600    #[cfg(all(feature = "ecb", feature = "aes"))]
1601    EcbAes192(dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Aes, 192)),
1602    #[cfg(all(feature = "ecb", feature = "aes"))]
1603    EcbAes256(dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Aes, 256)),
1604    #[cfg(all(feature = "ecb", feature = "camellia"))]
1605    EcbCamellia128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Camellia, 128)),
1606    #[cfg(all(feature = "ecb", feature = "camellia"))]
1607    EcbCamellia192(dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Camellia, 192)),
1608    #[cfg(all(feature = "ecb", feature = "camellia"))]
1609    EcbCamellia256(dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Camellia, 256)),
1610    #[cfg(all(feature = "ecb", feature = "sm4"))]
1611    EcbSm4_128(dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, Sm4, 128)),
1612}
1613
1614/// Generate a `match {}` on SymBlockCipherModeDecryptionInstanceState and
1615/// invoke a macro in the body of each match arm.
1616///
1617/// The supplied macro `m` gets invoked with (`$args`, symbolic mode, symbolic
1618/// block cipher, key size, `$block_cipher_instance`) for each arm, where
1619/// identifier `$block_cipher_instance` is bound to the variant's respective
1620/// block cipher implementation instance member.
1621macro_rules! gen_match_on_block_cipher_mode_decryption_instance {
1622    ($block_cipher_mode_instance_value:expr, $m:ident, $block_cipher_instance:ident $(, $($args:tt),*)?) => {
1623        match $block_cipher_mode_instance_value {
1624            #[cfg(all(feature = "ctr", feature = "aes"))]
1625            SymBlockCipherModeDecryptionInstanceState::CtrAes128($block_cipher_instance) => {
1626                $m!($($($args),*,)? Ctr, Aes, 128, $block_cipher_instance)
1627            },
1628            #[cfg(all(feature = "ctr", feature = "aes"))]
1629            SymBlockCipherModeDecryptionInstanceState::CtrAes192($block_cipher_instance) => {
1630                $m!($($($args),*,)? Ctr, Aes, 192, $block_cipher_instance)
1631            },
1632            #[cfg(all(feature = "ctr", feature = "aes"))]
1633            SymBlockCipherModeDecryptionInstanceState::CtrAes256($block_cipher_instance) => {
1634                $m!($($($args),*,)? Ctr, Aes, 256, $block_cipher_instance)
1635            },
1636            #[cfg(all(feature = "ctr", feature = "camellia"))]
1637            SymBlockCipherModeDecryptionInstanceState::CtrCamellia128($block_cipher_instance) => {
1638                $m!($($($args),*,)? Ctr, Camellia, 128, $block_cipher_instance)
1639            },
1640            #[cfg(all(feature = "ctr", feature = "camellia"))]
1641            SymBlockCipherModeDecryptionInstanceState::CtrCamellia192($block_cipher_instance) => {
1642                $m!($($($args),*,)? Ctr, Camellia, 192, $block_cipher_instance)
1643            },
1644            #[cfg(all(feature = "ctr", feature = "camellia"))]
1645            SymBlockCipherModeDecryptionInstanceState::CtrCamellia256($block_cipher_instance) => {
1646                $m!($($($args),*,)? Ctr, Camellia, 256, $block_cipher_instance)
1647            },
1648            #[cfg(all(feature = "ctr", feature = "sm4"))]
1649            SymBlockCipherModeDecryptionInstanceState::CtrSm4_128($block_cipher_instance) => {
1650                $m!($($($args),*,)? Ctr, Sm4, 128, $block_cipher_instance)
1651            },
1652
1653            #[cfg(all(feature = "ofb", feature = "aes"))]
1654            SymBlockCipherModeDecryptionInstanceState::OfbAes128($block_cipher_instance) => {
1655                $m!($($($args),*,)? Ofb, Aes, 128, $block_cipher_instance)
1656            },
1657            #[cfg(all(feature = "ofb", feature = "aes"))]
1658            SymBlockCipherModeDecryptionInstanceState::OfbAes192($block_cipher_instance) => {
1659                $m!($($($args),*,)? Ofb, Aes, 192, $block_cipher_instance)
1660            },
1661            #[cfg(all(feature = "ofb", feature = "aes"))]
1662            SymBlockCipherModeDecryptionInstanceState::OfbAes256($block_cipher_instance) => {
1663                $m!($($($args),*,)? Ofb, Aes, 256, $block_cipher_instance)
1664            },
1665            #[cfg(all(feature = "ofb", feature = "camellia"))]
1666            SymBlockCipherModeDecryptionInstanceState::OfbCamellia128($block_cipher_instance) => {
1667                $m!($($($args),*,)? Ofb, Camellia, 128, $block_cipher_instance)
1668            },
1669            #[cfg(all(feature = "ofb", feature = "camellia"))]
1670            SymBlockCipherModeDecryptionInstanceState::OfbCamellia192($block_cipher_instance) => {
1671                $m!($($($args),*,)? Ofb, Camellia, 192, $block_cipher_instance)
1672            },
1673            #[cfg(all(feature = "ofb", feature = "camellia"))]
1674            SymBlockCipherModeDecryptionInstanceState::OfbCamellia256($block_cipher_instance) => {
1675                $m!($($($args),*,)? Ofb, Camellia, 256, $block_cipher_instance)
1676            },
1677            #[cfg(all(feature = "ofb", feature = "sm4"))]
1678            SymBlockCipherModeDecryptionInstanceState::OfbSm4_128($block_cipher_instance) => {
1679                $m!($($($args),*,)? Ofb, Sm4, 128, $block_cipher_instance)
1680            },
1681
1682            #[cfg(all(feature = "cbc", feature = "aes"))]
1683            SymBlockCipherModeDecryptionInstanceState::CbcAes128($block_cipher_instance) => {
1684                $m!($($($args),*,)? Cbc, Aes, 128, $block_cipher_instance)
1685            },
1686            #[cfg(all(feature = "cbc", feature = "aes"))]
1687            SymBlockCipherModeDecryptionInstanceState::CbcAes192($block_cipher_instance) => {
1688                $m!($($($args),*,)? Cbc, Aes, 192, $block_cipher_instance)
1689            },
1690            #[cfg(all(feature = "cbc", feature = "aes"))]
1691            SymBlockCipherModeDecryptionInstanceState::CbcAes256($block_cipher_instance) => {
1692                $m!($($($args),*,)? Cbc, Aes, 256, $block_cipher_instance)
1693            },
1694            #[cfg(all(feature = "cbc", feature = "camellia"))]
1695            SymBlockCipherModeDecryptionInstanceState::CbcCamellia128($block_cipher_instance) => {
1696                $m!($($($args),*,)? Cbc, Camellia, 128, $block_cipher_instance)
1697            },
1698            #[cfg(all(feature = "cbc", feature = "camellia"))]
1699            SymBlockCipherModeDecryptionInstanceState::CbcCamellia192($block_cipher_instance) => {
1700                $m!($($($args),*,)? Cbc, Camellia, 192, $block_cipher_instance)
1701            },
1702            #[cfg(all(feature = "cbc", feature = "camellia"))]
1703            SymBlockCipherModeDecryptionInstanceState::CbcCamellia256($block_cipher_instance) => {
1704                $m!($($($args),*,)? Cbc, Camellia, 256, $block_cipher_instance)
1705            },
1706            #[cfg(all(feature = "cbc", feature = "sm4"))]
1707            SymBlockCipherModeDecryptionInstanceState::CbcSm4_128($block_cipher_instance) => {
1708                $m!($($($args),*,)? Cbc, Sm4, 128, $block_cipher_instance)
1709            },
1710
1711            #[cfg(all(feature = "cfb", feature = "aes"))]
1712            SymBlockCipherModeDecryptionInstanceState::CfbAes128($block_cipher_instance) => {
1713                $m!($($($args),*,)? Cfb, Aes, 128, $block_cipher_instance)
1714            },
1715            #[cfg(all(feature = "cfb", feature = "aes"))]
1716            SymBlockCipherModeDecryptionInstanceState::CfbAes192($block_cipher_instance) => {
1717                $m!($($($args),*,)? Cfb, Aes, 192, $block_cipher_instance)
1718            },
1719            #[cfg(all(feature = "cfb", feature = "aes"))]
1720            SymBlockCipherModeDecryptionInstanceState::CfbAes256($block_cipher_instance) => {
1721                $m!($($($args),*,)? Cfb, Aes, 256, $block_cipher_instance)
1722            },
1723            #[cfg(all(feature = "cfb", feature = "camellia"))]
1724            SymBlockCipherModeDecryptionInstanceState::CfbCamellia128($block_cipher_instance) => {
1725                $m!($($($args),*,)? Cfb, Camellia, 128, $block_cipher_instance)
1726            },
1727            #[cfg(all(feature = "cfb", feature = "camellia"))]
1728            SymBlockCipherModeDecryptionInstanceState::CfbCamellia192($block_cipher_instance) => {
1729                $m!($($($args),*,)? Cfb, Camellia, 192, $block_cipher_instance)
1730            },
1731            #[cfg(all(feature = "cfb", feature = "camellia"))]
1732            SymBlockCipherModeDecryptionInstanceState::CfbCamellia256($block_cipher_instance) => {
1733                $m!($($($args),*,)? Cfb, Camellia, 256, $block_cipher_instance)
1734            },
1735            #[cfg(all(feature = "cfb", feature = "sm4"))]
1736            SymBlockCipherModeDecryptionInstanceState::CfbSm4_128($block_cipher_instance) => {
1737                $m!($($($args),*,)? Cfb, Sm4, 128, $block_cipher_instance)
1738            },
1739
1740            #[cfg(all(feature = "ecb", feature = "aes"))]
1741            SymBlockCipherModeDecryptionInstanceState::EcbAes128($block_cipher_instance) => {
1742                $m!($($($args),*,)? Ecb, Aes, 128, $block_cipher_instance)
1743            },
1744            #[cfg(all(feature = "ecb", feature = "aes"))]
1745            SymBlockCipherModeDecryptionInstanceState::EcbAes192($block_cipher_instance) => {
1746                $m!($($($args),*,)? Ecb, Aes, 192, $block_cipher_instance)
1747            },
1748            #[cfg(all(feature = "ecb", feature = "aes"))]
1749            SymBlockCipherModeDecryptionInstanceState::EcbAes256($block_cipher_instance) => {
1750                $m!($($($args),*,)? Ecb, Aes, 256, $block_cipher_instance)
1751            },
1752            #[cfg(all(feature = "ecb", feature = "camellia"))]
1753            SymBlockCipherModeDecryptionInstanceState::EcbCamellia128($block_cipher_instance) => {
1754                $m!($($($args),*,)? Ecb, Camellia, 128, $block_cipher_instance)
1755            },
1756            #[cfg(all(feature = "ecb", feature = "camellia"))]
1757            SymBlockCipherModeDecryptionInstanceState::EcbCamellia192($block_cipher_instance) => {
1758                $m!($($($args),*,)? Ecb, Camellia, 192, $block_cipher_instance)
1759            },
1760            #[cfg(all(feature = "ecb", feature = "camellia"))]
1761            SymBlockCipherModeDecryptionInstanceState::EcbCamellia256($block_cipher_instance) => {
1762                $m!($($($args),*,)? Ecb, Camellia, 256, $block_cipher_instance)
1763            },
1764            #[cfg(all(feature = "ecb", feature = "sm4"))]
1765            SymBlockCipherModeDecryptionInstanceState::EcbSm4_128($block_cipher_instance) => {
1766                $m!($($($args),*,)? Ecb, Sm4, 128, $block_cipher_instance)
1767            },
1768        }
1769    };
1770}
1771
1772/// Map a triplet of (symbolic mode, symbolic block cipher, key size) to a
1773/// variant of SymBlockCipherModeDecryptionInstanceState.
1774macro_rules! mode_and_block_cipher_to_block_cipher_mode_decryption_instance_variant {
1775    (Ctr, Aes, 128) => {
1776        SymBlockCipherModeDecryptionInstanceState::CtrAes128
1777    };
1778    (Ctr, Aes, 192) => {
1779        SymBlockCipherModeDecryptionInstanceState::CtrAes192
1780    };
1781    (Ctr, Aes, 256) => {
1782        SymBlockCipherModeDecryptionInstanceState::CtrAes256
1783    };
1784    (Ctr, Camellia, 128) => {
1785        SymBlockCipherModeDecryptionInstanceState::CtrCamellia128
1786    };
1787    (Ctr, Camellia, 192) => {
1788        SymBlockCipherModeDecryptionInstanceState::CtrCamellia192
1789    };
1790    (Ctr, Camellia, 256) => {
1791        SymBlockCipherModeDecryptionInstanceState::CtrCamellia256
1792    };
1793    (Ctr, Sm4, 128) => {
1794        SymBlockCipherModeDecryptionInstanceState::CtrSm4_128
1795    };
1796
1797    (Ofb, Aes, 128) => {
1798        SymBlockCipherModeDecryptionInstanceState::OfbAes128
1799    };
1800    (Ofb, Aes, 192) => {
1801        SymBlockCipherModeDecryptionInstanceState::OfbAes192
1802    };
1803    (Ofb, Aes, 256) => {
1804        SymBlockCipherModeDecryptionInstanceState::OfbAes256
1805    };
1806    (Ofb, Camellia, 128) => {
1807        SymBlockCipherModeDecryptionInstanceState::OfbCamellia128
1808    };
1809    (Ofb, Camellia, 192) => {
1810        SymBlockCipherModeDecryptionInstanceState::OfbCamellia192
1811    };
1812    (Ofb, Camellia, 256) => {
1813        SymBlockCipherModeDecryptionInstanceState::OfbCamellia256
1814    };
1815    (Ofb, Sm4, 128) => {
1816        SymBlockCipherModeDecryptionInstanceState::OfbSm4_128
1817    };
1818
1819    (Cbc, Aes, 128) => {
1820        SymBlockCipherModeDecryptionInstanceState::CbcAes128
1821    };
1822    (Cbc, Aes, 192) => {
1823        SymBlockCipherModeDecryptionInstanceState::CbcAes192
1824    };
1825    (Cbc, Aes, 256) => {
1826        SymBlockCipherModeDecryptionInstanceState::CbcAes256
1827    };
1828    (Cbc, Camellia, 128) => {
1829        SymBlockCipherModeDecryptionInstanceState::CbcCamellia128
1830    };
1831    (Cbc, Camellia, 192) => {
1832        SymBlockCipherModeDecryptionInstanceState::CbcCamellia192
1833    };
1834    (Cbc, Camellia, 256) => {
1835        SymBlockCipherModeDecryptionInstanceState::CbcCamellia256
1836    };
1837    (Cbc, Sm4, 128) => {
1838        SymBlockCipherModeDecryptionInstanceState::CbcSm4_128
1839    };
1840
1841    (Cfb, Aes, 128) => {
1842        SymBlockCipherModeDecryptionInstanceState::CfbAes128
1843    };
1844    (Cfb, Aes, 192) => {
1845        SymBlockCipherModeDecryptionInstanceState::CfbAes192
1846    };
1847    (Cfb, Aes, 256) => {
1848        SymBlockCipherModeDecryptionInstanceState::CfbAes256
1849    };
1850    (Cfb, Camellia, 128) => {
1851        SymBlockCipherModeDecryptionInstanceState::CfbCamellia128
1852    };
1853    (Cfb, Camellia, 192) => {
1854        SymBlockCipherModeDecryptionInstanceState::CfbCamellia192
1855    };
1856    (Cfb, Camellia, 256) => {
1857        SymBlockCipherModeDecryptionInstanceState::CfbCamellia256
1858    };
1859    (Cfb, Sm4, 128) => {
1860        SymBlockCipherModeDecryptionInstanceState::CfbSm4_128
1861    };
1862
1863    (Ecb, Aes, 128) => {
1864        SymBlockCipherModeDecryptionInstanceState::EcbAes128
1865    };
1866    (Ecb, Aes, 192) => {
1867        SymBlockCipherModeDecryptionInstanceState::EcbAes192
1868    };
1869    (Ecb, Aes, 256) => {
1870        SymBlockCipherModeDecryptionInstanceState::EcbAes256
1871    };
1872    (Ecb, Camellia, 128) => {
1873        SymBlockCipherModeDecryptionInstanceState::EcbCamellia128
1874    };
1875    (Ecb, Camellia, 192) => {
1876        SymBlockCipherModeDecryptionInstanceState::EcbCamellia192
1877    };
1878    (Ecb, Camellia, 256) => {
1879        SymBlockCipherModeDecryptionInstanceState::EcbCamellia256
1880    };
1881    (Ecb, Sm4, 128) => {
1882        SymBlockCipherModeDecryptionInstanceState::EcbSm4_128
1883    };
1884}
1885
1886macro_rules! mode_to_dec_impl {
1887    (Ctr, $block_cipher_impl:ty) => {
1888        ctr_impl::Decryptor::<&$block_cipher_impl>
1889    };
1890    (Ofb, $block_cipher_impl:ty) => {
1891        ofb::OfbCore::<&$block_cipher_impl>
1892    };
1893    (Cbc, $block_cipher_impl:ty) => {
1894        cbc::Decryptor::<&$block_cipher_impl>
1895    };
1896    (Cfb, $block_cipher_impl:ty) => {
1897        cfb_mode::Decryptor::<&$block_cipher_impl>
1898    };
1899    (Ecb, $block_cipher_impl:ty) => {
1900        ecb::Decryptor::<&$block_cipher_impl>
1901    };
1902}
1903
1904// Instantiate a block cipher mode implementation wrapping a block cipher
1905// instance. Used from SymBlockCipherDecryptionInstanceState::decrypt() and
1906// SymBlockCipherDecryptionInstanceState::decrypt_in_place().
1907macro_rules! gen_mode_decryptor_impl_new_instance_snippet {
1908    (Ecb,
1909     $block_alg_id:ident,
1910     $key_size:tt,
1911     $block_cipher_instance:ident,
1912     $iv:ident,
1913     $iv_out_opt:ident,
1914    ) => {{
1915        if $iv.len() != 0 {
1916            return Err(CryptoError::InvalidIV);
1917        } else if !$iv_out_opt.as_ref().map(|iv_out| iv_out.is_empty()).unwrap_or(true) {
1918            return Err(CryptoError::Internal);
1919        }
1920
1921        // Note that the block cipher instance is a reference, which implements
1922        // crypto_common's BlockDecrypt, hence BlockDecryptMut. This reduces the
1923        // mode instance's size on the stack significantly. Also, all (possibly
1924        // external) block cipher mode implementations impl ZeroizeOnDrop.
1925        <mode_to_dec_impl!(
1926            Ecb,
1927            dec_mode_and_block_cipher_to_block_cipher_impl!(Ecb, $block_alg_id, $key_size)
1928        )>::inner_init($block_cipher_instance)
1929    }};
1930    ($mode_id:ident,
1931     $block_alg_id:ident,
1932     $key_size:tt,
1933     $block_cipher_instance:ident,
1934     $iv:ident,
1935     $iv_out_opt:ident,
1936    ) => {{
1937        let expected_iv_len = mode_and_block_cipher_to_iv_len!($mode_id, $block_alg_id, $key_size);
1938        if $iv.len() != expected_iv_len {
1939            return Err(CryptoError::InvalidIV);
1940        } else if $iv_out_opt
1941            .as_ref()
1942            .map(|iv_out| iv_out.len() != expected_iv_len)
1943            .unwrap_or(false)
1944        {
1945            return Err(CryptoError::Internal);
1946        }
1947
1948        let iv = crypto_common::Iv::<
1949            mode_to_dec_impl!(
1950                $mode_id,
1951                dec_mode_and_block_cipher_to_block_cipher_impl!($mode_id, $block_alg_id, $key_size)
1952            ),
1953        >::from_slice($iv);
1954
1955        // Note that the block cipher instance is a reference, which implements
1956        // crypto_common's BlockDecrypt, hence BlockDecryptMut. This reduces the
1957        // mode instance's size on the stack significantly. Also, all (possibly
1958        // external) block cipher mode implementations impl ZeroizeOnDrop.
1959        <mode_to_dec_impl!(
1960            $mode_id,
1961            dec_mode_and_block_cipher_to_block_cipher_impl!($mode_id, $block_alg_id, $key_size)
1962        )>::inner_iv_init($block_cipher_instance, iv)
1963    }};
1964}
1965
1966impl SymBlockCipherModeDecryptionInstanceState {
1967    fn new(
1968        mode: tpm2_interface::TpmiAlgCipherMode,
1969        alg: &SymBlockCipherAlg,
1970        key: &[u8],
1971    ) -> Result<Box<Self>, CryptoError> {
1972        macro_rules! gen_instantiate {
1973            ($mode_id:ident, $block_alg_id:ident, $key_size:tt) => {{
1974                // Don't use crypto_common's convenience KeyInit::from_slice() for instantiating
1975                // the cipher, but wrap the key explictly first to have all possible
1976                // error paths out of the way, thereby enabling a zero copy construction
1977                // right into the Box' memory.
1978                let expected_key_len = <dec_mode_and_block_cipher_to_block_cipher_impl!(
1979                    $mode_id,
1980                    $block_alg_id,
1981                    $key_size
1982                ) as crypto_common::KeySizeUser>::KeySize::to_usize();
1983                debug_assert_eq!(8 * expected_key_len, $key_size);
1984                if key.len() != expected_key_len {
1985                    return Err(CryptoError::KeySize);
1986                }
1987
1988                let key = crypto_common::Key::<
1989                    dec_mode_and_block_cipher_to_block_cipher_impl!($mode_id, $block_alg_id, $key_size),
1990                >::from_slice(key);
1991
1992                box_try_new_with(|| -> Result<Self, convert::Infallible> {
1993                    Ok(
1994                        mode_and_block_cipher_to_block_cipher_mode_decryption_instance_variant!(
1995                            $mode_id,
1996                            $block_alg_id,
1997                            $key_size
1998                        )(<dec_mode_and_block_cipher_to_block_cipher_impl!(
1999                            $mode_id,
2000                            $block_alg_id,
2001                            $key_size
2002                        )>::new(key)),
2003                    )
2004                })?
2005            }};
2006        }
2007
2008        Ok(gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg!(
2009            mode,
2010            alg,
2011            gen_instantiate
2012        ))
2013    }
2014
2015    fn block_cipher_block_len(&self) -> usize {
2016        macro_rules! gen_block_cipher_block_len {
2017            ($_mode_id:ident, $block_cipher_alg_id:ident, $key_size:tt, $_block_cipher_instance:ident) => {
2018                block_cipher_to_block_len!($block_cipher_alg_id, $key_size)
2019            };
2020        }
2021        gen_match_on_block_cipher_mode_decryption_instance!(self, gen_block_cipher_block_len, _block_cipher_instance)
2022    }
2023
2024    fn iv_len(&self) -> usize {
2025        macro_rules! gen_iv_len_for_mode_and_block_cipher {
2026            ($mode_id:ident,
2027              $block_alg_id:ident,
2028              $key_size:tt,
2029              $_block_cipher_instance:ident) => {
2030                mode_and_block_cipher_to_iv_len!($mode_id, $block_alg_id, $key_size)
2031            };
2032        }
2033        gen_match_on_block_cipher_mode_decryption_instance!(
2034            self,
2035            gen_iv_len_for_mode_and_block_cipher,
2036            _block_cipher_instance
2037        )
2038    }
2039
2040    #[inline(never)]
2041    fn decrypt<'a, 'b>(
2042        &self,
2043        iv: &[u8],
2044        dst: &mut dyn CryptoWalkableIoSlicesMutIter<'a>,
2045        src: &mut dyn CryptoWalkableIoSlicesIter<'b>,
2046        iv_out: Option<&mut [u8]>,
2047    ) -> Result<(), CryptoError> {
2048        // Generate code snippet for the block transform callback passed to
2049        // transform_next_blocks() for (external) mode implementations
2050        // implementing the cipher::BlockDecryptMut trait.
2051        macro_rules! gen_block_decrypt_trait_mode_block_decrypt_transform_cb_snippet {
2052            ($mode_transform_impl_instance:ident) => {
2053                |dst_blocks: &mut [u8], src_blocks: Option<&[u8]>| {
2054                    if let Some(src_blocks) = src_blocks {
2055                        $mode_transform_impl_instance.decrypt_block_b2b_mut(src_blocks.into(), dst_blocks.into());
2056                    } else {
2057                        $mode_transform_impl_instance.decrypt_block_mut(dst_blocks.into());
2058                    }
2059                }
2060            };
2061        }
2062
2063        gen_match_on_block_cipher_mode_decryption_instance!(
2064            self,
2065            sym_block_cipher_mode_instance_gen_transform,
2066            block_cipher_instance,
2067            gen_mode_decryptor_impl_new_instance_snippet,
2068            gen_block_decrypt_trait_mode_block_decrypt_transform_cb_snippet,
2069            gen_mode_transform_grab_iv_snippet,
2070            dst,
2071            src,
2072            iv,
2073            iv_out
2074        );
2075
2076        Ok(())
2077    }
2078
2079    #[inline(never)]
2080    fn decrypt_in_place<'a, DI: CryptoPeekableIoSlicesMutIter<'a>>(
2081        &self,
2082        iv: &[u8],
2083        mut dst: DI,
2084        iv_out: Option<&mut [u8]>,
2085    ) -> Result<(), CryptoError> {
2086        // Generate code snippet for the block transform callback passed to
2087        // transform_next_blocks_in_place() for (external) mode implementations
2088        // implementing the cipher::BlockDecryptMut trait.
2089        macro_rules! gen_block_decrypt_trait_mode_block_decrypt_transform_cb_snippet {
2090            ($mode_transform_impl_instance:ident) => {
2091                |dst_blocks: &mut [u8]| {
2092                    $mode_transform_impl_instance.decrypt_block_mut(dst_blocks.into());
2093                }
2094            };
2095        }
2096
2097        gen_match_on_block_cipher_mode_decryption_instance!(
2098            self,
2099            sym_block_cipher_mode_instance_gen_transform_in_place,
2100            block_cipher_instance,
2101            gen_mode_decryptor_impl_new_instance_snippet,
2102            gen_block_decrypt_trait_mode_block_decrypt_transform_cb_snippet,
2103            gen_mode_transform_grab_iv_snippet,
2104            dst,
2105            iv,
2106            iv_out
2107        );
2108
2109        Ok(())
2110    }
2111}
2112
2113impl convert::From<&SymBlockCipherModeDecryptionInstance> for SymBlockCipherAlg {
2114    fn from(value: &SymBlockCipherModeDecryptionInstance) -> Self {
2115        macro_rules! gen_block_cipher_to_block_cipher_alg {
2116            ($_mode_id:ident,
2117             $block_alg_id:ident,
2118             $key_size:tt,
2119             $_block_cipher_instance:ident) => {
2120                block_cipher_to_sym_block_cipher_alg_variant!($block_alg_id, $key_size)
2121            };
2122        }
2123        gen_match_on_block_cipher_mode_decryption_instance!(
2124            &*value.state,
2125            gen_block_cipher_to_block_cipher_alg,
2126            _block_cipher_instance
2127        )
2128    }
2129}
2130
2131impl convert::From<&SymBlockCipherModeDecryptionInstance> for tpm2_interface::TpmiAlgCipherMode {
2132    fn from(value: &SymBlockCipherModeDecryptionInstance) -> Self {
2133        macro_rules! gen_block_cipher_to_tpmi_alg_cipher_mode {
2134            ($mode_id:ident,
2135             $_block_alg_id:ident,
2136             $_key_size:tt,
2137             $_block_cipher_instance:ident) => {
2138                mode_to_tpmi_alg_cipher_mode!($mode_id)
2139            };
2140        }
2141        gen_match_on_block_cipher_mode_decryption_instance!(
2142            &*value.state,
2143            gen_block_cipher_to_tpmi_alg_cipher_mode,
2144            _block_cipher_instance
2145        )
2146    }
2147}