1 //! AES block cipher implementation using the ARMv8 Cryptography Extensions.
2 //!
3 //! Based on this C intrinsics implementation:
4 //! <https://github.com/noloader/AES-Intrinsics/blob/master/aes-arm.c>
5 //!
6 //! Original C written and placed in public domain by Jeffrey Walton.
7 //! Based on code from ARM, and by Johannes Schneiders, Skip Hovsmith and
8 //! Barry O'Rourke for the mbedTLS project.
9
10 #![allow(clippy::needless_range_loop)]
11
12 #[cfg(feature = "hazmat")]
13 pub(crate) mod hazmat;
14
15 mod decrypt;
16 mod encrypt;
17 mod expand;
18
19 use self::{
20 decrypt::{decrypt, decrypt8},
21 encrypt::{encrypt, encrypt8},
22 expand::{expand_key, inv_expanded_keys},
23 };
24 use crate::{Block, ParBlocks};
25 use cipher::{
26 consts::{U16, U24, U32, U8},
27 generic_array::GenericArray,
28 BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
29 };
30 use core::arch::aarch64::*;
31
32 macro_rules! define_aes_impl {
33 (
34 $name:ident,
35 $name_enc:ident,
36 $name_dec:ident,
37 $key_size:ty,
38 $rounds:tt,
39 $doc:expr
40 ) => {
41 #[doc=$doc]
42 #[doc = "block cipher"]
43 #[derive(Clone)]
44 pub struct $name {
45 encrypt: $name_enc,
46 decrypt: $name_dec,
47 }
48
49 impl NewBlockCipher for $name {
50 type KeySize = $key_size;
51
52 #[inline]
53 fn new(key: &GenericArray<u8, $key_size>) -> Self {
54 let encrypt = $name_enc::new(key);
55 let decrypt = $name_dec::from(&encrypt);
56 Self { encrypt, decrypt }
57 }
58 }
59
60 impl BlockCipher for $name {
61 type BlockSize = U16;
62 type ParBlocks = U8;
63 }
64
65 impl BlockEncrypt for $name {
66 #[inline]
67 fn encrypt_block(&self, block: &mut Block) {
68 self.encrypt.encrypt_block(block)
69 }
70
71 #[inline]
72 fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) {
73 self.encrypt.encrypt_par_blocks(blocks)
74 }
75 }
76
77 impl BlockDecrypt for $name {
78 #[inline]
79 fn decrypt_block(&self, block: &mut Block) {
80 self.decrypt.decrypt_block(block)
81 }
82
83 #[inline]
84 fn decrypt_par_blocks(&self, blocks: &mut ParBlocks) {
85 self.decrypt.decrypt_par_blocks(blocks)
86 }
87 }
88
89 #[doc=$doc]
90 #[doc = "block cipher (encrypt-only)"]
91 #[derive(Clone)]
92 pub struct $name_enc {
93 round_keys: [uint8x16_t; $rounds],
94 }
95
96 impl NewBlockCipher for $name_enc {
97 type KeySize = $key_size;
98
99 fn new(key: &GenericArray<u8, $key_size>) -> Self {
100 Self {
101 round_keys: expand_key(key.as_ref()),
102 }
103 }
104 }
105
106 impl BlockCipher for $name_enc {
107 type BlockSize = U16;
108 type ParBlocks = U8;
109 }
110
111 impl BlockEncrypt for $name_enc {
112 fn encrypt_block(&self, block: &mut Block) {
113 unsafe { encrypt(&self.round_keys, block) }
114 }
115
116 fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) {
117 unsafe { encrypt8(&self.round_keys, blocks) }
118 }
119 }
120
121 #[doc=$doc]
122 #[doc = "block cipher (decrypt-only)"]
123 #[derive(Clone)]
124 pub struct $name_dec {
125 round_keys: [uint8x16_t; $rounds],
126 }
127
128 impl NewBlockCipher for $name_dec {
129 type KeySize = $key_size;
130
131 fn new(key: &GenericArray<u8, $key_size>) -> Self {
132 $name_enc::new(key).into()
133 }
134 }
135
136 impl From<$name_enc> for $name_dec {
137 fn from(enc: $name_enc) -> $name_dec {
138 Self::from(&enc)
139 }
140 }
141
142 impl From<&$name_enc> for $name_dec {
143 fn from(enc: &$name_enc) -> $name_dec {
144 let mut round_keys = enc.round_keys;
145 inv_expanded_keys(&mut round_keys);
146 Self { round_keys }
147 }
148 }
149
150 impl BlockCipher for $name_dec {
151 type BlockSize = U16;
152 type ParBlocks = U8;
153 }
154
155 impl BlockDecrypt for $name_dec {
156 fn decrypt_block(&self, block: &mut Block) {
157 unsafe { decrypt(&self.round_keys, block) }
158 }
159
160 fn decrypt_par_blocks(&self, blocks: &mut ParBlocks) {
161 unsafe { decrypt8(&self.round_keys, blocks) }
162 }
163 }
164
165 opaque_debug::implement!($name);
166 opaque_debug::implement!($name_enc);
167 opaque_debug::implement!($name_dec);
168 };
169 }
170
171 define_aes_impl!(Aes128, Aes128Enc, Aes128Dec, U16, 11, "AES-128");
172 define_aes_impl!(Aes192, Aes192Enc, Aes192Dec, U24, 13, "AES-192");
173 define_aes_impl!(Aes256, Aes256Enc, Aes256Dec, U32, 15, "AES-256");
174
175 // TODO(tarcieri): use `stdarch` intrinsic for this when it becomes available
176 #[inline(always)]
vst1q_u8(dst: *mut u8, src: uint8x16_t)177 unsafe fn vst1q_u8(dst: *mut u8, src: uint8x16_t) {
178 dst.copy_from_nonoverlapping(&src as *const _ as *const u8, 16);
179 }
180
181 #[cfg(test)]
182 mod tests {
183 use super::{
184 decrypt, decrypt8, encrypt, encrypt8, expand_key, inv_expanded_keys, vst1q_u8, ParBlocks,
185 };
186 use core::{arch::aarch64::*, convert::TryInto};
187 use hex_literal::hex;
188
189 /// FIPS 197, Appendix A.1: AES-128 Cipher Key
190 /// user input, unaligned buffer
191 const AES128_KEY: [u8; 16] = hex!("2b7e151628aed2a6abf7158809cf4f3c");
192
193 /// FIPS 197 Appendix A.1: Expansion of a 128-bit Cipher Key
194 /// library controlled, aligned buffer
195 const AES128_EXP_KEYS: [[u8; 16]; 11] = [
196 AES128_KEY,
197 hex!("a0fafe1788542cb123a339392a6c7605"),
198 hex!("f2c295f27a96b9435935807a7359f67f"),
199 hex!("3d80477d4716fe3e1e237e446d7a883b"),
200 hex!("ef44a541a8525b7fb671253bdb0bad00"),
201 hex!("d4d1c6f87c839d87caf2b8bc11f915bc"),
202 hex!("6d88a37a110b3efddbf98641ca0093fd"),
203 hex!("4e54f70e5f5fc9f384a64fb24ea6dc4f"),
204 hex!("ead27321b58dbad2312bf5607f8d292f"),
205 hex!("ac7766f319fadc2128d12941575c006e"),
206 hex!("d014f9a8c9ee2589e13f0cc8b6630ca6"),
207 ];
208
209 /// Inverse expanded keys for [`AES128_EXPANDED_KEYS`]
210 const AES128_EXP_INVKEYS: [[u8; 16]; 11] = [
211 hex!("d014f9a8c9ee2589e13f0cc8b6630ca6"),
212 hex!("0c7b5a631319eafeb0398890664cfbb4"),
213 hex!("df7d925a1f62b09da320626ed6757324"),
214 hex!("12c07647c01f22c7bc42d2f37555114a"),
215 hex!("6efcd876d2df54807c5df034c917c3b9"),
216 hex!("6ea30afcbc238cf6ae82a4b4b54a338d"),
217 hex!("90884413d280860a12a128421bc89739"),
218 hex!("7c1f13f74208c219c021ae480969bf7b"),
219 hex!("cc7505eb3e17d1ee82296c51c9481133"),
220 hex!("2b3708a7f262d405bc3ebdbf4b617d62"),
221 AES128_KEY,
222 ];
223
224 /// FIPS 197, Appendix A.2: AES-192 Cipher Key
225 /// user input, unaligned buffer
226 const AES192_KEY: [u8; 24] = hex!("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b");
227
228 /// FIPS 197 Appendix A.2: Expansion of a 192-bit Cipher Key
229 /// library controlled, aligned buffer
230 const AES192_EXP_KEYS: [[u8; 16]; 13] = [
231 hex!("8e73b0f7da0e6452c810f32b809079e5"),
232 hex!("62f8ead2522c6b7bfe0c91f72402f5a5"),
233 hex!("ec12068e6c827f6b0e7a95b95c56fec2"),
234 hex!("4db7b4bd69b5411885a74796e92538fd"),
235 hex!("e75fad44bb095386485af05721efb14f"),
236 hex!("a448f6d94d6dce24aa326360113b30e6"),
237 hex!("a25e7ed583b1cf9a27f939436a94f767"),
238 hex!("c0a69407d19da4e1ec1786eb6fa64971"),
239 hex!("485f703222cb8755e26d135233f0b7b3"),
240 hex!("40beeb282f18a2596747d26b458c553e"),
241 hex!("a7e1466c9411f1df821f750aad07d753"),
242 hex!("ca4005388fcc5006282d166abc3ce7b5"),
243 hex!("e98ba06f448c773c8ecc720401002202"),
244 ];
245
246 /// FIPS 197, Appendix A.3: AES-256 Cipher Key
247 /// user input, unaligned buffer
248 const AES256_KEY: [u8; 32] =
249 hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
250
251 /// FIPS 197 Appendix A.3: Expansion of a 256-bit Cipher Key
252 /// library controlled, aligned buffer
253 const AES256_EXP_KEYS: [[u8; 16]; 15] = [
254 hex!("603deb1015ca71be2b73aef0857d7781"),
255 hex!("1f352c073b6108d72d9810a30914dff4"),
256 hex!("9ba354118e6925afa51a8b5f2067fcde"),
257 hex!("a8b09c1a93d194cdbe49846eb75d5b9a"),
258 hex!("d59aecb85bf3c917fee94248de8ebe96"),
259 hex!("b5a9328a2678a647983122292f6c79b3"),
260 hex!("812c81addadf48ba24360af2fab8b464"),
261 hex!("98c5bfc9bebd198e268c3ba709e04214"),
262 hex!("68007bacb2df331696e939e46c518d80"),
263 hex!("c814e20476a9fb8a5025c02d59c58239"),
264 hex!("de1369676ccc5a71fa2563959674ee15"),
265 hex!("5886ca5d2e2f31d77e0af1fa27cf73c3"),
266 hex!("749c47ab18501ddae2757e4f7401905a"),
267 hex!("cafaaae3e4d59b349adf6acebd10190d"),
268 hex!("fe4890d1e6188d0b046df344706c631e"),
269 ];
270
271 /// FIPS 197, Appendix B input
272 /// user input, unaligned buffer
273 const INPUT: [u8; 16] = hex!("3243f6a8885a308d313198a2e0370734");
274
275 /// FIPS 197, Appendix B output
276 const EXPECTED: [u8; 16] = hex!("3925841d02dc09fbdc118597196a0b32");
277
load_expanded_keys<const N: usize>(input: [[u8; 16]; N]) -> [uint8x16_t; N]278 fn load_expanded_keys<const N: usize>(input: [[u8; 16]; N]) -> [uint8x16_t; N] {
279 let mut output = [unsafe { vdupq_n_u8(0) }; N];
280
281 for (src, dst) in input.iter().zip(output.iter_mut()) {
282 *dst = unsafe { vld1q_u8(src.as_ptr()) }
283 }
284
285 output
286 }
287
store_expanded_keys<const N: usize>(input: [uint8x16_t; N]) -> [[u8; 16]; N]288 fn store_expanded_keys<const N: usize>(input: [uint8x16_t; N]) -> [[u8; 16]; N] {
289 let mut output = [[0u8; 16]; N];
290
291 for (src, dst) in input.iter().zip(output.iter_mut()) {
292 unsafe { vst1q_u8(dst.as_mut_ptr(), *src) }
293 }
294
295 output
296 }
297
298 #[test]
aes128_key_expansion()299 fn aes128_key_expansion() {
300 let ek = expand_key(&AES128_KEY);
301 assert_eq!(store_expanded_keys(ek), AES128_EXP_KEYS);
302 }
303
304 #[test]
aes128_key_expansion_inv()305 fn aes128_key_expansion_inv() {
306 let mut ek = load_expanded_keys(AES128_EXP_KEYS);
307 inv_expanded_keys(&mut ek);
308 assert_eq!(store_expanded_keys(ek), AES128_EXP_INVKEYS);
309 }
310
311 #[test]
aes192_key_expansion()312 fn aes192_key_expansion() {
313 let ek = expand_key(&AES192_KEY);
314 assert_eq!(store_expanded_keys(ek), AES192_EXP_KEYS);
315 }
316
317 #[test]
aes256_key_expansion()318 fn aes256_key_expansion() {
319 let ek = expand_key(&AES256_KEY);
320 assert_eq!(store_expanded_keys(ek), AES256_EXP_KEYS);
321 }
322
323 #[test]
aes128_encrypt()324 fn aes128_encrypt() {
325 // Intentionally misaligned block
326 let mut block = [0u8; 19];
327 block[3..].copy_from_slice(&INPUT);
328
329 unsafe {
330 encrypt(
331 &load_expanded_keys(AES128_EXP_KEYS),
332 (&mut block[3..]).try_into().unwrap(),
333 )
334 };
335
336 assert_eq!(&block[3..], &EXPECTED);
337 }
338
339 #[test]
aes128_encrypt8()340 fn aes128_encrypt8() {
341 let mut blocks = ParBlocks::default();
342
343 for block in &mut blocks {
344 block.copy_from_slice(&INPUT);
345 }
346
347 unsafe { encrypt8(&load_expanded_keys(AES128_EXP_KEYS), &mut blocks) };
348
349 for block in &blocks {
350 assert_eq!(block.as_slice(), &EXPECTED);
351 }
352 }
353
354 #[test]
aes128_decrypt()355 fn aes128_decrypt() {
356 // Intentionally misaligned block
357 let mut block = [0u8; 19];
358 block[3..].copy_from_slice(&EXPECTED);
359
360 unsafe {
361 decrypt(
362 &load_expanded_keys(AES128_EXP_INVKEYS),
363 (&mut block[3..]).try_into().unwrap(),
364 )
365 };
366
367 assert_eq!(&block[3..], &INPUT);
368 }
369
370 #[test]
aes128_decrypt8()371 fn aes128_decrypt8() {
372 let mut blocks = ParBlocks::default();
373
374 for block in &mut blocks {
375 block.copy_from_slice(&EXPECTED);
376 }
377
378 unsafe { decrypt8(&load_expanded_keys(AES128_EXP_INVKEYS), &mut blocks) };
379
380 for block in &blocks {
381 assert_eq!(block.as_slice(), &INPUT);
382 }
383 }
384 }
385