Skip to content

Commit

Permalink
aes: autodetection support for AES-NI
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tarcieri committed Nov 26, 2020
1 parent 68c1756 commit 0fb7bb5
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .github/workflows/aes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ jobs:
- run: ${{ matrix.deps }}
- run: cargo check --target ${{ matrix.target }} --all-features
- run: cargo test --release --target ${{ matrix.target }}
- run: cargo test --release --target ${{ matrix.target }} --features autodetect
- run: cargo test --release --target ${{ matrix.target }} --features compact
- run: cargo test --release --target ${{ matrix.target }} --features ctr
- run: cargo test --release --target ${{ matrix.target }} --all-features
Expand Down Expand Up @@ -109,6 +110,7 @@ jobs:
- run: ${{ matrix.deps }}
- run: cargo check --target ${{ matrix.target }} --all-features
- run: cargo test --release --target ${{ matrix.target }}
- run: cargo test --release --target ${{ matrix.target }} --features autodetect
- run: cargo test --release --target ${{ matrix.target }} --features compact
- run: cargo test --release --target ${{ matrix.target }} --features ctr
- run: cargo test --release --target ${{ matrix.target }} --all-features
Expand Down
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions aes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ categories = ["cryptography", "no-std"]
[dependencies]
cfg-if = "1"
cipher = "=0.3.0-pre"
cpuid-bool = { version = "0.1", optional = true }
ctr = { version = "=0.7.0-pre", optional = true }
opaque-debug = "0.3"

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

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

[package.metadata.docs.rs]
Expand Down
107 changes: 107 additions & 0 deletions aes/src/autodetect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//! Autodetection support for hardware accelerated AES backends with fallback
//! to the fixsliced "soft" implementation.

use crate::{Block, ParBlocks};
use cipher::{
consts::{U16, U24, U32, U8},
generic_array::GenericArray,
BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
};

macro_rules! define_aes_impl {
(
$name:tt,
$module:tt,
$key_size:ty,
$doc:expr
) => {
#[doc=$doc]
#[derive(Clone)]
pub struct $name($module::Inner);

mod $module {
#[derive(Clone)]
pub(super) enum Inner {
Ni(crate::ni::$name),
Soft(crate::soft::$name),
}
}

impl NewBlockCipher for $name {
type KeySize = $key_size;

#[inline]
fn new(key: &GenericArray<u8, $key_size>) -> Self {
if cpuid_bool::cpuid_bool!("aes") {
$name($module::Inner::Ni(crate::ni::$name::new(key)))
} else {
$name($module::Inner::Soft(crate::soft::$name::new(key)))
}
}
}

impl BlockCipher for $name {
type BlockSize = U16;
type ParBlocks = U8;
}

impl BlockEncrypt for $name {
#[inline]
fn encrypt_block(&self, block: &mut Block) {
match &self.0 {
$module::Inner::Ni(aes) => aes.encrypt_block(block),
$module::Inner::Soft(aes) => aes.encrypt_block(block),
}
}

#[inline]
fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) {
match &self.0 {
$module::Inner::Ni(aes) => aes.encrypt_par_blocks(blocks),
$module::Inner::Soft(aes) => aes.encrypt_par_blocks(blocks),
}
}
}

impl BlockDecrypt for $name {
#[inline]
fn decrypt_block(&self, block: &mut Block) {
match &self.0 {
$module::Inner::Ni(aes) => aes.decrypt_block(block),
$module::Inner::Soft(aes) => aes.decrypt_block(block),
}
}

#[inline]
fn decrypt_par_blocks(&self, blocks: &mut ParBlocks) {
match &self.0 {
$module::Inner::Ni(aes) => aes.decrypt_par_blocks(blocks),
$module::Inner::Soft(aes) => aes.decrypt_par_blocks(blocks),
}
}
}

opaque_debug::implement!($name);
}
}

define_aes_impl!(
Aes128,
aes128,
U16,
"AES-128 block cipher instance"
);

define_aes_impl!(
Aes192,
aes192,
U24,
"AES-192 block cipher instance"
);

define_aes_impl!(
Aes256,
aes256,
U32,
"AES-256 block cipher instance"
);
12 changes: 11 additions & 1 deletion aes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,17 @@ cfg_if! {
any(target_arch = "x86_64", target_arch = "x86"),
))] {
mod ni;
pub use ni::{Aes128, Aes192, Aes256};

cfg_if! {
if #[cfg(feature = "autodetect")] {
mod autodetect;
mod soft;

pub use autodetect::{Aes128, Aes192, Aes256};
} else {
pub use ni::{Aes128, Aes192, Aes256};
}
}

#[cfg(feature = "ctr")]
cfg_if! {
Expand Down
2 changes: 2 additions & 0 deletions aes/src/soft/ctr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! AES in counter mode (a.k.a. AES-CTR)

#![cfg_attr(feature = "autodetect", allow(dead_code))]

use super::{Aes128, Aes192, Aes256};

/// AES-128 in CTR mode
Expand Down

0 comments on commit 0fb7bb5

Please sign in to comment.