Skip to main content

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