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