1 // Copyright 2022 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! An abstraction layer around AES implementations. 16 //! 17 //! The design is an attempt to make it easy to provide implementations that are both idiomatic 18 //! Rust (e.g. RustCrypto) as well as FFI-backed (e.g. openssl and other C impls). 19 #![forbid(unsafe_code)] 20 #![deny(missing_docs)] 21 22 use core::{array, fmt}; 23 24 pub mod ctr; 25 26 #[cfg(feature = "alloc")] 27 pub mod cbc; 28 #[cfg(feature = "gcm_siv")] 29 pub mod gcm_siv; 30 31 /// Block size in bytes for AES (and XTS-AES) 32 pub const BLOCK_SIZE: usize = 16; 33 34 /// A single AES block. 35 pub type AesBlock = [u8; BLOCK_SIZE]; 36 37 /// Helper trait to enforce encryption and decryption with the same size key 38 pub trait Aes { 39 /// The AES key containing the raw bytes used to for key scheduling 40 type Key: AesKey; 41 42 /// The cipher used for encryption 43 type EncryptCipher: AesEncryptCipher<Key = Self::Key>; 44 45 /// the cipher used for decryption 46 type DecryptCipher: AesDecryptCipher<Key = Self::Key>; 47 } 48 49 /// The base AesCipher trait which describes common operations to both encryption and decryption ciphers 50 pub trait AesCipher { 51 /// The type of the key used which holds the raw bytes used in key scheduling 52 type Key: AesKey; 53 54 /// Creates a new cipher from the AesKey new(key: &Self::Key) -> Self55 fn new(key: &Self::Key) -> Self; 56 } 57 58 /// An AES cipher used for encrypting blocks 59 pub trait AesEncryptCipher: AesCipher { 60 /// Encrypt `block` in place. encrypt(&self, block: &mut AesBlock)61 fn encrypt(&self, block: &mut AesBlock); 62 } 63 64 /// An AES cipher used for decrypting blocks 65 pub trait AesDecryptCipher: AesCipher { 66 /// Decrypt `block` in place. decrypt(&self, block: &mut AesBlock)67 fn decrypt(&self, block: &mut AesBlock); 68 } 69 70 /// An appropriately sized `[u8; N]` array that the key can be constructed from, e.g. `[u8; 16]` 71 /// for AES-128. 72 pub trait AesKey: for<'a> TryFrom<&'a [u8], Error = Self::TryFromError> { 73 /// The error used by the `TryFrom` implementation used to construct `Self::Array` from a 74 /// slice. For the typical case of `Self::Array` being an `[u8; N]`, this would be 75 /// `core::array::TryFromSliceError`. 76 /// 77 /// This is broken out as a separate type to allow the `fmt::Debug` requirement needed for 78 /// `expect()`. 79 type TryFromError: fmt::Debug; 80 81 /// The byte array type the key can be represented with 82 type Array; 83 84 /// Key size in bytes -- must match the length of `Self::KeyBytes`.` 85 /// 86 /// Unfortunately `KeyBytes` can't reference this const in the type declaration, so it must be 87 /// specified separately. 88 const KEY_SIZE: usize; 89 90 /// Returns the key material as a slice as_slice(&self) -> &[u8]91 fn as_slice(&self) -> &[u8]; 92 93 /// Returns the key material as an array as_array(&self) -> &Self::Array94 fn as_array(&self) -> &Self::Array; 95 } 96 97 /// An AES-128 key. 98 #[derive(Clone)] 99 pub struct Aes128Key { 100 key: [u8; 16], 101 } 102 103 impl AesKey for Aes128Key { 104 type TryFromError = array::TryFromSliceError; 105 type Array = [u8; 16]; 106 const KEY_SIZE: usize = 16; 107 as_slice(&self) -> &[u8]108 fn as_slice(&self) -> &[u8] { 109 &self.key 110 } 111 as_array(&self) -> &Self::Array112 fn as_array(&self) -> &Self::Array { 113 &self.key 114 } 115 } 116 117 impl TryFrom<&[u8]> for Aes128Key { 118 type Error = array::TryFromSliceError; 119 try_from(value: &[u8]) -> Result<Self, Self::Error>120 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 121 value.try_into().map(|arr| Self { key: arr }) 122 } 123 } 124 125 impl From<[u8; 16]> for Aes128Key { from(arr: [u8; 16]) -> Self126 fn from(arr: [u8; 16]) -> Self { 127 Self { key: arr } 128 } 129 } 130 131 /// An AES-256 key. 132 #[derive(Clone)] 133 pub struct Aes256Key { 134 key: [u8; 32], 135 } 136 137 impl AesKey for Aes256Key { 138 type TryFromError = array::TryFromSliceError; 139 type Array = [u8; 32]; 140 const KEY_SIZE: usize = 32; 141 as_slice(&self) -> &[u8]142 fn as_slice(&self) -> &[u8] { 143 &self.key 144 } 145 as_array(&self) -> &Self::Array146 fn as_array(&self) -> &Self::Array { 147 &self.key 148 } 149 } 150 151 impl TryFrom<&[u8]> for Aes256Key { 152 type Error = array::TryFromSliceError; 153 try_from(value: &[u8]) -> Result<Self, Self::Error>154 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 155 value.try_into().map(|arr| Self { key: arr }) 156 } 157 } 158 159 impl From<[u8; 32]> for Aes256Key { from(arr: [u8; 32]) -> Self160 fn from(arr: [u8; 32]) -> Self { 161 Self { key: arr } 162 } 163 } 164 165 /// Module for testing implementations of this crate. 166 #[cfg(feature = "testing")] 167 pub mod testing { 168 use super::*; 169 pub use crate::testing::prelude::*; 170 use core::marker; 171 use hex_literal::hex; 172 use rstest_reuse::template; 173 174 /// Test encryption with AES-128 aes_128_test_encrypt<A: AesEncryptCipher<Key = Aes128Key>>( _marker: marker::PhantomData<A>, )175 pub fn aes_128_test_encrypt<A: AesEncryptCipher<Key = Aes128Key>>( 176 _marker: marker::PhantomData<A>, 177 ) { 178 // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.1 179 let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into(); 180 let mut block = [0_u8; 16]; 181 let enc_cipher = A::new(&key); 182 183 block.copy_from_slice(&hex!("6bc1bee22e409f96e93d7e117393172a")); 184 enc_cipher.encrypt(&mut block); 185 assert_eq!(hex!("3ad77bb40d7a3660a89ecaf32466ef97"), block); 186 187 block.copy_from_slice(&hex!("ae2d8a571e03ac9c9eb76fac45af8e51")); 188 enc_cipher.encrypt(&mut block); 189 assert_eq!(hex!("f5d3d58503b9699de785895a96fdbaaf"), block); 190 191 block.copy_from_slice(&hex!("30c81c46a35ce411e5fbc1191a0a52ef")); 192 enc_cipher.encrypt(&mut block); 193 assert_eq!(hex!("43b1cd7f598ece23881b00e3ed030688"), block); 194 195 block.copy_from_slice(&hex!("f69f2445df4f9b17ad2b417be66c3710")); 196 enc_cipher.encrypt(&mut block); 197 assert_eq!(hex!("7b0c785e27e8ad3f8223207104725dd4"), block); 198 } 199 200 /// Test decryption with AES-128 aes_128_test_decrypt<A: AesDecryptCipher<Key = Aes128Key>>( _marker: marker::PhantomData<A>, )201 pub fn aes_128_test_decrypt<A: AesDecryptCipher<Key = Aes128Key>>( 202 _marker: marker::PhantomData<A>, 203 ) { 204 // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.2 205 let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into(); 206 let mut block = [0_u8; 16]; 207 let dec_cipher = A::new(&key); 208 209 block.copy_from_slice(&hex!("3ad77bb40d7a3660a89ecaf32466ef97")); 210 dec_cipher.decrypt(&mut block); 211 assert_eq!(hex!("6bc1bee22e409f96e93d7e117393172a"), block); 212 213 block.copy_from_slice(&hex!("f5d3d58503b9699de785895a96fdbaaf")); 214 dec_cipher.decrypt(&mut block); 215 assert_eq!(hex!("ae2d8a571e03ac9c9eb76fac45af8e51"), block); 216 217 block.copy_from_slice(&hex!("43b1cd7f598ece23881b00e3ed030688")); 218 dec_cipher.decrypt(&mut block); 219 assert_eq!(hex!("30c81c46a35ce411e5fbc1191a0a52ef"), block); 220 221 block.copy_from_slice(&hex!("7b0c785e27e8ad3f8223207104725dd4")); 222 dec_cipher.decrypt(&mut block); 223 assert_eq!(hex!("f69f2445df4f9b17ad2b417be66c3710"), block); 224 } 225 226 /// Test encryption with AES-256 aes_256_test_encrypt<A: AesEncryptCipher<Key = Aes256Key>>( _marker: marker::PhantomData<A>, )227 pub fn aes_256_test_encrypt<A: AesEncryptCipher<Key = Aes256Key>>( 228 _marker: marker::PhantomData<A>, 229 ) { 230 // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.5 231 let key: Aes256Key = 232 hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into(); 233 let mut block: [u8; 16]; 234 let enc_cipher = A::new(&key); 235 236 block = hex!("6bc1bee22e409f96e93d7e117393172a"); 237 enc_cipher.encrypt(&mut block); 238 assert_eq!(hex!("f3eed1bdb5d2a03c064b5a7e3db181f8"), block); 239 240 block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51"); 241 enc_cipher.encrypt(&mut block); 242 assert_eq!(hex!("591ccb10d410ed26dc5ba74a31362870"), block); 243 244 block = hex!("30c81c46a35ce411e5fbc1191a0a52ef"); 245 enc_cipher.encrypt(&mut block); 246 assert_eq!(hex!("b6ed21b99ca6f4f9f153e7b1beafed1d"), block); 247 248 block = hex!("f69f2445df4f9b17ad2b417be66c3710"); 249 enc_cipher.encrypt(&mut block); 250 assert_eq!(hex!("23304b7a39f9f3ff067d8d8f9e24ecc7"), block); 251 } 252 253 /// Test decryption with AES-256 aes_256_test_decrypt<A: AesDecryptCipher<Key = Aes256Key>>( _marker: marker::PhantomData<A>, )254 pub fn aes_256_test_decrypt<A: AesDecryptCipher<Key = Aes256Key>>( 255 _marker: marker::PhantomData<A>, 256 ) { 257 // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.6 258 let key: Aes256Key = 259 hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into(); 260 let mut block: [u8; 16]; 261 let dec_cipher = A::new(&key); 262 263 block = hex!("f3eed1bdb5d2a03c064b5a7e3db181f8"); 264 dec_cipher.decrypt(&mut block); 265 assert_eq!(hex!("6bc1bee22e409f96e93d7e117393172a"), block); 266 267 block = hex!("591ccb10d410ed26dc5ba74a31362870"); 268 dec_cipher.decrypt(&mut block); 269 assert_eq!(hex!("ae2d8a571e03ac9c9eb76fac45af8e51"), block); 270 271 block = hex!("b6ed21b99ca6f4f9f153e7b1beafed1d"); 272 dec_cipher.decrypt(&mut block); 273 assert_eq!(hex!("30c81c46a35ce411e5fbc1191a0a52ef"), block); 274 275 block = hex!("23304b7a39f9f3ff067d8d8f9e24ecc7"); 276 dec_cipher.decrypt(&mut block); 277 assert_eq!(hex!("f69f2445df4f9b17ad2b417be66c3710"), block); 278 } 279 280 /// Generates the test cases to validate the AES-128 implementation. 281 /// For example, to test `MyAes128Impl`: 282 /// 283 /// ``` 284 /// use crypto_provider::aes::testing::*; 285 /// 286 /// mod tests { 287 /// #[apply(aes_128_encrypt_test_cases)] 288 /// fn aes_128_tests(f: CryptoProviderTestCase<MyAes128Impl>) { 289 /// f(MyAes128Impl); 290 /// } 291 /// } 292 /// ``` 293 #[template] 294 #[export] 295 #[rstest] 296 #[case::encrypt(aes_128_test_encrypt)] aes_128_encrypt_test_cases<A: AesFactory<Key = Aes128Key>>( #[case] testcase: CryptoProviderTestCase<F>, )297 fn aes_128_encrypt_test_cases<A: AesFactory<Key = Aes128Key>>( 298 #[case] testcase: CryptoProviderTestCase<F>, 299 ) { 300 } 301 302 /// Generates the test cases to validate the AES-128 implementation. 303 /// For example, to test `MyAes128Impl`: 304 /// 305 /// ``` 306 /// use crypto_provider::aes::testing::*; 307 /// 308 /// mod tests { 309 /// #[apply(aes_128_decrypt_test_cases)] 310 /// fn aes_128_tests(f: CryptoProviderTestCase<MyAes128Impl>) { 311 /// f(MyAes128Impl); 312 /// } 313 /// } 314 /// ``` 315 #[template] 316 #[export] 317 #[rstest] 318 #[case::decrypt(aes_128_test_decrypt)] aes_128_decrypt_test_cases<F: AesFactory<Key = Aes128Key>>( #[case] testcase: CryptoProviderTestCase<F>, )319 fn aes_128_decrypt_test_cases<F: AesFactory<Key = Aes128Key>>( 320 #[case] testcase: CryptoProviderTestCase<F>, 321 ) { 322 } 323 324 /// Generates the test cases to validate the AES-256 implementation. 325 /// For example, to test `MyAes256Impl`: 326 /// 327 /// ``` 328 /// use crypto_provider::aes::testing::*; 329 /// 330 /// mod tests { 331 /// #[apply(aes_256_encrypt_test_cases)] 332 /// fn aes_256_tests(f: CryptoProviderTestCase<MyAes256Impl>) { 333 /// f(MyAes256Impl); 334 /// } 335 /// } 336 /// ``` 337 #[template] 338 #[export] 339 #[rstest] 340 #[case::encrypt(aes_256_test_encrypt)] aes_256_encrypt_test_cases<F: AesFactory<Key = Aes256Key>>( #[case] testcase: CryptoProviderTestCase<F>, )341 fn aes_256_encrypt_test_cases<F: AesFactory<Key = Aes256Key>>( 342 #[case] testcase: CryptoProviderTestCase<F>, 343 ) { 344 } 345 346 /// Generates the test cases to validate the AES-256 implementation. 347 /// For example, to test `MyAes256Impl`: 348 /// 349 /// ``` 350 /// use crypto_provider::aes::testing::*; 351 /// 352 /// mod tests { 353 /// #[apply(aes_256_decrypt_test_cases)] 354 /// fn aes_256_tests(f: CryptoProviderTestCase<MyAes256Impl>) { 355 /// f(MyAes256Impl); 356 /// } 357 /// } 358 /// ``` 359 #[template] 360 #[export] 361 #[rstest] 362 #[case::decrypt(aes_256_test_decrypt)] aes_256_decrypt_test_cases<F: AesFactory<Key = Aes256Key>>( #[case] testcase: CryptoProviderTestCase<F>, )363 fn aes_256_decrypt_test_cases<F: AesFactory<Key = Aes256Key>>( 364 #[case] testcase: CryptoProviderTestCase<F>, 365 ) { 366 } 367 } 368