Skip to main content

ssh_cipher/block_cipher/
aes.rs

1//! AES block cipher.
2
3use super::sealed::BlockCipher;
4use crate::Cipher;
5use ::aes::{Aes128, Aes192, Aes256, Block};
6use ::cipher::{
7    BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure, BlockCipherEncrypt,
8    BlockSizeUser, InvalidLength, KeyInit, array::sizes::U16,
9};
10use core::fmt;
11use core::fmt::Debug;
12
13/// Advanced Encryption Standard (AES) low-level block cipher.
14///
15/// Supports 128-bit, 192-bit, and 256-bit keys.
16pub struct Aes {
17    inner: Inner,
18}
19
20/// Inner enum over supported key sizes.
21enum Inner {
22    Aes128(Aes128),
23    Aes192(Aes192),
24    Aes256(Aes256),
25}
26
27impl Aes {
28    /// Create a new AES block cipher instance.
29    ///
30    /// Supports `key` whose length is 16-bytes (128-bit), 24-bytes (192-bits), or 32-bytes
31    /// (256-bits).
32    ///
33    /// # Errors
34    /// Returns [`InvalidLength`] if the length of `key` is not any of the above.
35    pub fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
36        if let Ok(cipher) = Aes128::new_from_slice(key) {
37            return Ok(Self {
38                inner: Inner::Aes128(cipher),
39            });
40        }
41
42        if let Ok(cipher) = Aes192::new_from_slice(key) {
43            return Ok(Self {
44                inner: Inner::Aes192(cipher),
45            });
46        }
47
48        if let Ok(cipher) = Aes256::new_from_slice(key) {
49            return Ok(Self {
50                inner: Inner::Aes256(cipher),
51            });
52        }
53
54        Err(InvalidLength)
55    }
56}
57
58impl BlockCipher for Aes {
59    fn new_from_slice(slice: &[u8]) -> Result<Self, InvalidLength> {
60        Aes::new_from_slice(slice)
61    }
62
63    fn is_supported(cipher: Cipher) -> bool {
64        matches!(
65            cipher,
66            Cipher::Aes128Cbc
67                | Cipher::Aes192Cbc
68                | Cipher::Aes256Cbc
69                | Cipher::Aes128Ctr
70                | Cipher::Aes192Ctr
71                | Cipher::Aes256Ctr
72        )
73    }
74}
75
76impl BlockCipherDecrypt for Aes {
77    fn decrypt_blocks(&self, blocks: &mut [Block]) {
78        match &self.inner {
79            Inner::Aes128(aes) => aes.decrypt_blocks(blocks),
80            Inner::Aes192(aes) => aes.decrypt_blocks(blocks),
81            Inner::Aes256(aes) => aes.decrypt_blocks(blocks),
82        }
83    }
84
85    fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = Self::BlockSize>) {
86        match &self.inner {
87            Inner::Aes128(aes) => aes.decrypt_with_backend(f),
88            Inner::Aes192(aes) => aes.decrypt_with_backend(f),
89            Inner::Aes256(aes) => aes.decrypt_with_backend(f),
90        }
91    }
92}
93
94impl BlockCipherEncrypt for Aes {
95    fn encrypt_blocks(&self, blocks: &mut [Block]) {
96        match &self.inner {
97            Inner::Aes128(aes) => aes.encrypt_blocks(blocks),
98            Inner::Aes192(aes) => aes.encrypt_blocks(blocks),
99            Inner::Aes256(aes) => aes.encrypt_blocks(blocks),
100        }
101    }
102
103    fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = Self::BlockSize>) {
104        match &self.inner {
105            Inner::Aes128(aes) => aes.encrypt_with_backend(f),
106            Inner::Aes192(aes) => aes.encrypt_with_backend(f),
107            Inner::Aes256(aes) => aes.encrypt_with_backend(f),
108        }
109    }
110}
111
112impl BlockSizeUser for Aes {
113    type BlockSize = U16;
114}
115
116impl Debug for Aes {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        f.debug_struct("Aes").finish_non_exhaustive()
119    }
120}