1use crate::aws_lc::{
7 AES_cbc_encrypt, AES_cfb128_encrypt, AES_ctr128_encrypt, AES_ecb_encrypt, AES_DECRYPT,
8 AES_ENCRYPT, AES_KEY,
9};
10use crate::cipher::block::Block;
11use crate::error::Unspecified;
12use crate::fips::indicator_check;
13use zeroize::Zeroize;
14
15use super::{DecryptionContext, EncryptionContext, OperatingMode, SymmetricCipherKey};
16
17pub const AES_128_KEY_LEN: usize = 16;
19
20pub const AES_192_KEY_LEN: usize = 24;
22
23pub const AES_256_KEY_LEN: usize = 32;
25
26pub const AES_CBC_IV_LEN: usize = 16;
28
29pub const AES_CTR_IV_LEN: usize = 16;
31
32pub const AES_CFB_IV_LEN: usize = 16;
34
35pub const AES_BLOCK_LEN: usize = 16;
36
37#[inline]
38pub(crate) fn encrypt_block(aes_key: &AES_KEY, mut block: Block) -> Block {
39 {
40 let block_ref = block.as_mut();
41 debug_assert_eq!(block_ref.len(), AES_BLOCK_LEN);
42 aes_ecb_encrypt(aes_key, block_ref);
43 }
44 block
45}
46
47pub(super) fn encrypt_ctr_mode(
48 key: &SymmetricCipherKey,
49 context: EncryptionContext,
50 in_out: &mut [u8],
51) -> Result<DecryptionContext, Unspecified> {
52 let (SymmetricCipherKey::Aes128 { enc_key, .. }
53 | SymmetricCipherKey::Aes192 { enc_key, .. }
54 | SymmetricCipherKey::Aes256 { enc_key, .. }) = &key
55 else {
56 unreachable!()
57 };
58
59 let mut iv = {
60 let mut iv = [0u8; AES_CTR_IV_LEN];
61 iv.copy_from_slice((&context).try_into()?);
62 iv
63 };
64
65 let mut buffer = [0u8; AES_BLOCK_LEN];
66
67 aes_ctr128_encrypt(enc_key, &mut iv, &mut buffer, in_out);
68 iv.zeroize();
69
70 Ok(context.into())
71}
72
73pub(super) fn decrypt_ctr_mode<'in_out>(
74 key: &SymmetricCipherKey,
75 context: DecryptionContext,
76 in_out: &'in_out mut [u8],
77) -> Result<&'in_out mut [u8], Unspecified> {
78 encrypt_ctr_mode(key, context.into(), in_out).map(|_| in_out)
80}
81
82pub(super) fn encrypt_cbc_mode(
83 key: &SymmetricCipherKey,
84 context: EncryptionContext,
85 in_out: &mut [u8],
86) -> Result<DecryptionContext, Unspecified> {
87 let (SymmetricCipherKey::Aes128 { enc_key, .. }
88 | SymmetricCipherKey::Aes192 { enc_key, .. }
89 | SymmetricCipherKey::Aes256 { enc_key, .. }) = &key
90 else {
91 unreachable!()
92 };
93
94 let mut iv = {
95 let mut iv = [0u8; AES_CBC_IV_LEN];
96 iv.copy_from_slice((&context).try_into()?);
97 iv
98 };
99
100 aes_cbc_encrypt(enc_key, &mut iv, in_out);
101 iv.zeroize();
102
103 Ok(context.into())
104}
105
106#[allow(clippy::needless_pass_by_value)]
107pub(super) fn decrypt_cbc_mode<'in_out>(
108 key: &SymmetricCipherKey,
109 context: DecryptionContext,
110 in_out: &'in_out mut [u8],
111) -> Result<&'in_out mut [u8], Unspecified> {
112 let (SymmetricCipherKey::Aes128 { dec_key, .. }
113 | SymmetricCipherKey::Aes192 { dec_key, .. }
114 | SymmetricCipherKey::Aes256 { dec_key, .. }) = &key
115 else {
116 unreachable!()
117 };
118
119 let mut iv = {
120 let mut iv = [0u8; AES_CBC_IV_LEN];
121 iv.copy_from_slice((&context).try_into()?);
122 iv
123 };
124
125 aes_cbc_decrypt(dec_key, &mut iv, in_out);
126 iv.zeroize();
127
128 Ok(in_out)
129}
130
131#[allow(clippy::needless_pass_by_value)]
132pub(super) fn encrypt_cfb_mode(
133 key: &SymmetricCipherKey,
134 mode: OperatingMode,
135 context: EncryptionContext,
136 in_out: &mut [u8],
137) -> Result<DecryptionContext, Unspecified> {
138 let (SymmetricCipherKey::Aes128 { enc_key, .. }
139 | SymmetricCipherKey::Aes192 { enc_key, .. }
140 | SymmetricCipherKey::Aes256 { enc_key, .. }) = &key
141 else {
142 unreachable!()
143 };
144
145 let mut iv = {
146 let mut iv = [0u8; AES_CFB_IV_LEN];
147 iv.copy_from_slice((&context).try_into()?);
148 iv
149 };
150
151 let cfb_encrypt: fn(&AES_KEY, &mut [u8], &mut [u8]) = match mode {
152 OperatingMode::CFB128 => aes_cfb128_encrypt,
154 _ => unreachable!(),
155 };
156
157 cfb_encrypt(enc_key, &mut iv, in_out);
158 iv.zeroize();
159
160 Ok(context.into())
161}
162
163#[allow(clippy::needless_pass_by_value)]
164pub(super) fn decrypt_cfb_mode<'in_out>(
165 key: &SymmetricCipherKey,
166 mode: OperatingMode,
167 context: DecryptionContext,
168 in_out: &'in_out mut [u8],
169) -> Result<&'in_out mut [u8], Unspecified> {
170 let (SymmetricCipherKey::Aes128 { enc_key, .. }
171 | SymmetricCipherKey::Aes192 { enc_key, .. }
172 | SymmetricCipherKey::Aes256 { enc_key, .. }) = &key
173 else {
174 unreachable!()
175 };
176
177 let mut iv = {
178 let mut iv = [0u8; AES_CFB_IV_LEN];
179 iv.copy_from_slice((&context).try_into()?);
180 iv
181 };
182
183 let cfb_decrypt: fn(&AES_KEY, &mut [u8], &mut [u8]) = match mode {
184 OperatingMode::CFB128 => aes_cfb128_decrypt,
186 _ => unreachable!(),
187 };
188
189 cfb_decrypt(enc_key, &mut iv, in_out);
190
191 iv.zeroize();
192
193 Ok(in_out)
194}
195
196#[allow(clippy::needless_pass_by_value, clippy::unnecessary_wraps)]
197pub(super) fn encrypt_ecb_mode(
198 key: &SymmetricCipherKey,
199 context: EncryptionContext,
200 in_out: &mut [u8],
201) -> Result<DecryptionContext, Unspecified> {
202 if !matches!(context, EncryptionContext::None) {
203 unreachable!();
204 }
205
206 let (SymmetricCipherKey::Aes128 { enc_key, .. }
207 | SymmetricCipherKey::Aes192 { enc_key, .. }
208 | SymmetricCipherKey::Aes256 { enc_key, .. }) = &key
209 else {
210 unreachable!()
211 };
212
213 let mut in_out_iter = in_out.chunks_exact_mut(AES_BLOCK_LEN);
214
215 for block in in_out_iter.by_ref() {
216 aes_ecb_encrypt(enc_key, block);
217 }
218
219 debug_assert!(in_out_iter.into_remainder().is_empty());
222
223 Ok(context.into())
224}
225
226#[allow(clippy::needless_pass_by_value, clippy::unnecessary_wraps)]
227pub(super) fn decrypt_ecb_mode<'in_out>(
228 key: &SymmetricCipherKey,
229 context: DecryptionContext,
230 in_out: &'in_out mut [u8],
231) -> Result<&'in_out mut [u8], Unspecified> {
232 if !matches!(context, DecryptionContext::None) {
233 unreachable!();
234 }
235
236 let (SymmetricCipherKey::Aes128 { dec_key, .. }
237 | SymmetricCipherKey::Aes192 { dec_key, .. }
238 | SymmetricCipherKey::Aes256 { dec_key, .. }) = &key
239 else {
240 unreachable!()
241 };
242
243 {
244 let mut in_out_iter = in_out.chunks_exact_mut(AES_BLOCK_LEN);
245
246 for block in in_out_iter.by_ref() {
247 aes_ecb_decrypt(dec_key, block);
248 }
249
250 debug_assert!(in_out_iter.into_remainder().is_empty());
253 }
254
255 Ok(in_out)
256}
257
258fn aes_ecb_encrypt(key: &AES_KEY, in_out: &mut [u8]) {
259 indicator_check!(unsafe {
260 AES_ecb_encrypt(in_out.as_ptr(), in_out.as_mut_ptr(), key, AES_ENCRYPT);
261 });
262}
263
264fn aes_ecb_decrypt(key: &AES_KEY, in_out: &mut [u8]) {
265 indicator_check!(unsafe {
266 AES_ecb_encrypt(in_out.as_ptr(), in_out.as_mut_ptr(), key, AES_DECRYPT);
267 });
268}
269
270fn aes_ctr128_encrypt(key: &AES_KEY, iv: &mut [u8], block_buffer: &mut [u8], in_out: &mut [u8]) {
271 let mut num: u32 = 0;
272
273 indicator_check!(unsafe {
274 AES_ctr128_encrypt(
275 in_out.as_ptr(),
276 in_out.as_mut_ptr(),
277 in_out.len(),
278 key,
279 iv.as_mut_ptr(),
280 block_buffer.as_mut_ptr(),
281 &mut num,
282 );
283 });
284
285 Zeroize::zeroize(block_buffer);
286}
287
288fn aes_cbc_encrypt(key: &AES_KEY, iv: &mut [u8], in_out: &mut [u8]) {
289 indicator_check!(unsafe {
290 AES_cbc_encrypt(
291 in_out.as_ptr(),
292 in_out.as_mut_ptr(),
293 in_out.len(),
294 key,
295 iv.as_mut_ptr(),
296 AES_ENCRYPT,
297 );
298 });
299}
300
301fn aes_cbc_decrypt(key: &AES_KEY, iv: &mut [u8], in_out: &mut [u8]) {
302 indicator_check!(unsafe {
303 AES_cbc_encrypt(
304 in_out.as_ptr(),
305 in_out.as_mut_ptr(),
306 in_out.len(),
307 key,
308 iv.as_mut_ptr(),
309 AES_DECRYPT,
310 );
311 });
312}
313
314fn aes_cfb128_encrypt(key: &AES_KEY, iv: &mut [u8], in_out: &mut [u8]) {
315 let mut num: i32 = 0;
316 indicator_check!(unsafe {
317 AES_cfb128_encrypt(
318 in_out.as_ptr(),
319 in_out.as_mut_ptr(),
320 in_out.len(),
321 key,
322 iv.as_mut_ptr(),
323 &mut num,
324 AES_ENCRYPT,
325 );
326 });
327}
328
329fn aes_cfb128_decrypt(key: &AES_KEY, iv: &mut [u8], in_out: &mut [u8]) {
330 let mut num: i32 = 0;
331 indicator_check!(unsafe {
332 AES_cfb128_encrypt(
333 in_out.as_ptr(),
334 in_out.as_mut_ptr(),
335 in_out.len(),
336 key,
337 iv.as_mut_ptr(),
338 &mut num,
339 AES_DECRYPT,
340 );
341 });
342}