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 #[cfg(test)] 176 mod tests { 177 use super::{decrypt, decrypt8, encrypt, encrypt8, expand_key, inv_expanded_keys, ParBlocks}; 178 use core::{arch::aarch64::*, convert::TryInto}; 179 use hex_literal::hex; 180 181 /// FIPS 197, Appendix A.1: AES-128 Cipher Key 182 /// user input, unaligned buffer 183 const AES128_KEY: [u8; 16] = hex!("2b7e151628aed2a6abf7158809cf4f3c"); 184 185 /// FIPS 197 Appendix A.1: Expansion of a 128-bit Cipher Key 186 /// library controlled, aligned buffer 187 const AES128_EXP_KEYS: [[u8; 16]; 11] = [ 188 AES128_KEY, 189 hex!("a0fafe1788542cb123a339392a6c7605"), 190 hex!("f2c295f27a96b9435935807a7359f67f"), 191 hex!("3d80477d4716fe3e1e237e446d7a883b"), 192 hex!("ef44a541a8525b7fb671253bdb0bad00"), 193 hex!("d4d1c6f87c839d87caf2b8bc11f915bc"), 194 hex!("6d88a37a110b3efddbf98641ca0093fd"), 195 hex!("4e54f70e5f5fc9f384a64fb24ea6dc4f"), 196 hex!("ead27321b58dbad2312bf5607f8d292f"), 197 hex!("ac7766f319fadc2128d12941575c006e"), 198 hex!("d014f9a8c9ee2589e13f0cc8b6630ca6"), 199 ]; 200 201 /// Inverse expanded keys for [`AES128_EXPANDED_KEYS`] 202 const AES128_EXP_INVKEYS: [[u8; 16]; 11] = [ 203 hex!("d014f9a8c9ee2589e13f0cc8b6630ca6"), 204 hex!("0c7b5a631319eafeb0398890664cfbb4"), 205 hex!("df7d925a1f62b09da320626ed6757324"), 206 hex!("12c07647c01f22c7bc42d2f37555114a"), 207 hex!("6efcd876d2df54807c5df034c917c3b9"), 208 hex!("6ea30afcbc238cf6ae82a4b4b54a338d"), 209 hex!("90884413d280860a12a128421bc89739"), 210 hex!("7c1f13f74208c219c021ae480969bf7b"), 211 hex!("cc7505eb3e17d1ee82296c51c9481133"), 212 hex!("2b3708a7f262d405bc3ebdbf4b617d62"), 213 AES128_KEY, 214 ]; 215 216 /// FIPS 197, Appendix A.2: AES-192 Cipher Key 217 /// user input, unaligned buffer 218 const AES192_KEY: [u8; 24] = hex!("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"); 219 220 /// FIPS 197 Appendix A.2: Expansion of a 192-bit Cipher Key 221 /// library controlled, aligned buffer 222 const AES192_EXP_KEYS: [[u8; 16]; 13] = [ 223 hex!("8e73b0f7da0e6452c810f32b809079e5"), 224 hex!("62f8ead2522c6b7bfe0c91f72402f5a5"), 225 hex!("ec12068e6c827f6b0e7a95b95c56fec2"), 226 hex!("4db7b4bd69b5411885a74796e92538fd"), 227 hex!("e75fad44bb095386485af05721efb14f"), 228 hex!("a448f6d94d6dce24aa326360113b30e6"), 229 hex!("a25e7ed583b1cf9a27f939436a94f767"), 230 hex!("c0a69407d19da4e1ec1786eb6fa64971"), 231 hex!("485f703222cb8755e26d135233f0b7b3"), 232 hex!("40beeb282f18a2596747d26b458c553e"), 233 hex!("a7e1466c9411f1df821f750aad07d753"), 234 hex!("ca4005388fcc5006282d166abc3ce7b5"), 235 hex!("e98ba06f448c773c8ecc720401002202"), 236 ]; 237 238 /// FIPS 197, Appendix A.3: AES-256 Cipher Key 239 /// user input, unaligned buffer 240 const AES256_KEY: [u8; 32] = 241 hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"); 242 243 /// FIPS 197 Appendix A.3: Expansion of a 256-bit Cipher Key 244 /// library controlled, aligned buffer 245 const AES256_EXP_KEYS: [[u8; 16]; 15] = [ 246 hex!("603deb1015ca71be2b73aef0857d7781"), 247 hex!("1f352c073b6108d72d9810a30914dff4"), 248 hex!("9ba354118e6925afa51a8b5f2067fcde"), 249 hex!("a8b09c1a93d194cdbe49846eb75d5b9a"), 250 hex!("d59aecb85bf3c917fee94248de8ebe96"), 251 hex!("b5a9328a2678a647983122292f6c79b3"), 252 hex!("812c81addadf48ba24360af2fab8b464"), 253 hex!("98c5bfc9bebd198e268c3ba709e04214"), 254 hex!("68007bacb2df331696e939e46c518d80"), 255 hex!("c814e20476a9fb8a5025c02d59c58239"), 256 hex!("de1369676ccc5a71fa2563959674ee15"), 257 hex!("5886ca5d2e2f31d77e0af1fa27cf73c3"), 258 hex!("749c47ab18501ddae2757e4f7401905a"), 259 hex!("cafaaae3e4d59b349adf6acebd10190d"), 260 hex!("fe4890d1e6188d0b046df344706c631e"), 261 ]; 262 263 /// FIPS 197, Appendix B input 264 /// user input, unaligned buffer 265 const INPUT: [u8; 16] = hex!("3243f6a8885a308d313198a2e0370734"); 266 267 /// FIPS 197, Appendix B output 268 const EXPECTED: [u8; 16] = hex!("3925841d02dc09fbdc118597196a0b32"); 269 load_expanded_keys<const N: usize>(input: [[u8; 16]; N]) -> [uint8x16_t; N]270 fn load_expanded_keys<const N: usize>(input: [[u8; 16]; N]) -> [uint8x16_t; N] { 271 let mut output = [unsafe { vdupq_n_u8(0) }; N]; 272 273 for (src, dst) in input.iter().zip(output.iter_mut()) { 274 *dst = unsafe { vld1q_u8(src.as_ptr()) } 275 } 276 277 output 278 } 279 store_expanded_keys<const N: usize>(input: [uint8x16_t; N]) -> [[u8; 16]; N]280 fn store_expanded_keys<const N: usize>(input: [uint8x16_t; N]) -> [[u8; 16]; N] { 281 let mut output = [[0u8; 16]; N]; 282 283 for (src, dst) in input.iter().zip(output.iter_mut()) { 284 unsafe { vst1q_u8(dst.as_mut_ptr(), *src) } 285 } 286 287 output 288 } 289 290 #[test] aes128_key_expansion()291 fn aes128_key_expansion() { 292 let ek = expand_key(&AES128_KEY); 293 assert_eq!(store_expanded_keys(ek), AES128_EXP_KEYS); 294 } 295 296 #[test] aes128_key_expansion_inv()297 fn aes128_key_expansion_inv() { 298 let mut ek = load_expanded_keys(AES128_EXP_KEYS); 299 inv_expanded_keys(&mut ek); 300 assert_eq!(store_expanded_keys(ek), AES128_EXP_INVKEYS); 301 } 302 303 #[test] aes192_key_expansion()304 fn aes192_key_expansion() { 305 let ek = expand_key(&AES192_KEY); 306 assert_eq!(store_expanded_keys(ek), AES192_EXP_KEYS); 307 } 308 309 #[test] aes256_key_expansion()310 fn aes256_key_expansion() { 311 let ek = expand_key(&AES256_KEY); 312 assert_eq!(store_expanded_keys(ek), AES256_EXP_KEYS); 313 } 314 315 #[test] aes128_encrypt()316 fn aes128_encrypt() { 317 // Intentionally misaligned block 318 let mut block = [0u8; 19]; 319 block[3..].copy_from_slice(&INPUT); 320 321 unsafe { 322 encrypt( 323 &load_expanded_keys(AES128_EXP_KEYS), 324 (&mut block[3..]).try_into().unwrap(), 325 ) 326 }; 327 328 assert_eq!(&block[3..], &EXPECTED); 329 } 330 331 #[test] aes128_encrypt8()332 fn aes128_encrypt8() { 333 let mut blocks = ParBlocks::default(); 334 335 for block in &mut blocks { 336 block.copy_from_slice(&INPUT); 337 } 338 339 unsafe { encrypt8(&load_expanded_keys(AES128_EXP_KEYS), &mut blocks) }; 340 341 for block in &blocks { 342 assert_eq!(block.as_slice(), &EXPECTED); 343 } 344 } 345 346 #[test] aes128_decrypt()347 fn aes128_decrypt() { 348 // Intentionally misaligned block 349 let mut block = [0u8; 19]; 350 block[3..].copy_from_slice(&EXPECTED); 351 352 unsafe { 353 decrypt( 354 &load_expanded_keys(AES128_EXP_INVKEYS), 355 (&mut block[3..]).try_into().unwrap(), 356 ) 357 }; 358 359 assert_eq!(&block[3..], &INPUT); 360 } 361 362 #[test] aes128_decrypt8()363 fn aes128_decrypt8() { 364 let mut blocks = ParBlocks::default(); 365 366 for block in &mut blocks { 367 block.copy_from_slice(&EXPECTED); 368 } 369 370 unsafe { decrypt8(&load_expanded_keys(AES128_EXP_INVKEYS), &mut blocks) }; 371 372 for block in &blocks { 373 assert_eq!(block.as_slice(), &INPUT); 374 } 375 } 376 } 377