1use crate::soft;
5use cipher::{
6 AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure,
7 BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser,
8 consts::{U16, U24, U32},
9};
10use core::fmt;
11use core::mem::ManuallyDrop;
12
13#[cfg(target_arch = "aarch64")]
14use crate::armv8 as arch;
15
16#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
17use crate::x86 as arch;
18
19macro_rules! define_aes_impl {
20 (
21 name = $name:ident,
22 name_enc = $name_enc:ident,
23 name_dec = $name_dec:ident,
24 module = $module:tt,
25 key_size = $key_size:ty,
26 doc = $doc:expr,
27 ) => {
28 mod $module {
29 use super::{arch, soft};
30 use core::mem::ManuallyDrop;
31
32 pub(super) union Inner {
33 pub(super) arch: ManuallyDrop<arch::$name>,
34 pub(super) soft: ManuallyDrop<soft::$name>,
35 }
36
37 pub(super) union InnerEnc {
38 pub(super) arch: ManuallyDrop<arch::$name_enc>,
39 pub(super) soft: ManuallyDrop<soft::$name_enc>,
40 }
41
42 pub(super) union InnerDec {
43 pub(super) arch: ManuallyDrop<arch::$name_dec>,
44 pub(super) soft: ManuallyDrop<soft::$name_dec>,
45 }
46 }
47
48 #[doc=$doc]
49 #[doc = "block cipher"]
50 pub struct $name {
51 inner: $module::Inner,
52 token: arch::features::aes::InitToken,
53 }
54
55 impl KeySizeUser for $name {
56 type KeySize = $key_size;
57 }
58 impl From<$name_enc> for $name {
59 #[inline]
60 fn from(enc: $name_enc) -> $name {
61 Self::from(&enc)
62 }
63 }
64
65 impl From<&$name_enc> for $name {
66 fn from(enc: &$name_enc) -> $name {
67 use core::ops::Deref;
68 let inner = if enc.token.get() {
69 $module::Inner {
70 arch: ManuallyDrop::new(unsafe { enc.inner.arch.deref().into() }),
71 }
72 } else {
73 $module::Inner {
74 soft: ManuallyDrop::new(unsafe { enc.inner.soft.deref().into() }),
75 }
76 };
77
78 Self {
79 inner,
80 token: enc.token,
81 }
82 }
83 }
84
85 impl KeyInit for $name {
86 #[inline]
87 fn new(key: &Key<Self>) -> Self {
88 let (token, aes_features) = arch::features::aes::init_get();
89
90 let inner = if aes_features {
91 $module::Inner {
92 arch: ManuallyDrop::new(arch::$name::new(key)),
93 }
94 } else {
95 $module::Inner {
96 soft: ManuallyDrop::new(soft::$name::new(key)),
97 }
98 };
99
100 Self { inner, token }
101 }
102 }
103
104 impl Clone for $name {
105 fn clone(&self) -> Self {
106 let inner = if self.token.get() {
107 $module::Inner {
108 arch: unsafe { self.inner.arch.clone() },
109 }
110 } else {
111 $module::Inner {
112 soft: unsafe { self.inner.soft.clone() },
113 }
114 };
115
116 Self {
117 inner,
118 token: self.token,
119 }
120 }
121 }
122
123 impl BlockSizeUser for $name {
124 type BlockSize = U16;
125 }
126
127 impl BlockCipherEncrypt for $name {
128 fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = U16>) {
129 if self.token.get() {
130 unsafe { &self.inner.arch }.encrypt_with_backend(f)
131 } else {
132 unsafe { &self.inner.soft }.encrypt_with_backend(f)
133 }
134 }
135 }
136
137 impl BlockCipherDecrypt for $name {
138 fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = U16>) {
139 if self.token.get() {
140 unsafe { &self.inner.arch }.decrypt_with_backend(f)
141 } else {
142 unsafe { &self.inner.soft }.decrypt_with_backend(f)
143 }
144 }
145 }
146
147 impl fmt::Debug for $name {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
149 f.write_str(concat!(stringify!($name), " { .. }"))
150 }
151 }
152
153 impl AlgorithmName for $name {
154 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 f.write_str(stringify!($name))
156 }
157 }
158
159 impl Drop for $name {
160 #[inline]
161 fn drop(&mut self) {
162 if self.token.get() {
163 unsafe { ManuallyDrop::drop(&mut self.inner.arch) };
164 } else {
165 unsafe { ManuallyDrop::drop(&mut self.inner.soft) };
166 };
167 }
168 }
169
170 #[cfg(feature = "zeroize")]
171 impl zeroize::ZeroizeOnDrop for $name {}
172
173 #[doc=$doc]
174 #[doc = "block cipher (encrypt-only)"]
175 pub struct $name_enc {
176 inner: $module::InnerEnc,
177 token: arch::features::aes::InitToken,
178 }
179
180 impl KeySizeUser for $name_enc {
181 type KeySize = $key_size;
182 }
183
184 impl KeyInit for $name_enc {
185 #[inline]
186 fn new(key: &Key<Self>) -> Self {
187 let (token, aes_features) = arch::features::aes::init_get();
188
189 let inner = if aes_features {
190 $module::InnerEnc {
191 arch: ManuallyDrop::new(arch::$name_enc::new(key)),
192 }
193 } else {
194 $module::InnerEnc {
195 soft: ManuallyDrop::new(soft::$name_enc::new(key)),
196 }
197 };
198
199 Self { inner, token }
200 }
201 }
202
203 impl Clone for $name_enc {
204 fn clone(&self) -> Self {
205 let inner = if self.token.get() {
206 $module::InnerEnc {
207 arch: unsafe { self.inner.arch.clone() },
208 }
209 } else {
210 $module::InnerEnc {
211 soft: unsafe { self.inner.soft.clone() },
212 }
213 };
214
215 Self {
216 inner,
217 token: self.token,
218 }
219 }
220 }
221
222 impl BlockSizeUser for $name_enc {
223 type BlockSize = U16;
224 }
225
226 impl BlockCipherEncrypt for $name_enc {
227 fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure<BlockSize = U16>) {
228 if self.token.get() {
229 unsafe { &self.inner.arch }.encrypt_with_backend(f)
230 } else {
231 unsafe { &self.inner.soft }.encrypt_with_backend(f)
232 }
233 }
234 }
235
236 impl fmt::Debug for $name_enc {
237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
238 f.write_str(concat!(stringify!($name_enc), " { .. }"))
239 }
240 }
241
242 impl AlgorithmName for $name_enc {
243 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
244 f.write_str(stringify!($name_enc))
245 }
246 }
247
248 impl Drop for $name_enc {
249 #[inline]
250 fn drop(&mut self) {
251 if self.token.get() {
252 unsafe { ManuallyDrop::drop(&mut self.inner.arch) };
253 } else {
254 unsafe { ManuallyDrop::drop(&mut self.inner.soft) };
255 };
256 }
257 }
258
259 #[cfg(feature = "zeroize")]
260 impl zeroize::ZeroizeOnDrop for $name_enc {}
261
262 #[doc=$doc]
263 #[doc = "block cipher (decrypt-only)"]
264 pub struct $name_dec {
265 inner: $module::InnerDec,
266 token: arch::features::aes::InitToken,
267 }
268
269 impl KeySizeUser for $name_dec {
270 type KeySize = $key_size;
271 }
272
273 impl From<$name_enc> for $name_dec {
274 #[inline]
275 fn from(enc: $name_enc) -> $name_dec {
276 Self::from(&enc)
277 }
278 }
279
280 impl From<&$name_enc> for $name_dec {
281 fn from(enc: &$name_enc) -> $name_dec {
282 use core::ops::Deref;
283 let inner = if enc.token.get() {
284 $module::InnerDec {
285 arch: ManuallyDrop::new(unsafe { enc.inner.arch.deref().into() }),
286 }
287 } else {
288 $module::InnerDec {
289 soft: ManuallyDrop::new(unsafe { enc.inner.soft.deref().into() }),
290 }
291 };
292
293 Self {
294 inner,
295 token: enc.token,
296 }
297 }
298 }
299
300 impl KeyInit for $name_dec {
301 #[inline]
302 fn new(key: &Key<Self>) -> Self {
303 let (token, aes_features) = arch::features::aes::init_get();
304
305 let inner = if aes_features {
306 $module::InnerDec {
307 arch: ManuallyDrop::new(arch::$name_dec::new(key)),
308 }
309 } else {
310 $module::InnerDec {
311 soft: ManuallyDrop::new(soft::$name_dec::new(key)),
312 }
313 };
314
315 Self { inner, token }
316 }
317 }
318
319 impl Clone for $name_dec {
320 fn clone(&self) -> Self {
321 let inner = if self.token.get() {
322 $module::InnerDec {
323 arch: unsafe { self.inner.arch.clone() },
324 }
325 } else {
326 $module::InnerDec {
327 soft: unsafe { self.inner.soft.clone() },
328 }
329 };
330
331 Self {
332 inner,
333 token: self.token,
334 }
335 }
336 }
337
338 impl BlockSizeUser for $name_dec {
339 type BlockSize = U16;
340 }
341
342 impl BlockCipherDecrypt for $name_dec {
343 fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure<BlockSize = U16>) {
344 if self.token.get() {
345 unsafe { &self.inner.arch }.decrypt_with_backend(f)
346 } else {
347 unsafe { &self.inner.soft }.decrypt_with_backend(f)
348 }
349 }
350 }
351
352 impl fmt::Debug for $name_dec {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
354 f.write_str(concat!(stringify!($name_dec), " { .. }"))
355 }
356 }
357
358 impl AlgorithmName for $name_dec {
359 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
360 f.write_str(stringify!($name_dec))
361 }
362 }
363
364 impl Drop for $name_dec {
365 #[inline]
366 fn drop(&mut self) {
367 if self.token.get() {
368 unsafe { ManuallyDrop::drop(&mut self.inner.arch) };
369 } else {
370 unsafe { ManuallyDrop::drop(&mut self.inner.soft) };
371 };
372 }
373 }
374
375 #[cfg(feature = "zeroize")]
376 impl zeroize::ZeroizeOnDrop for $name_dec {}
377 };
378}
379
380define_aes_impl!(
381 name = Aes128,
382 name_enc = Aes128Enc,
383 name_dec = Aes128Dec,
384 module = aes128,
385 key_size = U16,
386 doc = "AES-128",
387);
388define_aes_impl!(
389 name = Aes192,
390 name_enc = Aes192Enc,
391 name_dec = Aes192Dec,
392 module = aes192,
393 key_size = U24,
394 doc = "AES-192",
395);
396define_aes_impl!(
397 name = Aes256,
398 name_enc = Aes256Enc,
399 name_dec = Aes256Dec,
400 module = aes256,
401 key_size = U32,
402 doc = "AES-256",
403);