Skip to main content

crypto/aes/
mod.rs

1mod aes;
2mod aes_ct;
3mod aes_ctr;
4mod aes_gcm;
5mod ghash;
6
7#[cfg(target_arch = "x86_64")]
8mod aes_amd64;
9#[cfg(target_arch = "aarch64")]
10mod aes_arm64;
11
12#[cfg(target_arch = "x86_64")]
13mod aes_gcm_amd64;
14#[cfg(target_arch = "aarch64")]
15mod aes_gcm_arm64;
16
17#[cfg(target_arch = "x86_64")]
18mod aes_ctr_amd64;
19#[cfg(target_arch = "aarch64")]
20mod aes_ctr_arm64;
21
22#[cfg(target_arch = "x86_64")]
23mod ghash_amd64;
24#[cfg(target_arch = "aarch64")]
25mod ghash_arm64;
26
27pub(crate) use aes::RoundKeys;
28pub use aes::{decrypt_block, encrypt_block, expand_key};
29pub use aes_ctr::{Aes128Ctr, Aes256Ctr};
30pub use aes_gcm::{Aes128Gcm, Aes256Gcm};
31
32/// A raw AES-128 block cipher.
33///
34/// Use this when the same key encrypts many single blocks, such as QUIC header protection
35/// (RFC 9001 ยง5.4.3), where the per-packet cost would otherwise be dominated by
36/// the schedule.
37#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
38pub struct Aes128Block {
39    schedule: aes_ct::CtSchedule,
40}
41
42impl Aes128Block {
43    /// Precomputes the AES-128 key schedule for `key`.
44    pub fn new(key: &[u8; 16]) -> Self {
45        Self {
46            schedule: aes_ct::keysched(&aes::expand_key::<11>(key)),
47        }
48    }
49
50    /// Encrypts one 16-byte block using the precomputed schedule.
51    #[inline(always)]
52    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
53        aes_ct::encrypt_block_sched(&self.schedule, block)
54    }
55}
56
57/// A raw AES-256 block cipher.
58///
59/// See [`Aes128Block`] to learn when to use this.
60#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
61pub struct Aes256Block {
62    schedule: aes_ct::CtSchedule,
63}
64
65impl Aes256Block {
66    /// Precomputes the AES-256 key schedule for `key`.
67    pub fn new(key: &[u8; 32]) -> Self {
68        Self {
69            schedule: aes_ct::keysched(&aes::expand_key::<15>(key)),
70        }
71    }
72
73    /// Encrypts one 16-byte block using the precomputed schedule.
74    #[inline(always)]
75    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
76        aes_ct::encrypt_block_sched(&self.schedule, block)
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    fn encrypt_block_128(key: &[u8; 16], block: &[u8; 16]) -> [u8; 16] {
85        encrypt_block(&expand_key::<11>(key), block)
86    }
87
88    fn encrypt_block_256(key: &[u8; 32], block: &[u8; 16]) -> [u8; 16] {
89        encrypt_block(&expand_key::<15>(key), block)
90    }
91
92    #[test]
93    fn precomputed_block_ciphers_match_one_shot() {
94        let key128 = [0x11u8; 16];
95        let key256 = [0x22u8; 32];
96        let block = [0x33u8; 16];
97
98        let aes128 = Aes128Block::new(&key128);
99        assert_eq!(aes128.encrypt_block(&block), encrypt_block_128(&key128, &block));
100
101        let aes256 = Aes256Block::new(&key256);
102        assert_eq!(aes256.encrypt_block(&block), encrypt_block_256(&key256, &block));
103    }
104}