Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/aes-0.7.5/src/autodetect.rs
Line
Count
Source
1
//! Autodetection support for hardware accelerated AES backends with fallback
2
//! to the fixsliced "soft" implementation.
3
4
use crate::{soft, Block, ParBlocks};
5
use cipher::{
6
    consts::{U16, U24, U32, U8},
7
    generic_array::GenericArray,
8
    BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
9
};
10
use core::mem::ManuallyDrop;
11
12
#[cfg(all(target_arch = "aarch64", feature = "armv8"))]
13
use crate::armv8 as intrinsics;
14
15
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
16
use crate::ni as intrinsics;
17
18
cpufeatures::new!(aes_intrinsics, "aes");
19
20
macro_rules! define_aes_impl {
21
    (
22
        $name:tt,
23
        $module:tt,
24
        $key_size:ty,
25
        $doc:expr
26
    ) => {
27
        #[doc=$doc]
28
        pub struct $name {
29
            inner: $module::Inner,
30
            token: aes_intrinsics::InitToken,
31
        }
32
33
        mod $module {
34
            use super::{intrinsics, soft};
35
            use core::mem::ManuallyDrop;
36
37
            pub(super) union Inner {
38
                pub(super) intrinsics: ManuallyDrop<intrinsics::$name>,
39
                pub(super) soft: ManuallyDrop<soft::$name>,
40
            }
41
        }
42
43
        impl NewBlockCipher for $name {
44
            type KeySize = $key_size;
45
46
            #[inline]
47
560
            fn new(key: &GenericArray<u8, $key_size>) -> Self {
48
560
                let (token, aesni_present) = aes_intrinsics::init_get();
49
50
560
                let inner = if aesni_present {
51
560
                    $module::Inner {
52
560
                        intrinsics: ManuallyDrop::new(intrinsics::$name::new(key)),
53
0
                    }
54
                } else {
55
0
                    $module::Inner {
56
0
                        soft: ManuallyDrop::new(soft::$name::new(key)),
57
0
                    }
58
                };
59
60
560
                Self { inner, token }
61
560
            }
<aes::autodetect::Aes128 as cipher::block::NewBlockCipher>::new
Line
Count
Source
47
560
            fn new(key: &GenericArray<u8, $key_size>) -> Self {
48
560
                let (token, aesni_present) = aes_intrinsics::init_get();
49
50
560
                let inner = if aesni_present {
51
560
                    $module::Inner {
52
560
                        intrinsics: ManuallyDrop::new(intrinsics::$name::new(key)),
53
560
                    }
54
                } else {
55
0
                    $module::Inner {
56
0
                        soft: ManuallyDrop::new(soft::$name::new(key)),
57
0
                    }
58
                };
59
60
560
                Self { inner, token }
61
560
            }
Unexecuted instantiation: <aes::autodetect::Aes192 as cipher::block::NewBlockCipher>::new
Unexecuted instantiation: <aes::autodetect::Aes256 as cipher::block::NewBlockCipher>::new
62
        }
63
64
        impl Clone for $name {
65
0
            fn clone(&self) -> Self {
66
0
                let inner = if self.token.get() {
67
0
                    $module::Inner {
68
0
                        intrinsics: unsafe { self.inner.intrinsics.clone() },
69
0
                    }
70
                } else {
71
0
                    $module::Inner {
72
0
                        soft: unsafe { self.inner.soft.clone() },
73
0
                    }
74
                };
75
76
0
                Self {
77
0
                    inner,
78
0
                    token: self.token,
79
0
                }
80
0
            }
Unexecuted instantiation: <aes::autodetect::Aes192 as core::clone::Clone>::clone
Unexecuted instantiation: <aes::autodetect::Aes128 as core::clone::Clone>::clone
Unexecuted instantiation: <aes::autodetect::Aes256 as core::clone::Clone>::clone
81
        }
82
83
        impl BlockCipher for $name {
84
            type BlockSize = U16;
85
            type ParBlocks = U8;
86
        }
87
88
        impl BlockEncrypt for $name {
89
            #[inline]
90
596
            fn encrypt_block(&self, block: &mut Block) {
91
596
                if self.token.get() {
92
596
                    unsafe { self.inner.intrinsics.encrypt_block(block) }
93
                } else {
94
0
                    unsafe { self.inner.soft.encrypt_block(block) }
95
                }
96
596
            }
<aes::autodetect::Aes128 as cipher::block::BlockEncrypt>::encrypt_block
Line
Count
Source
90
596
            fn encrypt_block(&self, block: &mut Block) {
91
596
                if self.token.get() {
92
596
                    unsafe { self.inner.intrinsics.encrypt_block(block) }
93
                } else {
94
0
                    unsafe { self.inner.soft.encrypt_block(block) }
95
                }
96
596
            }
Unexecuted instantiation: <aes::autodetect::Aes192 as cipher::block::BlockEncrypt>::encrypt_block
Unexecuted instantiation: <aes::autodetect::Aes256 as cipher::block::BlockEncrypt>::encrypt_block
97
98
            #[inline]
99
4
            fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) {
100
4
                if self.token.get() {
101
4
                    unsafe { self.inner.intrinsics.encrypt_par_blocks(blocks) }
102
                } else {
103
0
                    unsafe { self.inner.soft.encrypt_par_blocks(blocks) }
104
                }
105
4
            }
<aes::autodetect::Aes128 as cipher::block::BlockEncrypt>::encrypt_par_blocks
Line
Count
Source
99
4
            fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) {
100
4
                if self.token.get() {
101
4
                    unsafe { self.inner.intrinsics.encrypt_par_blocks(blocks) }
102
                } else {
103
0
                    unsafe { self.inner.soft.encrypt_par_blocks(blocks) }
104
                }
105
4
            }
Unexecuted instantiation: <aes::autodetect::Aes192 as cipher::block::BlockEncrypt>::encrypt_par_blocks
Unexecuted instantiation: <aes::autodetect::Aes256 as cipher::block::BlockEncrypt>::encrypt_par_blocks
106
        }
107
108
        impl BlockDecrypt for $name {
109
            #[inline]
110
0
            fn decrypt_block(&self, block: &mut Block) {
111
0
                if self.token.get() {
112
0
                    unsafe { self.inner.intrinsics.decrypt_block(block) }
113
                } else {
114
0
                    unsafe { self.inner.soft.decrypt_block(block) }
115
                }
116
0
            }
Unexecuted instantiation: <aes::autodetect::Aes128 as cipher::block::BlockDecrypt>::decrypt_block
Unexecuted instantiation: <aes::autodetect::Aes192 as cipher::block::BlockDecrypt>::decrypt_block
Unexecuted instantiation: <aes::autodetect::Aes256 as cipher::block::BlockDecrypt>::decrypt_block
117
118
            #[inline]
119
0
            fn decrypt_par_blocks(&self, blocks: &mut ParBlocks) {
120
0
                if self.token.get() {
121
0
                    unsafe { self.inner.intrinsics.decrypt_par_blocks(blocks) }
122
                } else {
123
0
                    unsafe { self.inner.soft.decrypt_par_blocks(blocks) }
124
                }
125
0
            }
Unexecuted instantiation: <aes::autodetect::Aes128 as cipher::block::BlockDecrypt>::decrypt_par_blocks
Unexecuted instantiation: <aes::autodetect::Aes192 as cipher::block::BlockDecrypt>::decrypt_par_blocks
Unexecuted instantiation: <aes::autodetect::Aes256 as cipher::block::BlockDecrypt>::decrypt_par_blocks
126
        }
127
128
        opaque_debug::implement!($name);
129
    };
130
}
131
132
define_aes_impl!(Aes128, aes128, U16, "AES-128 block cipher instance");
133
define_aes_impl!(Aes192, aes192, U24, "AES-192 block cipher instance");
134
define_aes_impl!(Aes256, aes256, U32, "AES-256 block cipher instance");
135
136
#[cfg(all(feature = "ctr", target_arch = "aarch64"))]
137
pub(crate) mod ctr {
138
    use super::{Aes128, Aes192, Aes256};
139
140
    /// AES-128 in CTR mode
141
    pub type Aes128Ctr = ::ctr::Ctr64BE<Aes128>;
142
143
    /// AES-192 in CTR mode
144
    pub type Aes192Ctr = ::ctr::Ctr64BE<Aes192>;
145
146
    /// AES-256 in CTR mode
147
    pub type Aes256Ctr = ::ctr::Ctr64BE<Aes256>;
148
}
149
150
#[cfg(all(feature = "ctr", any(target_arch = "x86_64", target_arch = "x86")))]
151
pub(crate) mod ctr {
152
    use super::{Aes128, Aes192, Aes256};
153
    use crate::{ni, soft};
154
    use cipher::{
155
        errors::{LoopError, OverflowError},
156
        generic_array::GenericArray,
157
        BlockCipher, FromBlockCipher, SeekNum, StreamCipher, StreamCipherSeek,
158
    };
159
    use core::mem::ManuallyDrop;
160
161
    cpufeatures::new!(aes_ssse3_cpuid, "aes", "ssse3");
162
163
    macro_rules! define_aes_ctr_impl {
164
        (
165
            $name:tt,
166
            $cipher:ident,
167
            $module:tt,
168
            $doc:expr
169
        ) => {
170
            #[doc=$doc]
171
            #[cfg_attr(docsrs, doc(cfg(feature = "ctr")))]
172
            pub struct $name {
173
                inner: $module::Inner,
174
                token: aes_ssse3_cpuid::InitToken,
175
            }
176
177
            mod $module {
178
                use crate::{ni, soft};
179
                use core::mem::ManuallyDrop;
180
181
                pub(super) union Inner {
182
                    pub(super) ni: ManuallyDrop<ni::$name>,
183
                    pub(super) soft: ManuallyDrop<soft::$name>,
184
                }
185
            }
186
187
            impl FromBlockCipher for $name {
188
                type BlockCipher = $cipher;
189
                type NonceSize = <$cipher as BlockCipher>::BlockSize;
190
191
                fn from_block_cipher(
192
                    cipher: $cipher,
193
                    nonce: &GenericArray<u8, Self::NonceSize>,
194
                ) -> Self {
195
                    let (token, aesni_present) = aes_ssse3_cpuid::init_get();
196
197
                    let inner = if aesni_present {
198
                        let ni = ni::$name::from_block_cipher(
199
                            unsafe { (*cipher.inner.intrinsics).clone() },
200
                            nonce,
201
                        );
202
203
                        $module::Inner {
204
                            ni: ManuallyDrop::new(ni),
205
                        }
206
                    } else {
207
                        let soft = soft::$name::from_block_cipher(
208
                            unsafe { (*cipher.inner.soft).clone() },
209
                            nonce,
210
                        );
211
212
                        $module::Inner {
213
                            soft: ManuallyDrop::new(soft),
214
                        }
215
                    };
216
217
                    Self { inner, token }
218
                }
219
            }
220
221
            impl StreamCipher for $name {
222
                #[inline]
223
                fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> {
224
                    if self.token.get() {
225
                        unsafe { (*self.inner.ni).try_apply_keystream(data) }
226
                    } else {
227
                        unsafe { (*self.inner.soft).try_apply_keystream(data) }
228
                    }
229
                }
230
            }
231
232
            impl StreamCipherSeek for $name {
233
                #[inline]
234
                fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError> {
235
                    if self.token.get() {
236
                        unsafe { (*self.inner.ni).try_current_pos() }
237
                    } else {
238
                        unsafe { (*self.inner.soft).try_current_pos() }
239
                    }
240
                }
241
242
                #[inline]
243
                fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError> {
244
                    if self.token.get() {
245
                        unsafe { (*self.inner.ni).try_seek(pos) }
246
                    } else {
247
                        unsafe { (*self.inner.soft).try_seek(pos) }
248
                    }
249
                }
250
            }
251
252
            opaque_debug::implement!($name);
253
        };
254
    }
255
256
    define_aes_ctr_impl!(Aes128Ctr, Aes128, aes128ctr, "AES-128 in CTR mode");
257
    define_aes_ctr_impl!(Aes192Ctr, Aes192, aes192ctr, "AES-192 in CTR mode");
258
    define_aes_ctr_impl!(Aes256Ctr, Aes256, aes256ctr, "AES-256 in CTR mode");
259
}