Skip to main content

cocoon_tpm_crypto/
symcipher.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2023-2025 SUSE LLC
3// Author: Nicolai Stange <nstange@suse.de>
4
5//! Common interface to symmetric cipher algorithm implementations.
6//!
7//! # High level overview:
8//!
9//! For the encryption with block ciphers, a
10//! [`SymBlockCipherModeEncryptionInstance`] must first get instantiated either
11//! [directly with a raw key byte slice](SymBlockCipherModeEncryption
12//! Instance::new) or through a
13//! [`SymBlockCipherKey`](SymBlockCipherKey::instantiate_block_cipher_mode_enc).
14//! That instance can then be used to
15//! [encrypt](SymBlockCipherModeEncryptionInstance::encrypt) one or more
16//! messages.
17//!
18//! Similarly, for the decryption with block ciphers, a
19//! [`SymBlockCipherModeDecryptionInstance`] must first get instantiated either
20//! [directly with a raw key byte slice](SymBlockCipherModeDecryption
21//! Instance::new) or through a
22//! [`SymBlockCipherKey`](SymBlockCipherKey::instantiate_block_cipher_mode_dec).
23//! That instance can then be used to
24//! [decrypt](SymBlockCipherModeDecryptionInstance::decrypt) one or more
25//! messages.
26
27// Lifetimes are not obvious at first sight here, make the explicit.
28#![allow(clippy::needless_lifetimes)]
29
30extern crate alloc;
31use alloc::vec::Vec;
32
33use crate::{
34    CryptoError,
35    io_slices::{CryptoPeekableIoSlicesMutIter, CryptoWalkableIoSlicesIter, CryptoWalkableIoSlicesMutIter},
36    rng,
37};
38use crate::{
39    tpm2_interface,
40    utils_common::{
41        alloc::try_alloc_zeroizing_vec,
42        bitmanip::BitManip as _,
43        io_slices::{self, IoSlicesIterCommon as _, IoSlicesMutIter as _},
44        zeroize,
45    },
46};
47use core::convert;
48
49/// AES key sizes.
50#[cfg(feature = "aes")]
51#[derive(Clone, Copy, PartialEq, Eq)]
52pub enum SymBlockCipherAesKeySize {
53    Aes128,
54    Aes192,
55    Aes256,
56}
57
58/// Camellia key sizes.
59#[cfg(feature = "camellia")]
60#[derive(Clone, Copy, PartialEq, Eq)]
61pub enum SymBlockCipherCamelliaKeySize {
62    Camellia128,
63    Camellia192,
64    Camellia256,
65}
66
67/// SM4 key sizes.
68#[cfg(feature = "sm4")]
69#[derive(Clone, Copy, PartialEq, Eq)]
70pub enum SymBlockCipherSm4KeySize {
71    Sm4_128,
72}
73
74/// Indentify a symmetric block cipher algorithm together with a selected key
75/// size.
76///
77/// For example `SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128)`
78/// would identify "Aes128".
79#[derive(Clone, Copy, PartialEq, Eq)]
80pub enum SymBlockCipherAlg {
81    #[cfg(feature = "aes")]
82    Aes(SymBlockCipherAesKeySize),
83    #[cfg(feature = "camellia")]
84    Camellia(SymBlockCipherCamelliaKeySize),
85    #[cfg(feature = "sm4")]
86    Sm4(SymBlockCipherSm4KeySize),
87}
88
89/// Map pair of (symbolic block cipher, key size) to the block length.
90macro_rules! block_cipher_to_block_len {
91    (Aes, 128) => {
92        16
93    };
94    (Aes, 192) => {
95        16
96    };
97    (Aes, 256) => {
98        16
99    };
100    (Camellia, 128) => {
101        16
102    };
103    (Camellia, 192) => {
104        16
105    };
106    (Camellia, 256) => {
107        16
108    };
109    (Sm4, 128) => {
110        16
111    };
112}
113
114/// Map pair of (symbolic block cipher, key size) to the key length in bytes.
115macro_rules! block_cipher_to_key_len {
116    (Aes, 128) => {
117        16
118    };
119    (Aes, 192) => {
120        24
121    };
122    (Aes, 256) => {
123        32
124    };
125    (Camellia, 128) => {
126        16
127    };
128    (Camellia, 192) => {
129        24
130    };
131    (Camellia, 256) => {
132        32
133    };
134    (Sm4, 128) => {
135        16
136    };
137}
138
139/// Generate a `match {}` on SymBlockCipherAlg and invoke a macro in the body of
140/// each match arm.
141///
142/// The supplied macro `m` gets invoked with (`$args`, symbolic block cipher,
143/// key size) for each arm.
144macro_rules! gen_match_on_block_cipher_alg {
145    ($block_cipher_alg_value:expr, $m:ident $(, $($args:tt),*)?) => {
146        match $block_cipher_alg_value {
147            #[cfg(feature = "aes")]
148            SymBlockCipherAlg::Aes(key_size) => {
149                match key_size {
150                    SymBlockCipherAesKeySize::Aes128 => {
151                        $m!($($($args),*,)? Aes, 128)
152                    },
153                    SymBlockCipherAesKeySize::Aes192 => {
154                        $m!($($($args),*,)? Aes, 192)
155                    },
156                    SymBlockCipherAesKeySize::Aes256 => {
157                        $m!($($($args),*,)? Aes, 256)
158                    },
159                }
160            },
161            #[cfg(feature = "camellia")]
162            SymBlockCipherAlg::Camellia(key_size) => {
163                match key_size {
164                    SymBlockCipherCamelliaKeySize::Camellia128 => {
165                        $m!($($($args),*,)? Camellia, 128)
166                    },
167                    SymBlockCipherCamelliaKeySize::Camellia192 => {
168                        $m!($($($args),*,)? Camellia, 192)
169                    },
170                    SymBlockCipherCamelliaKeySize::Camellia256 => {
171                        $m!($($($args),*,)? Camellia, 256)
172                    },
173                }
174            },
175            #[cfg(feature = "sm4")]
176            SymBlockCipherAlg::Sm4(key_size) => {
177                match key_size {
178                    SymBlockCipherSm4KeySize::Sm4_128 => {
179                        $m!($($($args),*,)? Sm4, 128)
180                    },
181                }
182            },
183        }
184    };
185}
186
187macro_rules! gen_match_on_tpmi_alg_cipher_mode {
188    ($mode_value:expr, $m:ident $(, $($args:tt),*)?) => {
189        match $mode_value {
190            #[cfg(feature = "ctr")]
191            tpm2_interface::TpmiAlgCipherMode::Ctr => {
192                $m!($($($args),*,)? Ctr)
193            },
194            #[cfg(feature = "ofb")]
195            tpm2_interface::TpmiAlgCipherMode::Ofb => {
196                $m!($($($args),*,)? Ofb)
197            },
198            #[cfg(feature = "cbc")]
199            tpm2_interface::TpmiAlgCipherMode::Cbc => {
200                $m!($($($args),*,)? Cbc)
201            },
202            #[cfg(feature = "cfb")]
203            tpm2_interface::TpmiAlgCipherMode::Cfb => {
204                $m!($($($args),*,)? Cfb)
205            },
206            #[cfg(feature = "ecb")]
207            tpm2_interface::TpmiAlgCipherMode::Ecb => {
208                $m!($($($args),*,)? Ecb)
209            },
210        }
211    };
212}
213
214// This gets invoked with the symbolic mode identifier appended to the args.
215macro_rules! __gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg {
216    ($block_cipher_alg_value:tt, $m:ident, $($args_and_mode_id:tt),*) => {
217        gen_match_on_block_cipher_alg!($block_cipher_alg_value, $m, $($args_and_mode_id),*)
218    };
219}
220
221/// Generated a nested `match {}` on a pair of
222/// [`TpmiAlgCipherMode`](tpm2_interface::TpmiAlgCipherMode) and
223/// [`SymBlockCipherAlg`]. The macro `$m` will get invoked within each match arm
224/// with the `$args` passed through and extended by a triplet of (symbolic mode,
225/// symbolic block cipher, key size) at the tail.
226macro_rules! gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg {
227    ($mode_value:expr, $block_cipher_alg_value:expr, $m:ident $(, $($args:tt),*)?) => {
228        gen_match_on_tpmi_alg_cipher_mode!(
229            $mode_value,
230            __gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg, $block_cipher_alg_value, $m $(,$($args),*)?
231        )
232    };
233}
234
235/// Map a triplet of (symbolic mode, symbolic block cipher, key size) to the IV
236/// length.
237macro_rules! mode_and_block_cipher_to_iv_len {
238    (Ctr, $block_alg_id:ident, $key_size:tt) => {
239        block_cipher_to_block_len!($block_alg_id, $key_size)
240    };
241    (Ofb, $block_alg_id:ident, $key_size:tt) => {
242        block_cipher_to_block_len!($block_alg_id, $key_size)
243    };
244    (Cbc, $block_alg_id:ident, $key_size:tt) => {
245        block_cipher_to_block_len!($block_alg_id, $key_size)
246    };
247    (Cfb, $block_alg_id:ident, $key_size:tt) => {
248        block_cipher_to_block_len!($block_alg_id, $key_size)
249    };
250    (Ecb, $_block_alg_id:ident, $_key_size:tt) => {
251        0
252    };
253}
254
255#[cfg(test)]
256macro_rules! mode_supports_partial_last_block {
257    (Ctr) => {
258        true
259    };
260    (Ofb) => {
261        true
262    };
263    (Cbc) => {
264        false
265    };
266    (Cfb) => {
267        true
268    };
269    (Ecb) => {
270        false
271    };
272}
273
274impl SymBlockCipherAlg {
275    /// Determine the key length associated with the symmetric block cipher
276    /// algorithm.
277    pub fn key_len(&self) -> usize {
278        macro_rules! gen_block_cipher_key_len {
279            ($block_alg_id:ident,
280             $key_size:tt) => {
281                block_cipher_to_key_len!($block_alg_id, $key_size)
282            };
283        }
284        gen_match_on_block_cipher_alg!(self, gen_block_cipher_key_len)
285    }
286
287    /// Determine the block length associated with the symmetric block cipher
288    /// algorithm.
289    pub fn block_len(&self) -> usize {
290        macro_rules! gen_block_cipher_block_len {
291            ($block_alg_id:ident,
292             $key_size:tt) => {
293                block_cipher_to_block_len!($block_alg_id, $key_size)
294            };
295        }
296        gen_match_on_block_cipher_alg!(self, gen_block_cipher_block_len)
297    }
298
299    /// Determine the IV length for a [block cipher
300    /// mode](tpm2_interface::TpmiAlgCipherMode) operating on the symmetric
301    /// block cipher algorithm.
302    pub fn iv_len_for_mode(&self, mode: tpm2_interface::TpmiAlgCipherMode) -> usize {
303        gen_match_on_tpmi_alg_cipher_mode_and_block_cipher_alg!(mode, self, mode_and_block_cipher_to_iv_len)
304    }
305}
306
307impl convert::TryFrom<(tpm2_interface::TpmiAlgSymObject, u16)> for SymBlockCipherAlg {
308    type Error = CryptoError;
309
310    /// Convert a pair of [TCG block cipher algorithm
311    /// identifier](tpm2_interface::TpmiAlgSymObject) and key size to
312    /// a [symmetric block cipher algorithm identifier](SymBlockCipherAlg).
313    fn try_from(value: (tpm2_interface::TpmiAlgSymObject, u16)) -> Result<Self, Self::Error> {
314        let (block_alg, key_size) = value;
315
316        match block_alg {
317            #[cfg(feature = "aes")]
318            tpm2_interface::TpmiAlgSymObject::Aes => match key_size {
319                128 => Ok(Self::Aes(SymBlockCipherAesKeySize::Aes128)),
320                192 => Ok(Self::Aes(SymBlockCipherAesKeySize::Aes192)),
321                256 => Ok(Self::Aes(SymBlockCipherAesKeySize::Aes256)),
322                _ => Err(CryptoError::InvalidParams),
323            },
324            #[cfg(feature = "camellia")]
325            tpm2_interface::TpmiAlgSymObject::Camellia => match key_size {
326                128 => Ok(Self::Camellia(SymBlockCipherCamelliaKeySize::Camellia128)),
327                192 => Ok(Self::Camellia(SymBlockCipherCamelliaKeySize::Camellia192)),
328                256 => Ok(Self::Camellia(SymBlockCipherCamelliaKeySize::Camellia256)),
329                _ => Err(CryptoError::InvalidParams),
330            },
331            #[cfg(feature = "sm4")]
332            tpm2_interface::TpmiAlgSymObject::Sm4 => match key_size {
333                128 => Ok(Self::Sm4(SymBlockCipherSm4KeySize::Sm4_128)),
334                _ => Err(CryptoError::InvalidParams),
335            },
336        }
337    }
338}
339
340impl convert::From<&SymBlockCipherAlg> for (tpm2_interface::TpmiAlgSymObject, u16) {
341    /// Convert a [symmetric block cipher algorithm
342    /// identifier](SymBlockCipherAlg) into a pair of [TCG block cipher
343    /// algorithm identifier](tpm2_interface::TpmiAlgSymObject) and key size.
344    fn from(value: &SymBlockCipherAlg) -> Self {
345        match value {
346            #[cfg(feature = "aes")]
347            SymBlockCipherAlg::Aes(key_size) => (
348                tpm2_interface::TpmiAlgSymObject::Aes,
349                match key_size {
350                    SymBlockCipherAesKeySize::Aes128 => 128,
351                    SymBlockCipherAesKeySize::Aes192 => 192,
352                    SymBlockCipherAesKeySize::Aes256 => 256,
353                },
354            ),
355            #[cfg(feature = "camellia")]
356            SymBlockCipherAlg::Camellia(key_size) => (
357                tpm2_interface::TpmiAlgSymObject::Camellia,
358                match key_size {
359                    SymBlockCipherCamelliaKeySize::Camellia128 => 128,
360                    SymBlockCipherCamelliaKeySize::Camellia192 => 192,
361                    SymBlockCipherCamelliaKeySize::Camellia256 => 256,
362                },
363            ),
364            #[cfg(feature = "sm4")]
365            SymBlockCipherAlg::Sm4(key_size) => (
366                tpm2_interface::TpmiAlgSymObject::Sm4,
367                match key_size {
368                    SymBlockCipherSm4KeySize::Sm4_128 => 128,
369                },
370            ),
371        }
372    }
373}
374
375/// A symmetric block cipher key.
376///
377/// Associate the raw key material with a [symmetric block cipher algorithm
378/// identifier](SymBlockCipherAlg).
379///
380/// May get instantiate either through [key generation](Self::generate) or from
381/// an existing raw key via [`TryFrom`].
382pub struct SymBlockCipherKey {
383    block_cipher_alg: SymBlockCipherAlg,
384    key: zeroize::Zeroizing<Vec<u8>>,
385}
386
387impl SymBlockCipherKey {
388    /// Get the key's associated [symmetric block cipher algorithm
389    /// identifier](SymBlockCipherAlg).
390    pub fn get_block_cipher_alg(&self) -> SymBlockCipherAlg {
391        self.block_cipher_alg
392    }
393
394    /// Take the key.
395    pub fn take_key(self) -> zeroize::Zeroizing<Vec<u8>> {
396        let Self {
397            block_cipher_alg: _,
398            key,
399        } = self;
400        key
401    }
402
403    /// Generate a new block cipher key.
404    ///
405    /// # Arguments:
406    /// * `block_cipher_alg` - The block cipher algorithm to generate a key for.
407    /// * `rng` - The random number generator to obtain key material from.
408    /// * `additional_rng_generate_input` - Additional input to pass along to
409    ///   the `rng`'s [generate()](rng::RngCore::generate) primitive.
410    pub fn generate(
411        block_cipher_alg: SymBlockCipherAlg,
412        rng: &mut dyn rng::RngCoreDispatchable,
413        additional_rng_generate_input: Option<&[Option<&[u8]>]>,
414    ) -> Result<Self, CryptoError> {
415        let mut key = try_alloc_zeroizing_vec(block_cipher_alg.key_len())?;
416        rng::rng_dyn_dispatch_generate(
417            rng,
418            io_slices::SingletonIoSliceMut::new(&mut key).map_infallible_err(),
419            additional_rng_generate_input,
420        )?;
421        Ok(Self { block_cipher_alg, key })
422    }
423
424    /// Instantiate a block cipher mode encryption instance for the key.
425    ///
426    /// # Arguments:
427    ///
428    /// * `mode` - The block cipher mode to instantiate an encryption instance
429    ///   with the key for.
430    pub fn instantiate_block_cipher_mode_enc(
431        &self,
432        mode: tpm2_interface::TpmiAlgCipherMode,
433    ) -> Result<SymBlockCipherModeEncryptionInstance, CryptoError> {
434        SymBlockCipherModeEncryptionInstance::new(mode, &self.block_cipher_alg, &self.key)
435    }
436
437    /// Instantiate a block cipher mode decryption instance for the key.
438    ///
439    /// # Arguments:
440    ///
441    /// * `mode` - The block cipher mode to instantiate an decryption instance
442    ///   with the key for.
443    pub fn instantiate_block_cipher_mode_dec(
444        &self,
445        mode: tpm2_interface::TpmiAlgCipherMode,
446    ) -> Result<SymBlockCipherModeDecryptionInstance, CryptoError> {
447        SymBlockCipherModeDecryptionInstance::new(mode, &self.block_cipher_alg, &self.key)
448    }
449}
450
451impl convert::TryFrom<(SymBlockCipherAlg, &[u8])> for SymBlockCipherKey {
452    type Error = CryptoError;
453
454    /// Construct a [`SymBlockCipherKey`] from a pair of [symmetric block cipher
455    /// algorithm identifier](SymBlockCipherAlg) and a raw key byte slice.
456    fn try_from(value: (SymBlockCipherAlg, &[u8])) -> Result<Self, Self::Error> {
457        let (block_cipher_alg, supplied_key) = value;
458
459        if supplied_key.len() != block_cipher_alg.key_len() {
460            return Err(CryptoError::KeySize);
461        }
462
463        let mut key = try_alloc_zeroizing_vec::<u8>(block_cipher_alg.key_len())?;
464        key.copy_from_slice(supplied_key);
465
466        Ok(Self { block_cipher_alg, key })
467    }
468}
469
470impl convert::TryFrom<(SymBlockCipherAlg, zeroize::Zeroizing<Vec<u8>>)> for SymBlockCipherKey {
471    type Error = CryptoError;
472
473    /// Destructure a [`SymBlockCipherKey`] into a pair of [symmetric block
474    /// cipher algorithm identifier](SymBlockCipherAlg) and a raw key byte
475    /// `Vec`.
476    fn try_from(value: (SymBlockCipherAlg, zeroize::Zeroizing<Vec<u8>>)) -> Result<Self, Self::Error> {
477        let (block_cipher_alg, supplied_key) = value;
478
479        if supplied_key.len() != block_cipher_alg.key_len() {
480            return Err(CryptoError::KeySize);
481        }
482
483        Ok(Self {
484            block_cipher_alg,
485            key: supplied_key,
486        })
487    }
488}
489
490impl zeroize::ZeroizeOnDrop for SymBlockCipherKey {}
491
492pub(crate) fn transform_next_blocks<
493    'a,
494    'b,
495    const ENABLE_PARTIAL_LAST_BLOCK: bool,
496    BT: FnMut(&mut [u8], Option<&[u8]>),
497>(
498    dst: &mut dyn CryptoWalkableIoSlicesMutIter<'a>,
499    src: &mut dyn CryptoWalkableIoSlicesIter<'b>,
500    mut block_transform: BT,
501    block_len: usize,
502    scratch_block_buf: &mut [u8],
503) -> Result<bool, CryptoError> {
504    let first_dst_slice_len = dst.next_slice_len()?;
505    // Try to process a batch of multiple block cipher blocks at once.
506    if first_dst_slice_len >= 2 * block_len {
507        let first_src_slice_len = src.next_slice_len()?;
508        if first_src_slice_len >= 2 * block_len {
509            let batch_len = first_dst_slice_len.min(first_src_slice_len);
510            let batch_len = if block_len.is_pow2() {
511                batch_len & !(block_len - 1)
512            } else {
513                batch_len - (batch_len % block_len)
514            };
515            let batch_dst_slice = match dst.next_slice_mut(Some(batch_len))? {
516                Some(batch_dst_slice) => batch_dst_slice,
517                None => return Err(CryptoError::Internal),
518            };
519            let batch_src_slice = match src.next_slice(Some(batch_len))? {
520                Some(batch_src_slice) => batch_src_slice,
521                None => return Err(CryptoError::Internal),
522            };
523
524            let mut pos_in_batch_slice = 0;
525            while pos_in_batch_slice != batch_len {
526                block_transform(
527                    &mut batch_dst_slice[pos_in_batch_slice..pos_in_batch_slice + block_len],
528                    Some(&batch_src_slice[pos_in_batch_slice..pos_in_batch_slice + block_len]),
529                );
530                pos_in_batch_slice += block_len
531            }
532            return Ok(true);
533        }
534    }
535
536    let first_dst_slice = match dst.next_slice_mut(Some(block_len))? {
537        Some(first_dst_slice) => first_dst_slice,
538        None => {
539            if !src.is_empty()? {
540                return Err(CryptoError::Internal);
541            }
542            return Ok(false);
543        }
544    };
545    let first_src_slice = match src.next_slice(Some(block_len))? {
546        Some(first_src_slice) => first_src_slice,
547        None => return Err(CryptoError::Internal),
548    };
549    if first_src_slice.len() == block_len && first_dst_slice.len() == block_len {
550        block_transform(first_dst_slice, Some(first_src_slice));
551    } else {
552        debug_assert_eq!(scratch_block_buf.len(), block_len);
553        let mut src_block_len = first_src_slice.len();
554        scratch_block_buf[..src_block_len].copy_from_slice(first_src_slice);
555        src_block_len += io_slices::SingletonIoSliceMut::new(&mut scratch_block_buf[src_block_len..])
556            .map_infallible_err::<CryptoError>()
557            .copy_from_iter(src)?;
558        if src_block_len != block_len {
559            if !ENABLE_PARTIAL_LAST_BLOCK {
560                return Err(CryptoError::Internal);
561            } else {
562                scratch_block_buf[src_block_len..].fill(0);
563            }
564        } else if src_block_len < first_dst_slice.len() {
565            return Err(CryptoError::Internal);
566        }
567
568        block_transform(scratch_block_buf, None);
569
570        let mut dst_block_len = first_dst_slice.len();
571        first_dst_slice.copy_from_slice(&scratch_block_buf[..dst_block_len]);
572        dst_block_len += dst.copy_from_iter(
573            &mut io_slices::SingletonIoSlice::new(&scratch_block_buf[dst_block_len..src_block_len])
574                .map_infallible_err(),
575        )?;
576        if dst_block_len != src_block_len {
577            return Err(CryptoError::Internal);
578        }
579    }
580
581    Ok(true)
582}
583
584pub(crate) fn transform_next_blocks_in_place<
585    'a,
586    'b,
587    const ENABLE_PARTIAL_LAST_BLOCK: bool,
588    BT: FnMut(&mut [u8]),
589    DI: CryptoPeekableIoSlicesMutIter<'a>,
590>(
591    dst: &mut DI,
592    mut block_transform: BT,
593    block_len: usize,
594    scratch_block_buf: &mut [u8],
595) -> Result<bool, CryptoError> {
596    let first_dst_slice_len = dst.next_slice_len()?;
597    // Try to process a batch of multiple block cipher blocks at once.
598    if first_dst_slice_len >= 2 * block_len {
599        let batch_len = if block_len.is_pow2() {
600            first_dst_slice_len & !(block_len - 1)
601        } else {
602            first_dst_slice_len - (first_dst_slice_len % block_len)
603        };
604        let batch_dst_slice = match dst.next_slice_mut(Some(batch_len))? {
605            Some(batch_dst_slice) => batch_dst_slice,
606            None => return Err(CryptoError::Internal),
607        };
608
609        let mut pos_in_batch_slice = 0;
610        while pos_in_batch_slice != batch_len {
611            block_transform(&mut batch_dst_slice[pos_in_batch_slice..pos_in_batch_slice + block_len]);
612            pos_in_batch_slice += block_len
613        }
614        return Ok(true);
615    }
616
617    let first_dst_slice = match dst.next_slice_mut(Some(block_len))? {
618        Some(first_dst_slice) => first_dst_slice,
619        None => {
620            return Ok(false);
621        }
622    };
623    if first_dst_slice.len() == block_len {
624        block_transform(first_dst_slice);
625    } else {
626        debug_assert_eq!(scratch_block_buf.len(), block_len);
627        let mut src_block_len = first_dst_slice.len();
628        scratch_block_buf[..src_block_len].copy_from_slice(first_dst_slice);
629        // When copying from the destination into the scratch buffer, retain the
630        // original IOSlicesMut, so that the result can later get written back again.
631        src_block_len += io_slices::SingletonIoSliceMut::new(&mut scratch_block_buf[src_block_len..])
632            .map_infallible_err()
633            .copy_from_iter(&mut dst.decoupled_borrow())?;
634        if src_block_len != block_len {
635            if !ENABLE_PARTIAL_LAST_BLOCK {
636                return Err(CryptoError::Internal);
637            } else {
638                scratch_block_buf[src_block_len..].fill(0);
639            }
640        }
641
642        block_transform(scratch_block_buf);
643
644        let mut dst_block_len = first_dst_slice.len();
645        first_dst_slice.copy_from_slice(&scratch_block_buf[..dst_block_len]);
646        dst_block_len += dst.copy_from_iter(
647            &mut io_slices::SingletonIoSlice::new(&scratch_block_buf[dst_block_len..]).map_infallible_err(),
648        )?;
649        debug_assert_eq!(dst_block_len, src_block_len);
650    }
651
652    Ok(true)
653}
654
655pub use super::backend::symcipher::*;
656
657#[cfg(test)]
658fn test_mode_supports_partial_last_block(mode: tpm2_interface::TpmiAlgCipherMode) -> bool {
659    gen_match_on_tpmi_alg_cipher_mode!(mode, mode_supports_partial_last_block)
660}
661
662#[cfg(test)]
663fn test_encrypt_decrypt(mode: tpm2_interface::TpmiAlgCipherMode, block_cipher_alg: SymBlockCipherAlg) {
664    use alloc::vec;
665
666    let key_len = block_cipher_alg.key_len();
667    let key = vec![0xffu8; key_len];
668    let key = SymBlockCipherKey::try_from((block_cipher_alg, key.as_slice())).unwrap();
669
670    let block_cipher_mode_encryption_instance = key.instantiate_block_cipher_mode_enc(mode).unwrap();
671
672    let block_len = block_cipher_alg.block_len();
673    let mode_supports_partial_last_block = test_mode_supports_partial_last_block(mode);
674    let msg_len = if mode_supports_partial_last_block {
675        4 * block_len - 1
676    } else {
677        4 * block_len
678    };
679    let mut msg = vec![0u8; msg_len];
680    for (i, b) in msg.iter_mut().enumerate() {
681        *b = (i % u8::MAX as usize) as u8
682    }
683
684    let iv_len = block_cipher_mode_encryption_instance.iv_len();
685    let mut encrypted = vec![0u8; msg_len];
686    let mut iv_out = vec![0xccu8; iv_len];
687    // Encrypt in two steps for testing the intermediate IV extraction code.
688    for (r, is_last) in [(0..3 * block_len, false), (3 * block_len..msg_len, true)] {
689        let iv = iv_out.clone();
690        let r_len = r.len();
691        let (src0, src1) = msg[r.clone()].split_at(r_len / 4);
692        let (dst0, dst1) = encrypted[r].split_at_mut(r_len / 4 * 3);
693        block_cipher_mode_encryption_instance
694            .encrypt(
695                &iv,
696                io_slices::BuffersSliceIoSlicesMutIter::new(&mut [dst0, dst1]).map_infallible_err(),
697                io_slices::BuffersSliceIoSlicesIter::new(&[src0, src1]).map_infallible_err(),
698                (!is_last || !mode_supports_partial_last_block).then_some(&mut iv_out),
699            )
700            .unwrap();
701    }
702    assert_ne!(&msg, &encrypted);
703
704    // Decrypt, also in two steps, and compare the result with the original message.
705    let block_cipher_mode_decryption_instance = key.instantiate_block_cipher_mode_dec(mode).unwrap();
706    let mut decrypted = vec![0u8; msg_len];
707    let mut iv_out = vec![0xccu8; iv_len];
708    // Encrypt in two steps for testing the intermediate IV extraction code.
709    for (r, is_last) in [(0..2 * block_len, false), (2 * block_len..msg_len, true)] {
710        let iv = iv_out.clone();
711        let r_len = r.len();
712        let (src0, src1) = encrypted[r.clone()].split_at(r_len / 4);
713        let (dst0, dst1) = decrypted[r].split_at_mut(r_len / 4 * 3);
714        block_cipher_mode_decryption_instance
715            .decrypt(
716                &iv,
717                io_slices::BuffersSliceIoSlicesMutIter::new(&mut [dst0, dst1]).map_infallible_err(),
718                io_slices::BuffersSliceIoSlicesIter::new(&[src0, src1]).map_infallible_err(),
719                (!is_last || !mode_supports_partial_last_block).then_some(&mut iv_out),
720            )
721            .unwrap();
722    }
723    assert_eq!(&msg, &decrypted);
724}
725
726#[cfg(all(feature = "ctr", feature = "aes"))]
727#[test]
728fn test_encrypt_decrypt_ctr_aes128() {
729    test_encrypt_decrypt(
730        tpm2_interface::TpmiAlgCipherMode::Ctr,
731        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
732    )
733}
734
735#[cfg(all(feature = "ofb", feature = "aes"))]
736#[test]
737fn test_encrypt_decrypt_ofb_aes128() {
738    test_encrypt_decrypt(
739        tpm2_interface::TpmiAlgCipherMode::Ofb,
740        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
741    )
742}
743
744#[cfg(all(feature = "cbc", feature = "aes"))]
745#[test]
746fn test_encrypt_decrypt_cbc_aes128() {
747    test_encrypt_decrypt(
748        tpm2_interface::TpmiAlgCipherMode::Cbc,
749        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
750    )
751}
752
753#[cfg(all(feature = "cfb", feature = "aes"))]
754#[test]
755fn test_encrypt_decrypt_cfb_aes128() {
756    test_encrypt_decrypt(
757        tpm2_interface::TpmiAlgCipherMode::Cfb,
758        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
759    )
760}
761
762#[cfg(all(feature = "ecb", feature = "aes"))]
763#[test]
764fn test_encrypt_decrypt_ecb_aes128() {
765    test_encrypt_decrypt(
766        tpm2_interface::TpmiAlgCipherMode::Ecb,
767        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
768    )
769}
770
771#[cfg(all(feature = "ctr", feature = "aes"))]
772#[test]
773fn test_encrypt_decrypt_ctr_aes192() {
774    test_encrypt_decrypt(
775        tpm2_interface::TpmiAlgCipherMode::Ctr,
776        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
777    )
778}
779
780#[cfg(all(feature = "ofb", feature = "aes"))]
781#[test]
782fn test_encrypt_decrypt_ofb_aes192() {
783    test_encrypt_decrypt(
784        tpm2_interface::TpmiAlgCipherMode::Ofb,
785        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
786    )
787}
788
789#[cfg(all(feature = "cbc", feature = "aes"))]
790#[test]
791fn test_encrypt_decrypt_cbc_aes192() {
792    test_encrypt_decrypt(
793        tpm2_interface::TpmiAlgCipherMode::Cbc,
794        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
795    )
796}
797
798#[cfg(all(feature = "cfb", feature = "aes"))]
799#[test]
800fn test_encrypt_decrypt_cfb_aes192() {
801    test_encrypt_decrypt(
802        tpm2_interface::TpmiAlgCipherMode::Cfb,
803        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
804    )
805}
806
807#[cfg(all(feature = "ecb", feature = "aes"))]
808#[test]
809fn test_encrypt_decrypt_ecb_aes192() {
810    test_encrypt_decrypt(
811        tpm2_interface::TpmiAlgCipherMode::Ecb,
812        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
813    )
814}
815
816#[cfg(all(feature = "ctr", feature = "aes"))]
817#[test]
818fn test_encrypt_decrypt_ctr_aes256() {
819    test_encrypt_decrypt(
820        tpm2_interface::TpmiAlgCipherMode::Ctr,
821        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
822    )
823}
824
825#[cfg(all(feature = "ofb", feature = "aes"))]
826#[test]
827fn test_encrypt_decrypt_ofb_aes256() {
828    test_encrypt_decrypt(
829        tpm2_interface::TpmiAlgCipherMode::Ofb,
830        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
831    )
832}
833
834#[cfg(all(feature = "cbc", feature = "aes"))]
835#[test]
836fn test_encrypt_decrypt_cbc_aes256() {
837    test_encrypt_decrypt(
838        tpm2_interface::TpmiAlgCipherMode::Cbc,
839        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
840    )
841}
842
843#[cfg(all(feature = "cfb", feature = "aes"))]
844#[test]
845fn test_encrypt_decrypt_cfb_aes256() {
846    test_encrypt_decrypt(
847        tpm2_interface::TpmiAlgCipherMode::Cfb,
848        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
849    )
850}
851
852#[cfg(all(feature = "ecb", feature = "aes"))]
853#[test]
854fn test_encrypt_decrypt_ecb_aes256() {
855    test_encrypt_decrypt(
856        tpm2_interface::TpmiAlgCipherMode::Ecb,
857        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
858    )
859}
860
861#[cfg(all(feature = "ctr", feature = "camellia"))]
862#[test]
863fn test_encrypt_decrypt_ctr_camellia128() {
864    test_encrypt_decrypt(
865        tpm2_interface::TpmiAlgCipherMode::Ctr,
866        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
867    )
868}
869
870#[cfg(all(feature = "ofb", feature = "camellia"))]
871#[test]
872fn test_encrypt_decrypt_ofb_camellia128() {
873    test_encrypt_decrypt(
874        tpm2_interface::TpmiAlgCipherMode::Ofb,
875        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
876    )
877}
878
879#[cfg(all(feature = "cbc", feature = "camellia"))]
880#[test]
881fn test_encrypt_decrypt_cbc_camellia128() {
882    test_encrypt_decrypt(
883        tpm2_interface::TpmiAlgCipherMode::Cbc,
884        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
885    )
886}
887
888#[cfg(all(feature = "cfb", feature = "camellia"))]
889#[test]
890fn test_encrypt_decrypt_cfb_camellia128() {
891    test_encrypt_decrypt(
892        tpm2_interface::TpmiAlgCipherMode::Cfb,
893        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
894    )
895}
896
897#[cfg(all(feature = "ecb", feature = "camellia"))]
898#[test]
899fn test_encrypt_decrypt_ecb_camellia128() {
900    test_encrypt_decrypt(
901        tpm2_interface::TpmiAlgCipherMode::Ecb,
902        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
903    )
904}
905
906#[cfg(all(feature = "ctr", feature = "camellia"))]
907#[test]
908fn test_encrypt_decrypt_ctr_camellia192() {
909    test_encrypt_decrypt(
910        tpm2_interface::TpmiAlgCipherMode::Ctr,
911        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
912    )
913}
914
915#[cfg(all(feature = "ofb", feature = "camellia"))]
916#[test]
917fn test_encrypt_decrypt_ofb_camellia192() {
918    test_encrypt_decrypt(
919        tpm2_interface::TpmiAlgCipherMode::Ofb,
920        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
921    )
922}
923
924#[cfg(all(feature = "cbc", feature = "camellia"))]
925#[test]
926fn test_encrypt_decrypt_cbc_camellia192() {
927    test_encrypt_decrypt(
928        tpm2_interface::TpmiAlgCipherMode::Cbc,
929        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
930    )
931}
932
933#[cfg(all(feature = "cfb", feature = "camellia"))]
934#[test]
935fn test_encrypt_decrypt_cfb_camellia192() {
936    test_encrypt_decrypt(
937        tpm2_interface::TpmiAlgCipherMode::Cfb,
938        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
939    )
940}
941
942#[cfg(all(feature = "ecb", feature = "camellia"))]
943#[test]
944fn test_encrypt_decrypt_ecb_camellia192() {
945    test_encrypt_decrypt(
946        tpm2_interface::TpmiAlgCipherMode::Ecb,
947        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
948    )
949}
950
951#[cfg(all(feature = "ctr", feature = "camellia"))]
952#[test]
953fn test_encrypt_decrypt_ctr_camellia256() {
954    test_encrypt_decrypt(
955        tpm2_interface::TpmiAlgCipherMode::Ctr,
956        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
957    )
958}
959
960#[cfg(all(feature = "ofb", feature = "camellia"))]
961#[test]
962fn test_encrypt_decrypt_ofb_camellia256() {
963    test_encrypt_decrypt(
964        tpm2_interface::TpmiAlgCipherMode::Ofb,
965        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
966    )
967}
968
969#[cfg(all(feature = "cbc", feature = "camellia"))]
970#[test]
971fn test_encrypt_decrypt_cbc_camellia256() {
972    test_encrypt_decrypt(
973        tpm2_interface::TpmiAlgCipherMode::Cbc,
974        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
975    )
976}
977
978#[cfg(all(feature = "cfb", feature = "camellia"))]
979#[test]
980fn test_encrypt_decrypt_cfb_camellia256() {
981    test_encrypt_decrypt(
982        tpm2_interface::TpmiAlgCipherMode::Cfb,
983        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
984    )
985}
986
987#[cfg(all(feature = "ecb", feature = "camellia"))]
988#[test]
989fn test_encrypt_decrypt_ecb_camellia256() {
990    test_encrypt_decrypt(
991        tpm2_interface::TpmiAlgCipherMode::Ecb,
992        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
993    )
994}
995
996#[cfg(all(feature = "ctr", feature = "sm4"))]
997#[test]
998fn test_encrypt_decrypt_ctr_sm4_128() {
999    test_encrypt_decrypt(
1000        tpm2_interface::TpmiAlgCipherMode::Ctr,
1001        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1002    )
1003}
1004
1005#[cfg(all(feature = "ofb", feature = "sm4"))]
1006#[test]
1007fn test_encrypt_decrypt_ofb_sm4_128() {
1008    test_encrypt_decrypt(
1009        tpm2_interface::TpmiAlgCipherMode::Ofb,
1010        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1011    )
1012}
1013
1014#[cfg(all(feature = "cbc", feature = "sm4"))]
1015#[test]
1016fn test_encrypt_decrypt_cbc_sm4_128() {
1017    test_encrypt_decrypt(
1018        tpm2_interface::TpmiAlgCipherMode::Cbc,
1019        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1020    )
1021}
1022
1023#[cfg(all(feature = "cfb", feature = "sm4"))]
1024#[test]
1025fn test_encrypt_decrypt_cfb_sm4_128() {
1026    test_encrypt_decrypt(
1027        tpm2_interface::TpmiAlgCipherMode::Cfb,
1028        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1029    )
1030}
1031
1032#[cfg(all(feature = "ecb", feature = "sm4"))]
1033#[test]
1034fn test_encrypt_decrypt_ecb_sm4_128() {
1035    test_encrypt_decrypt(
1036        tpm2_interface::TpmiAlgCipherMode::Ecb,
1037        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1038    )
1039}
1040
1041#[cfg(test)]
1042fn test_encrypt_decrypt_in_place(mode: tpm2_interface::TpmiAlgCipherMode, block_cipher_alg: SymBlockCipherAlg) {
1043    use alloc::vec;
1044
1045    let key_len = block_cipher_alg.key_len();
1046    let key = vec![0xffu8; key_len];
1047    let key = SymBlockCipherKey::try_from((block_cipher_alg, key.as_slice())).unwrap();
1048
1049    let block_cipher_mode_encryption_instance = key.instantiate_block_cipher_mode_enc(mode).unwrap();
1050
1051    let block_len = block_cipher_alg.block_len();
1052    let mode_supports_partial_last_block = test_mode_supports_partial_last_block(mode);
1053    let msg_len = if mode_supports_partial_last_block {
1054        4 * block_len - 1
1055    } else {
1056        4 * block_len
1057    };
1058    let mut msg = vec![0u8; msg_len];
1059    for (i, b) in msg.iter_mut().enumerate() {
1060        *b = (i % u8::MAX as usize) as u8
1061    }
1062
1063    let iv_len = block_cipher_mode_encryption_instance.iv_len();
1064    let mut dst = vec![0u8; msg_len];
1065    dst.copy_from_slice(&msg);
1066    let mut iv_out = vec![0xccu8; iv_len];
1067    // Encrypt in two steps for testing the intermediate IV extraction code.
1068    for (r, is_last) in [(0..3 * block_len, false), (3 * block_len..msg_len, true)] {
1069        let iv = iv_out.clone();
1070        let r_len = r.len();
1071        let (dst0, dst1) = dst[r].split_at_mut(r_len / 4);
1072        block_cipher_mode_encryption_instance
1073            .encrypt_in_place(
1074                &iv,
1075                io_slices::BuffersSliceIoSlicesMutIter::new(&mut [dst0, dst1]).map_infallible_err(),
1076                (!is_last || !mode_supports_partial_last_block).then_some(&mut iv_out),
1077            )
1078            .unwrap();
1079    }
1080    assert_ne!(&msg, &dst);
1081
1082    // Decrypt, also in two steps, and compare the result with the original message.
1083    let block_cipher_mode_decryption_instance = key.instantiate_block_cipher_mode_dec(mode).unwrap();
1084    let mut iv_out = vec![0xccu8; iv_len];
1085    // Encrypt in two steps for testing the intermediate IV extraction code.
1086    for (r, is_last) in [(0..2 * block_len, false), (2 * block_len..msg_len, true)] {
1087        let iv = iv_out.clone();
1088        let r_len = r.len();
1089        let (dst0, dst1) = dst[r].split_at_mut(r_len / 4 * 3);
1090        block_cipher_mode_decryption_instance
1091            .decrypt_in_place(
1092                &iv,
1093                io_slices::BuffersSliceIoSlicesMutIter::new(&mut [dst0, dst1]).map_infallible_err(),
1094                (!is_last || !mode_supports_partial_last_block).then_some(&mut iv_out),
1095            )
1096            .unwrap();
1097    }
1098    assert_eq!(&msg, &dst);
1099}
1100
1101#[cfg(all(feature = "ctr", feature = "aes"))]
1102#[test]
1103fn test_encrypt_decrypt_in_place_ctr_aes128() {
1104    test_encrypt_decrypt_in_place(
1105        tpm2_interface::TpmiAlgCipherMode::Ctr,
1106        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
1107    )
1108}
1109
1110#[cfg(all(feature = "ofb", feature = "aes"))]
1111#[test]
1112fn test_encrypt_decrypt_in_place_ofb_aes128() {
1113    test_encrypt_decrypt_in_place(
1114        tpm2_interface::TpmiAlgCipherMode::Ofb,
1115        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
1116    )
1117}
1118
1119#[cfg(all(feature = "cbc", feature = "aes"))]
1120#[test]
1121fn test_encrypt_decrypt_in_place_cbc_aes128() {
1122    test_encrypt_decrypt_in_place(
1123        tpm2_interface::TpmiAlgCipherMode::Cbc,
1124        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
1125    )
1126}
1127
1128#[cfg(all(feature = "cfb", feature = "aes"))]
1129#[test]
1130fn test_encrypt_decrypt_in_place_cfb_aes128() {
1131    test_encrypt_decrypt_in_place(
1132        tpm2_interface::TpmiAlgCipherMode::Cfb,
1133        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
1134    )
1135}
1136
1137#[cfg(all(feature = "ecb", feature = "aes"))]
1138#[test]
1139fn test_encrypt_decrypt_in_place_ecb_aes128() {
1140    test_encrypt_decrypt_in_place(
1141        tpm2_interface::TpmiAlgCipherMode::Ecb,
1142        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128),
1143    )
1144}
1145
1146#[cfg(all(feature = "ctr", feature = "aes"))]
1147#[test]
1148fn test_encrypt_decrypt_in_place_ctr_aes192() {
1149    test_encrypt_decrypt_in_place(
1150        tpm2_interface::TpmiAlgCipherMode::Ctr,
1151        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
1152    )
1153}
1154
1155#[cfg(all(feature = "ofb", feature = "aes"))]
1156#[test]
1157fn test_encrypt_decrypt_in_place_ofb_aes192() {
1158    test_encrypt_decrypt_in_place(
1159        tpm2_interface::TpmiAlgCipherMode::Ofb,
1160        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
1161    )
1162}
1163
1164#[cfg(all(feature = "cbc", feature = "aes"))]
1165#[test]
1166fn test_encrypt_decrypt_in_place_cbc_aes192() {
1167    test_encrypt_decrypt_in_place(
1168        tpm2_interface::TpmiAlgCipherMode::Cbc,
1169        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
1170    )
1171}
1172
1173#[cfg(all(feature = "cfb", feature = "aes"))]
1174#[test]
1175fn test_encrypt_decrypt_in_place_cfb_aes192() {
1176    test_encrypt_decrypt_in_place(
1177        tpm2_interface::TpmiAlgCipherMode::Cfb,
1178        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
1179    )
1180}
1181
1182#[cfg(all(feature = "ecb", feature = "aes"))]
1183#[test]
1184fn test_encrypt_decrypt_in_place_ecb_aes192() {
1185    test_encrypt_decrypt_in_place(
1186        tpm2_interface::TpmiAlgCipherMode::Ecb,
1187        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes192),
1188    )
1189}
1190
1191#[cfg(all(feature = "ctr", feature = "aes"))]
1192#[test]
1193fn test_encrypt_decrypt_in_place_ctr_aes256() {
1194    test_encrypt_decrypt_in_place(
1195        tpm2_interface::TpmiAlgCipherMode::Ctr,
1196        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
1197    )
1198}
1199
1200#[cfg(all(feature = "ofb", feature = "aes"))]
1201#[test]
1202fn test_encrypt_decrypt_in_place_ofb_aes256() {
1203    test_encrypt_decrypt_in_place(
1204        tpm2_interface::TpmiAlgCipherMode::Ofb,
1205        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
1206    )
1207}
1208
1209#[cfg(all(feature = "cbc", feature = "aes"))]
1210#[test]
1211fn test_encrypt_decrypt_in_place_cbc_aes256() {
1212    test_encrypt_decrypt_in_place(
1213        tpm2_interface::TpmiAlgCipherMode::Cbc,
1214        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
1215    )
1216}
1217
1218#[cfg(all(feature = "cfb", feature = "aes"))]
1219#[test]
1220fn test_encrypt_decrypt_in_place_cfb_aes256() {
1221    test_encrypt_decrypt_in_place(
1222        tpm2_interface::TpmiAlgCipherMode::Cfb,
1223        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
1224    )
1225}
1226
1227#[cfg(all(feature = "ecb", feature = "aes"))]
1228#[test]
1229fn test_encrypt_decrypt_in_place_ecb_aes256() {
1230    test_encrypt_decrypt_in_place(
1231        tpm2_interface::TpmiAlgCipherMode::Ecb,
1232        SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes256),
1233    )
1234}
1235
1236#[cfg(all(feature = "ctr", feature = "camellia"))]
1237#[test]
1238fn test_encrypt_decrypt_in_place_ctr_camellia128() {
1239    test_encrypt_decrypt_in_place(
1240        tpm2_interface::TpmiAlgCipherMode::Ctr,
1241        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
1242    )
1243}
1244
1245#[cfg(all(feature = "ofb", feature = "camellia"))]
1246#[test]
1247fn test_encrypt_decrypt_in_place_ofb_camellia128() {
1248    test_encrypt_decrypt_in_place(
1249        tpm2_interface::TpmiAlgCipherMode::Ofb,
1250        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
1251    )
1252}
1253
1254#[cfg(all(feature = "cbc", feature = "camellia"))]
1255#[test]
1256fn test_encrypt_decrypt_in_place_cbc_camellia128() {
1257    test_encrypt_decrypt_in_place(
1258        tpm2_interface::TpmiAlgCipherMode::Cbc,
1259        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
1260    )
1261}
1262
1263#[cfg(all(feature = "cfb", feature = "camellia"))]
1264#[test]
1265fn test_encrypt_decrypt_in_place_cfb_camellia128() {
1266    test_encrypt_decrypt_in_place(
1267        tpm2_interface::TpmiAlgCipherMode::Cfb,
1268        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
1269    )
1270}
1271
1272#[cfg(all(feature = "ecb", feature = "camellia"))]
1273#[test]
1274fn test_encrypt_decrypt_in_place_ecb_camellia128() {
1275    test_encrypt_decrypt_in_place(
1276        tpm2_interface::TpmiAlgCipherMode::Ecb,
1277        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128),
1278    )
1279}
1280
1281#[cfg(all(feature = "ctr", feature = "camellia"))]
1282#[test]
1283fn test_encrypt_decrypt_in_place_ctr_camellia192() {
1284    test_encrypt_decrypt_in_place(
1285        tpm2_interface::TpmiAlgCipherMode::Ctr,
1286        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
1287    )
1288}
1289
1290#[cfg(all(feature = "ofb", feature = "camellia"))]
1291#[test]
1292fn test_encrypt_decrypt_in_place_ofb_camellia192() {
1293    test_encrypt_decrypt_in_place(
1294        tpm2_interface::TpmiAlgCipherMode::Ofb,
1295        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
1296    )
1297}
1298
1299#[cfg(all(feature = "cbc", feature = "camellia"))]
1300#[test]
1301fn test_encrypt_decrypt_in_place_cbc_camellia192() {
1302    test_encrypt_decrypt_in_place(
1303        tpm2_interface::TpmiAlgCipherMode::Cbc,
1304        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
1305    )
1306}
1307
1308#[cfg(all(feature = "cfb", feature = "camellia"))]
1309#[test]
1310fn test_encrypt_decrypt_in_place_cfb_camellia192() {
1311    test_encrypt_decrypt_in_place(
1312        tpm2_interface::TpmiAlgCipherMode::Cfb,
1313        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
1314    )
1315}
1316
1317#[cfg(all(feature = "ecb", feature = "camellia"))]
1318#[test]
1319fn test_encrypt_decrypt_in_place_ecb_camellia192() {
1320    test_encrypt_decrypt_in_place(
1321        tpm2_interface::TpmiAlgCipherMode::Ecb,
1322        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia192),
1323    )
1324}
1325
1326#[cfg(all(feature = "ctr", feature = "camellia"))]
1327#[test]
1328fn test_encrypt_decrypt_in_place_ctr_camellia256() {
1329    test_encrypt_decrypt_in_place(
1330        tpm2_interface::TpmiAlgCipherMode::Ctr,
1331        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
1332    )
1333}
1334
1335#[cfg(all(feature = "ofb", feature = "camellia"))]
1336#[test]
1337fn test_encrypt_decrypt_in_place_ofb_camellia256() {
1338    test_encrypt_decrypt_in_place(
1339        tpm2_interface::TpmiAlgCipherMode::Ofb,
1340        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
1341    )
1342}
1343
1344#[cfg(all(feature = "cbc", feature = "camellia"))]
1345#[test]
1346fn test_encrypt_decrypt_in_place_cbc_camellia256() {
1347    test_encrypt_decrypt_in_place(
1348        tpm2_interface::TpmiAlgCipherMode::Cbc,
1349        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
1350    )
1351}
1352
1353#[cfg(all(feature = "cfb", feature = "camellia"))]
1354#[test]
1355fn test_encrypt_decrypt_in_place_cfb_camellia256() {
1356    test_encrypt_decrypt_in_place(
1357        tpm2_interface::TpmiAlgCipherMode::Cfb,
1358        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
1359    )
1360}
1361
1362#[cfg(all(feature = "ecb", feature = "camellia"))]
1363#[test]
1364fn test_encrypt_decrypt_in_place_ecb_camellia256() {
1365    test_encrypt_decrypt_in_place(
1366        tpm2_interface::TpmiAlgCipherMode::Ecb,
1367        SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia256),
1368    )
1369}
1370
1371#[cfg(all(feature = "ctr", feature = "sm4"))]
1372#[test]
1373fn test_encrypt_decrypt_in_place_ctr_sm4_128() {
1374    test_encrypt_decrypt_in_place(
1375        tpm2_interface::TpmiAlgCipherMode::Ctr,
1376        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1377    )
1378}
1379
1380#[cfg(all(feature = "ofb", feature = "sm4"))]
1381#[test]
1382fn test_encrypt_decrypt_in_place_ofb_sm4_128() {
1383    test_encrypt_decrypt_in_place(
1384        tpm2_interface::TpmiAlgCipherMode::Ofb,
1385        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1386    )
1387}
1388
1389#[cfg(all(feature = "cbc", feature = "sm4"))]
1390#[test]
1391fn test_encrypt_decrypt_in_place_cbc_sm4_128() {
1392    test_encrypt_decrypt_in_place(
1393        tpm2_interface::TpmiAlgCipherMode::Cbc,
1394        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1395    )
1396}
1397
1398#[cfg(all(feature = "cfb", feature = "sm4"))]
1399#[test]
1400fn test_encrypt_decrypt_in_place_cfb_sm4_128() {
1401    test_encrypt_decrypt_in_place(
1402        tpm2_interface::TpmiAlgCipherMode::Cfb,
1403        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1404    )
1405}
1406
1407#[cfg(all(feature = "ecb", feature = "sm4"))]
1408#[test]
1409fn test_encrypt_decrypt_in_place_ecb_sm4_128() {
1410    test_encrypt_decrypt_in_place(
1411        tpm2_interface::TpmiAlgCipherMode::Ecb,
1412        SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128),
1413    )
1414}
1415
1416macro_rules! cfg_select_block_cipher_alg {
1417    (($f:literal, $id:expr)) => {
1418        #[cfg(feature = $f)]
1419        return $id;
1420        #[cfg(not(feature = $f))]
1421        {
1422            "Force compile error for no block cipher configured"
1423        }
1424    };
1425    (($f:literal, $id:expr), $(($f_more:literal, $id_more:expr)),+) => {
1426        #[cfg(feature = $f)]
1427        return $id;
1428        #[cfg(not(feature = $f))]
1429        {
1430            cfg_select_hash!($(($f_more, $id_more)),+)
1431        }
1432    };
1433}
1434
1435pub const fn test_block_cipher_alg() -> SymBlockCipherAlg {
1436    cfg_select_block_cipher_alg!(
1437        ("aes", SymBlockCipherAlg::Aes(SymBlockCipherAesKeySize::Aes128)),
1438        (
1439            "camellia",
1440            SymBlockCipherAlg::Camellia(SymBlockCipherCamelliaKeySize::Camellia128)
1441        ),
1442        ("sm4", SymBlockCipherAlg::Sm4(SymBlockCipherSm4KeySize::Sm4_128))
1443    );
1444}