1//! AES block ciphers implementation using AES-NI instruction set.
2//!
3//! Ciphers functionality is accessed using `BlockCipher` trait from the
4//! [`cipher`](https://docs.rs/cipher) crate.
5//!
6//! # Vulnerability
7//! Lazy FP state restory vulnerability can allow local process to leak content
8//! of the FPU register, in which round keys are stored. This vulnerability
9//! can be mitigated at the operating system level by installing relevant
10//! patches. (i.e. keep your OS updated!) More info:
11//! - [Intel advisory](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00145.html)
12//! - [Wikipedia](https://en.wikipedia.org/wiki/Lazy_FP_state_restore)
13//!
14//! # Related documents
15//! - [Intel AES-NI whitepaper](https://software.intel.com/sites/default/files/article/165683/aes-wp-2012-09-22-v01.pdf)
16//! - [Use of the AES Instruction Set](https://www.cosic.esat.kuleuven.be/ecrypt/AESday/slides/Use_of_the_AES_Instruction_Set.pdf)
17
18#[macro_use]
19mod utils;
20
21mod aes128;
22mod aes192;
23mod aes256;
24
25#[cfg(test)]
26mod test_expand;
27
28#[cfg(feature = "hazmat")]
29pub(crate) mod hazmat;
30
31#[cfg(target_arch = "x86")]
32use core::arch::x86 as arch;
33#[cfg(target_arch = "x86_64")]
34use core::arch::x86_64 as arch;
35
36use crate::{Block, Block8};
37use cipher::{
38 consts::{U16, U24, U32, U8},
39 inout::InOut,
40 AlgorithmName, BlockBackend, BlockCipher, BlockClosure, BlockDecrypt, BlockEncrypt,
41 BlockSizeUser, Key, KeyInit, KeySizeUser, ParBlocksSizeUser,
42};
43use core::fmt;
44
45macro_rules! define_aes_impl {
46 (
47 $name:tt,
48 $name_enc:ident,
49 $name_dec:ident,
50 $name_back_enc:ident,
51 $name_back_dec:ident,
52 $module:tt,
53 $key_size:ty,
54 $doc:expr $(,)?
55 ) => {
56 #[doc=$doc]
57 #[doc = "block cipher"]
58 #[derive(Clone)]
59 pub struct $name {
60 encrypt: $name_enc,
61 decrypt: $name_dec,
62 }
63
64 impl $name {
65 #[inline(always)]
66 pub(crate) fn get_enc_backend(&self) -> $name_back_enc<'_> {
67 self.encrypt.get_enc_backend()
68 }
69
70 #[inline(always)]
71 pub(crate) fn get_dec_backend(&self) -> $name_back_dec<'_> {
72 self.decrypt.get_dec_backend()
73 }
74 }
75
76 impl BlockCipher for $name {}
77
78 impl KeySizeUser for $name {
79 type KeySize = $key_size;
80 }
81
82 impl KeyInit for $name {
83 #[inline]
84 fn new(key: &Key<Self>) -> Self {
85 let encrypt = $name_enc::new(key);
86 let decrypt = $name_dec::from(&encrypt);
87 Self { encrypt, decrypt }
88 }
89 }
90
91 impl From<$name_enc> for $name {
92 #[inline]
93 fn from(encrypt: $name_enc) -> $name {
94 let decrypt = (&encrypt).into();
95 Self { encrypt, decrypt }
96 }
97 }
98
99 impl From<&$name_enc> for $name {
100 #[inline]
101 fn from(encrypt: &$name_enc) -> $name {
102 let decrypt = encrypt.into();
103 let encrypt = encrypt.clone();
104 Self { encrypt, decrypt }
105 }
106 }
107
108 impl BlockSizeUser for $name {
109 type BlockSize = U16;
110 }
111
112 impl BlockEncrypt for $name {
113 fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
114 self.encrypt.encrypt_with_backend(f)
115 }
116 }
117
118 impl BlockDecrypt for $name {
119 fn decrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
120 self.decrypt.decrypt_with_backend(f)
121 }
122 }
123
124 impl fmt::Debug for $name {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
126 f.write_str(concat!(stringify!($name), " { .. }"))
127 }
128 }
129
130 impl AlgorithmName for $name {
131 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.write_str(stringify!($name))
133 }
134 }
135
136 #[cfg(feature = "zeroize")]
137 impl zeroize::ZeroizeOnDrop for $name {}
138
139 #[doc=$doc]
140 #[doc = "block cipher (encrypt-only)"]
141 #[derive(Clone)]
142 pub struct $name_enc {
143 round_keys: $module::RoundKeys,
144 }
145
146 impl $name_enc {
147 #[inline(always)]
148 pub(crate) fn get_enc_backend(&self) -> $name_back_enc<'_> {
149 $name_back_enc(self)
150 }
151 }
152
153 impl BlockCipher for $name_enc {}
154
155 impl KeySizeUser for $name_enc {
156 type KeySize = $key_size;
157 }
158
159 impl KeyInit for $name_enc {
160 fn new(key: &Key<Self>) -> Self {
161 // SAFETY: we enforce that this code is called only when
162 // target features required by `expand` were properly checked.
163 Self {
164 round_keys: unsafe { $module::expand_key(key.as_ref()) },
165 }
166 }
167 }
168
169 impl BlockSizeUser for $name_enc {
170 type BlockSize = U16;
171 }
172
173 impl BlockEncrypt for $name_enc {
174 fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
175 f.call(&mut self.get_enc_backend())
176 }
177 }
178
179 impl fmt::Debug for $name_enc {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
181 f.write_str(concat!(stringify!($name_enc), " { .. }"))
182 }
183 }
184
185 impl AlgorithmName for $name_enc {
186 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 f.write_str(stringify!($name_enc))
188 }
189 }
190
191 impl Drop for $name_enc {
192 #[inline]
193 fn drop(&mut self) {
194 #[cfg(feature = "zeroize")]
195 zeroize::Zeroize::zeroize(&mut self.round_keys);
196 }
197 }
198
199 #[cfg(feature = "zeroize")]
200 impl zeroize::ZeroizeOnDrop for $name_enc {}
201
202 #[doc=$doc]
203 #[doc = "block cipher (decrypt-only)"]
204 #[derive(Clone)]
205 pub struct $name_dec {
206 round_keys: $module::RoundKeys,
207 }
208
209 impl $name_dec {
210 #[inline(always)]
211 pub(crate) fn get_dec_backend(&self) -> $name_back_dec<'_> {
212 $name_back_dec(self)
213 }
214 }
215
216 impl BlockCipher for $name_dec {}
217
218 impl KeySizeUser for $name_dec {
219 type KeySize = $key_size;
220 }
221
222 impl KeyInit for $name_dec {
223 fn new(key: &Key<Self>) -> Self {
224 $name_enc::new(key).into()
225 }
226 }
227
228 impl From<$name_enc> for $name_dec {
229 #[inline]
230 fn from(enc: $name_enc) -> $name_dec {
231 Self::from(&enc)
232 }
233 }
234
235 impl From<&$name_enc> for $name_dec {
236 #[inline]
237 fn from(enc: &$name_enc) -> $name_dec {
238 let round_keys = unsafe { $module::inv_expanded_keys(&enc.round_keys) };
239 Self { round_keys }
240 }
241 }
242
243 impl BlockSizeUser for $name_dec {
244 type BlockSize = U16;
245 }
246
247 impl BlockDecrypt for $name_dec {
248 fn decrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
249 f.call(&mut self.get_dec_backend());
250 }
251 }
252
253 impl fmt::Debug for $name_dec {
254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
255 f.write_str(concat!(stringify!($name_dec), " { .. }"))
256 }
257 }
258
259 impl AlgorithmName for $name_dec {
260 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 f.write_str(stringify!($name_dec))
262 }
263 }
264
265 impl Drop for $name_dec {
266 #[inline]
267 fn drop(&mut self) {
268 #[cfg(feature = "zeroize")]
269 zeroize::Zeroize::zeroize(&mut self.round_keys);
270 }
271 }
272
273 #[cfg(feature = "zeroize")]
274 impl zeroize::ZeroizeOnDrop for $name_dec {}
275
276 pub(crate) struct $name_back_enc<'a>(&'a $name_enc);
277
278 impl<'a> BlockSizeUser for $name_back_enc<'a> {
279 type BlockSize = U16;
280 }
281
282 impl<'a> ParBlocksSizeUser for $name_back_enc<'a> {
283 type ParBlocksSize = U8;
284 }
285
286 impl<'a> BlockBackend for $name_back_enc<'a> {
287 #[inline(always)]
288 fn proc_block(&mut self, block: InOut<'_, '_, Block>) {
289 unsafe {
290 $module::encrypt1(&self.0.round_keys, block);
291 }
292 }
293
294 #[inline(always)]
295 fn proc_par_blocks(&mut self, blocks: InOut<'_, '_, Block8>) {
296 unsafe {
297 $module::encrypt8(&self.0.round_keys, blocks);
298 }
299 }
300 }
301
302 pub(crate) struct $name_back_dec<'a>(&'a $name_dec);
303
304 impl<'a> BlockSizeUser for $name_back_dec<'a> {
305 type BlockSize = U16;
306 }
307
308 impl<'a> ParBlocksSizeUser for $name_back_dec<'a> {
309 type ParBlocksSize = U8;
310 }
311
312 impl<'a> BlockBackend for $name_back_dec<'a> {
313 #[inline(always)]
314 fn proc_block(&mut self, block: InOut<'_, '_, Block>) {
315 unsafe {
316 $module::decrypt1(&self.0.round_keys, block);
317 }
318 }
319
320 #[inline(always)]
321 fn proc_par_blocks(&mut self, blocks: InOut<'_, '_, Block8>) {
322 unsafe {
323 $module::decrypt8(&self.0.round_keys, blocks);
324 }
325 }
326 }
327 };
328}
329
330define_aes_impl!(
331 Aes128,
332 Aes128Enc,
333 Aes128Dec,
334 Aes128BackEnc,
335 Aes128BackDec,
336 aes128,
337 U16,
338 "AES-128",
339);
340
341define_aes_impl!(
342 Aes192,
343 Aes192Enc,
344 Aes192Dec,
345 Aes192BackEnc,
346 Aes192BackDec,
347 aes192,
348 U24,
349 "AES-192",
350);
351
352define_aes_impl!(
353 Aes256,
354 Aes256Enc,
355 Aes256Dec,
356 Aes256BackEnc,
357 Aes256BackDec,
358 aes256,
359 U32,
360 "AES-256",
361);
362