aes/
soft.rs

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);