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. boringSSL and other C impls). 19 use core::{array, fmt}; 20 21 pub mod ctr; 22 23 pub mod cbc; 24 25 /// Block size in bytes for AES (and XTS-AES) 26 pub const BLOCK_SIZE: usize = 16; 27 28 /// A single AES block. 29 pub type AesBlock = [u8; BLOCK_SIZE]; 30 31 /// Helper trait to enforce encryption and decryption with the same size key 32 pub trait Aes { 33 /// The AES key containing the raw bytes used to for key scheduling 34 type Key: AesKey; 35 36 /// The cipher used for encryption 37 type EncryptCipher: AesEncryptCipher<Key = Self::Key>; 38 39 /// the cipher used for decryption 40 type DecryptCipher: AesDecryptCipher<Key = Self::Key>; 41 } 42 43 /// The base AesCipher trait which describes common operations to both encryption and decryption ciphers 44 pub trait AesCipher { 45 /// The type of the key used which holds the raw bytes used in key scheduling 46 type Key: AesKey; 47 48 /// Creates a new cipher from the AesKey new(key: &Self::Key) -> Self49 fn new(key: &Self::Key) -> Self; 50 } 51 52 /// An AES cipher used for encrypting blocks 53 pub trait AesEncryptCipher: AesCipher { 54 /// Encrypt `block` in place. encrypt(&self, block: &mut AesBlock)55 fn encrypt(&self, block: &mut AesBlock); 56 } 57 58 /// An AES cipher used for decrypting blocks 59 pub trait AesDecryptCipher: AesCipher { 60 /// Decrypt `block` in place. decrypt(&self, block: &mut AesBlock)61 fn decrypt(&self, block: &mut AesBlock); 62 } 63 64 /// An appropriately sized `[u8; N]` array that the key can be constructed from, e.g. `[u8; 16]` 65 /// for AES-128. 66 pub trait AesKey: for<'a> TryFrom<&'a [u8], Error = Self::TryFromError> { 67 /// The error used by the `TryFrom` implementation used to construct `Self::Array` from a 68 /// slice. For the typical case of `Self::Array` being an `[u8; N]`, this would be 69 /// `core::array::TryFromSliceError`. 70 /// 71 /// This is broken out as a separate type to allow the `fmt::Debug` requirement needed for 72 /// `expect()`. 73 type TryFromError: fmt::Debug; 74 75 /// The byte array type the key can be represented with 76 type Array; 77 78 /// Key size in bytes -- must match the length of `Self::KeyBytes`.` 79 /// 80 /// Unfortunately `KeyBytes` can't reference this const in the type declaration, so it must be 81 /// specified separately. 82 const KEY_SIZE: usize; 83 84 /// Returns the key material as a slice as_slice(&self) -> &[u8]85 fn as_slice(&self) -> &[u8]; 86 87 /// Returns the key material as an array as_array(&self) -> &Self::Array88 fn as_array(&self) -> &Self::Array; 89 } 90 91 /// An AES-128 key. 92 #[derive(Clone)] 93 pub struct Aes128Key { 94 key: [u8; 16], 95 } 96 97 impl AesKey for Aes128Key { 98 type TryFromError = array::TryFromSliceError; 99 type Array = [u8; 16]; 100 const KEY_SIZE: usize = 16; 101 as_slice(&self) -> &[u8]102 fn as_slice(&self) -> &[u8] { 103 &self.key 104 } 105 as_array(&self) -> &Self::Array106 fn as_array(&self) -> &Self::Array { 107 &self.key 108 } 109 } 110 111 impl TryFrom<&[u8]> for Aes128Key { 112 type Error = array::TryFromSliceError; 113 try_from(value: &[u8]) -> Result<Self, Self::Error>114 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 115 value.try_into().map(|arr| Self { key: arr }) 116 } 117 } 118 119 impl From<[u8; 16]> for Aes128Key { from(arr: [u8; 16]) -> Self120 fn from(arr: [u8; 16]) -> Self { 121 Self { key: arr } 122 } 123 } 124 125 /// An AES-256 key. 126 #[derive(Clone)] 127 pub struct Aes256Key { 128 key: [u8; 32], 129 } 130 131 impl AesKey for Aes256Key { 132 type TryFromError = array::TryFromSliceError; 133 type Array = [u8; 32]; 134 const KEY_SIZE: usize = 32; 135 as_slice(&self) -> &[u8]136 fn as_slice(&self) -> &[u8] { 137 &self.key 138 } 139 as_array(&self) -> &Self::Array140 fn as_array(&self) -> &Self::Array { 141 &self.key 142 } 143 } 144 145 impl TryFrom<&[u8]> for Aes256Key { 146 type Error = array::TryFromSliceError; 147 try_from(value: &[u8]) -> Result<Self, Self::Error>148 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 149 value.try_into().map(|arr| Self { key: arr }) 150 } 151 } 152 153 impl From<[u8; 32]> for Aes256Key { from(arr: [u8; 32]) -> Self154 fn from(arr: [u8; 32]) -> Self { 155 Self { key: arr } 156 } 157 } 158