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