1//! AES block cipher constant-time implementation.
2//!
3//! The implementation uses a technique called [fixslicing][1], an improved
4//! form of bitslicing which represents ciphers in a way which enables
5//! very efficient constant-time implementations in software.
6//!
7//! [1]: https://eprint.iacr.org/2020/1123.pdf
8
9#![deny(unsafe_code)]
10
11#[cfg_attr(not(target_pointer_width = "64"), path = "soft/fixslice32.rs")]
12#[cfg_attr(target_pointer_width = "64", path = "soft/fixslice64.rs")]
13pub(crate) mod fixslice;
14
15use crate::Block;
16use cipher::{
17 consts::{U16, U24, U32},
18 inout::InOut,
19 AlgorithmName, BlockBackend, BlockCipher, BlockClosure, BlockDecrypt, BlockEncrypt,
20 BlockSizeUser, Key, KeyInit, KeySizeUser, ParBlocksSizeUser,
21};
22use core::fmt;
23use fixslice::{BatchBlocks, FixsliceBlocks, FixsliceKeys128, FixsliceKeys192, FixsliceKeys256};
24
25macro_rules! define_aes_impl {
26 (
27 $name:tt,
28 $name_enc:ident,
29 $name_dec:ident,
30 $name_back_enc:ident,
31 $name_back_dec:ident,
32 $key_size:ty,
33 $fixslice_keys:ty,
34 $fixslice_key_schedule:path,
35 $fixslice_decrypt:path,
36 $fixslice_encrypt:path,
37 $doc:expr $(,)?
38 ) => {
39 #[doc=$doc]
40 #[doc = "block cipher"]
41 #[derive(Clone)]
42 pub struct $name {
43 keys: $fixslice_keys,
44 }
45
46 impl $name {
47 #[inline(always)]
48 pub(crate) fn get_enc_backend(&self) -> $name_back_enc<'_> {
49 $name_back_enc(self)
50 }
51
52 #[inline(always)]
53 pub(crate) fn get_dec_backend(&self) -> $name_back_dec<'_> {
54 $name_back_dec(self)
55 }
56 }
57
58 impl KeySizeUser for $name {
59 type KeySize = $key_size;
60 }
61
62 impl KeyInit for $name {
63 #[inline]
64 fn new(key: &Key<Self>) -> Self {
65 Self {
66 keys: $fixslice_key_schedule(key.as_ref()),
67 }
68 }
69 }
70
71 impl BlockSizeUser for $name {
72 type BlockSize = U16;
73 }
74
75 impl BlockCipher for $name {}
76
77 impl BlockEncrypt for $name {
78 fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
79 f.call(&mut self.get_enc_backend())
80 }
81 }
82
83 impl BlockDecrypt for $name {
84 fn decrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
85 f.call(&mut self.get_dec_backend())
86 }
87 }
88
89 impl From<$name_enc> for $name {
90 #[inline]
91 fn from(enc: $name_enc) -> $name {
92 enc.inner
93 }
94 }
95
96 impl From<&$name_enc> for $name {
97 #[inline]
98 fn from(enc: &$name_enc) -> $name {
99 enc.inner.clone()
100 }
101 }
102
103 impl fmt::Debug for $name {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
105 f.write_str(concat!(stringify!($name), " { .. }"))
106 }
107 }
108
109 impl AlgorithmName for $name {
110 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 f.write_str(stringify!($name))
112 }
113 }
114
115 impl Drop for $name {
116 #[inline]
117 fn drop(&mut self) {
118 #[cfg(feature = "zeroize")]
119 zeroize::Zeroize::zeroize(&mut self.keys);
120 }
121 }
122
123 #[cfg(feature = "zeroize")]
124 impl zeroize::ZeroizeOnDrop for $name {}
125
126 #[doc=$doc]
127 #[doc = "block cipher (encrypt-only)"]
128 #[derive(Clone)]
129 pub struct $name_enc {
130 inner: $name,
131 }
132
133 impl $name_enc {
134 #[inline(always)]
135 pub(crate) fn get_enc_backend(&self) -> $name_back_enc<'_> {
136 self.inner.get_enc_backend()
137 }
138 }
139
140 impl BlockCipher for $name_enc {}
141
142 impl KeySizeUser for $name_enc {
143 type KeySize = $key_size;
144 }
145
146 impl KeyInit for $name_enc {
147 #[inline(always)]
148 fn new(key: &Key<Self>) -> Self {
149 let inner = $name::new(key);
150 Self { inner }
151 }
152 }
153
154 impl BlockSizeUser for $name_enc {
155 type BlockSize = U16;
156 }
157
158 impl BlockEncrypt for $name_enc {
159 fn encrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
160 f.call(&mut self.get_enc_backend())
161 }
162 }
163
164 impl fmt::Debug for $name_enc {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
166 f.write_str(concat!(stringify!($name_enc), " { .. }"))
167 }
168 }
169
170 impl AlgorithmName for $name_enc {
171 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 f.write_str(stringify!($name_enc))
173 }
174 }
175
176 #[cfg(feature = "zeroize")]
177 impl zeroize::ZeroizeOnDrop for $name_enc {}
178
179 #[doc=$doc]
180 #[doc = "block cipher (decrypt-only)"]
181 #[derive(Clone)]
182 pub struct $name_dec {
183 inner: $name,
184 }
185
186 impl $name_dec {
187 #[inline(always)]
188 pub(crate) fn get_dec_backend(&self) -> $name_back_dec<'_> {
189 self.inner.get_dec_backend()
190 }
191 }
192
193 impl BlockCipher for $name_dec {}
194
195 impl KeySizeUser for $name_dec {
196 type KeySize = $key_size;
197 }
198
199 impl KeyInit for $name_dec {
200 #[inline(always)]
201 fn new(key: &Key<Self>) -> Self {
202 let inner = $name::new(key);
203 Self { inner }
204 }
205 }
206
207 impl From<$name_enc> for $name_dec {
208 #[inline]
209 fn from(enc: $name_enc) -> $name_dec {
210 Self { inner: enc.inner }
211 }
212 }
213
214 impl From<&$name_enc> for $name_dec {
215 #[inline]
216 fn from(enc: &$name_enc) -> $name_dec {
217 Self {
218 inner: enc.inner.clone(),
219 }
220 }
221 }
222
223 impl BlockSizeUser for $name_dec {
224 type BlockSize = U16;
225 }
226
227 impl BlockDecrypt for $name_dec {
228 fn decrypt_with_backend(&self, f: impl BlockClosure<BlockSize = U16>) {
229 f.call(&mut self.get_dec_backend());
230 }
231 }
232
233 impl fmt::Debug for $name_dec {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
235 f.write_str(concat!(stringify!($name_dec), " { .. }"))
236 }
237 }
238
239 impl AlgorithmName for $name_dec {
240 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 f.write_str(stringify!($name_dec))
242 }
243 }
244
245 #[cfg(feature = "zeroize")]
246 impl zeroize::ZeroizeOnDrop for $name_dec {}
247
248 pub(crate) struct $name_back_enc<'a>(&'a $name);
249
250 impl<'a> BlockSizeUser for $name_back_enc<'a> {
251 type BlockSize = U16;
252 }
253
254 impl<'a> ParBlocksSizeUser for $name_back_enc<'a> {
255 type ParBlocksSize = FixsliceBlocks;
256 }
257
258 impl<'a> BlockBackend for $name_back_enc<'a> {
259 #[inline(always)]
260 fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) {
261 let mut blocks = BatchBlocks::default();
262 blocks[0] = block.clone_in().into();
263 let res = $fixslice_encrypt(&self.0.keys, &blocks);
264 *block.get_out() = res[0].into();
265 }
266
267 #[inline(always)]
268 fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, BatchBlocks>) {
269 let res = $fixslice_encrypt(&self.0.keys, blocks.get_in());
270 *blocks.get_out() = res;
271 }
272 }
273
274 pub(crate) struct $name_back_dec<'a>(&'a $name);
275
276 impl<'a> BlockSizeUser for $name_back_dec<'a> {
277 type BlockSize = U16;
278 }
279
280 impl<'a> ParBlocksSizeUser for $name_back_dec<'a> {
281 type ParBlocksSize = FixsliceBlocks;
282 }
283
284 impl<'a> BlockBackend for $name_back_dec<'a> {
285 #[inline(always)]
286 fn proc_block(&mut self, mut block: InOut<'_, '_, Block>) {
287 let mut blocks = BatchBlocks::default();
288 blocks[0] = block.clone_in();
289 let res = $fixslice_decrypt(&self.0.keys, &blocks);
290 *block.get_out() = res[0];
291 }
292
293 #[inline(always)]
294 fn proc_par_blocks(&mut self, mut blocks: InOut<'_, '_, BatchBlocks>) {
295 let res = $fixslice_decrypt(&self.0.keys, blocks.get_in());
296 *blocks.get_out() = res;
297 }
298 }
299 };
300}
301
302define_aes_impl!(
303 Aes128,
304 Aes128Enc,
305 Aes128Dec,
306 Aes128BackEnc,
307 Aes128BackDec,
308 U16,
309 FixsliceKeys128,
310 fixslice::aes128_key_schedule,
311 fixslice::aes128_decrypt,
312 fixslice::aes128_encrypt,
313 "AES-128",
314);
315
316define_aes_impl!(
317 Aes192,
318 Aes192Enc,
319 Aes192Dec,
320 Aes192BackEnc,
321 Aes192BackDec,
322 U24,
323 FixsliceKeys192,
324 fixslice::aes192_key_schedule,
325 fixslice::aes192_decrypt,
326 fixslice::aes192_encrypt,
327 "AES-192",
328);
329
330define_aes_impl!(
331 Aes256,
332 Aes256Enc,
333 Aes256Dec,
334 Aes256BackEnc,
335 Aes256BackDec,
336 U32,
337 FixsliceKeys256,
338 fixslice::aes256_key_schedule,
339 fixslice::aes256_decrypt,
340 fixslice::aes256_encrypt,
341 "AES-256",
342);
343