Skip to content

Commit 9407a2d

Browse files
committed
aes: autodetection support for AES-NI
Adds an off-by-default `autodetect` feature which the `cpuid-bool` crate to detect whether AES-NI is available when compiling on i686/x86_64 architectures.
1 parent 68c1756 commit 9407a2d

File tree

6 files changed

+125
-3
lines changed

6 files changed

+125
-3
lines changed

.github/workflows/aes.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ jobs:
7171
- run: ${{ matrix.deps }}
7272
- run: cargo check --target ${{ matrix.target }} --all-features
7373
- run: cargo test --release --target ${{ matrix.target }}
74+
- run: cargo test --release --target ${{ matrix.target }} --features autodetect
7475
- run: cargo test --release --target ${{ matrix.target }} --features compact
7576
- run: cargo test --release --target ${{ matrix.target }} --features ctr
7677
- run: cargo test --release --target ${{ matrix.target }} --all-features
@@ -109,6 +110,7 @@ jobs:
109110
- run: ${{ matrix.deps }}
110111
- run: cargo check --target ${{ matrix.target }} --all-features
111112
- run: cargo test --release --target ${{ matrix.target }}
113+
- run: cargo test --release --target ${{ matrix.target }} --features autodetect
112114
- run: cargo test --release --target ${{ matrix.target }} --features compact
113115
- run: cargo test --release --target ${{ matrix.target }} --features ctr
114116
- run: cargo test --release --target ${{ matrix.target }} --all-features

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aes/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ categories = ["cryptography", "no-std"]
1717
[dependencies]
1818
cfg-if = "1"
1919
cipher = "=0.3.0-pre"
20+
cpuid-bool = { version = "0.1", optional = true }
2021
ctr = { version = "=0.7.0-pre", optional = true }
2122
opaque-debug = "0.3"
2223

2324
[dev-dependencies]
2425
cipher = { version = "=0.3.0-pre", features = ["dev"] }
2526

2627
[features]
28+
autodetect = ["cpuid-bool"] # Detect hardware AES and fallback to "soft" if unavailable
2729
compact = [] # Reduce code size at the cost of performance
2830

2931
[package.metadata.docs.rs]

aes/src/autodetect.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//! Autodetection support for hardware accelerated AES backends with fallback
2+
//! to the fixsliced "soft" implementation.
3+
4+
use crate::{Block, ParBlocks};
5+
use cipher::{
6+
consts::{U16, U24, U32, U8},
7+
generic_array::GenericArray,
8+
BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
9+
};
10+
11+
macro_rules! define_aes_impl {
12+
(
13+
$name:tt,
14+
$module:tt,
15+
$key_size:ty,
16+
$doc:expr
17+
) => {
18+
#[doc=$doc]
19+
#[derive(Clone)]
20+
pub struct $name($module::Inner);
21+
22+
mod $module {
23+
#[derive(Clone)]
24+
pub(super) enum Inner {
25+
Ni(crate::ni::$name),
26+
Soft(crate::soft::$name),
27+
}
28+
}
29+
30+
impl NewBlockCipher for $name {
31+
type KeySize = $key_size;
32+
33+
#[inline]
34+
fn new(key: &GenericArray<u8, $key_size>) -> Self {
35+
if cpuid_bool::cpuid_bool!("aes") {
36+
$name($module::Inner::Ni(crate::ni::$name::new(key)))
37+
} else {
38+
$name($module::Inner::Soft(crate::soft::$name::new(key)))
39+
}
40+
}
41+
}
42+
43+
impl BlockCipher for $name {
44+
type BlockSize = U16;
45+
type ParBlocks = U8;
46+
}
47+
48+
impl BlockEncrypt for $name {
49+
#[inline]
50+
fn encrypt_block(&self, block: &mut Block) {
51+
match &self.0 {
52+
$module::Inner::Ni(aes) => aes.encrypt_block(block),
53+
$module::Inner::Soft(aes) => aes.encrypt_block(block),
54+
}
55+
}
56+
57+
#[inline]
58+
fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) {
59+
match &self.0 {
60+
$module::Inner::Ni(aes) => aes.encrypt_par_blocks(blocks),
61+
$module::Inner::Soft(aes) => aes.encrypt_par_blocks(blocks),
62+
}
63+
}
64+
}
65+
66+
impl BlockDecrypt for $name {
67+
#[inline]
68+
fn decrypt_block(&self, block: &mut Block) {
69+
match &self.0 {
70+
$module::Inner::Ni(aes) => aes.decrypt_block(block),
71+
$module::Inner::Soft(aes) => aes.decrypt_block(block),
72+
}
73+
}
74+
75+
#[inline]
76+
fn decrypt_par_blocks(&self, blocks: &mut ParBlocks) {
77+
match &self.0 {
78+
$module::Inner::Ni(aes) => aes.decrypt_par_blocks(blocks),
79+
$module::Inner::Soft(aes) => aes.decrypt_par_blocks(blocks),
80+
}
81+
}
82+
}
83+
84+
opaque_debug::implement!($name);
85+
}
86+
}
87+
88+
define_aes_impl!(
89+
Aes128,
90+
aes128,
91+
U16,
92+
"AES-128 block cipher instance"
93+
);
94+
95+
define_aes_impl!(
96+
Aes192,
97+
aes192,
98+
U24,
99+
"AES-192 block cipher instance"
100+
);
101+
102+
define_aes_impl!(
103+
Aes256,
104+
aes256,
105+
U32,
106+
"AES-256 block cipher instance"
107+
);

aes/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,14 @@ use cfg_if::cfg_if;
6363

6464
cfg_if! {
6565
if #[cfg(all(
66-
target_feature = "aes",
67-
target_feature = "sse2",
6866
any(target_arch = "x86_64", target_arch = "x86"),
67+
feature = "autodetect"
6968
))] {
7069
mod ni;
71-
pub use ni::{Aes128, Aes192, Aes256};
70+
mod autodetect;
71+
mod soft;
72+
73+
pub use autodetect::{Aes128, Aes192, Aes256};
7274

7375
#[cfg(feature = "ctr")]
7476
cfg_if! {

aes/src/soft/ctr.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! AES in counter mode (a.k.a. AES-CTR)
22
3+
#![cfg_attr(feature = "autodetect", allow(dead_code))]
4+
35
use super::{Aes128, Aes192, Aes256};
46

57
/// AES-128 in CTR mode

0 commit comments

Comments
 (0)