diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..0d0c7a5 --- /dev/null +++ b/build.rs @@ -0,0 +1,65 @@ +#![cfg_attr( + all(feature = "nightly", target_arch = "arm", target_feature = "v8"), + feature(stdarch_arm_feature_detection) +)] +#![cfg_attr( + all( + feature = "nightly", + any(target_arch = "riscv64", target_arch = "riscv32") + ), + feature(stdarch_riscv_feature_detection) +)] +use std::arch::*; + +fn select_impl() -> &'static str { + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + if is_x86_feature_detected!("aes") && is_x86_feature_detected!("sse4.1") { + return "x86"; + } + #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] + if is_aarch64_feature_detected!("aes") { + return "neon"; + } + #[cfg(all(feature = "nightly", target_arch = "arm", target_feature = "v8"))] + if is_arm_feature_detected!("aes") { + return "arm-neon"; + } + #[cfg(all( + feature = "nightly", + any(target_arch = "riscv64", target_arch = "riscv32") + ))] + if is_riscv_feature_detected!("zkne") && is_riscv_feature_detected!("zknd") { + return "risc-v"; + } + "software" +} + +fn select_x2_impl() -> &'static str { + #[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))] + if is_x86_feature_detected!("vaes") { + return "vaes"; + } + "tuple" +} + +fn select_x4_impl() -> &'static str { + #[cfg(all(feature = "nightly", any(target_arch = "x86", target_arch = "x86_64")))] + if is_x86_feature_detected!("avx512f") { + return "avx512f"; + } + "tuple" +} + +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + + println!( + "cargo:rustc-check-cfg=cfg(aes_impl, values(\"x86\", \"neon\", \"arm-neon\", \"risc-v\", \"software\"))" + ); + println!("cargo:rustc-check-cfg=cfg(aes_x2_impl, values(\"vaes\", \"tuple\"))"); + println!("cargo:rustc-check-cfg=cfg(aes_x4_impl, values(\"avx512f\", \"tuple\"))"); + + println!("cargo:rustc-cfg=aes_impl=\"{}\"", select_impl()); + println!("cargo:rustc-cfg=aes_x2_impl=\"{}\"", select_x2_impl()); + println!("cargo:rustc-cfg=aes_x4_impl=\"{}\"", select_x4_impl()); +} diff --git a/src/aes_arm.rs b/src/aes_arm.rs index 3afd5b5..d4a7065 100644 --- a/src/aes_arm.rs +++ b/src/aes_arm.rs @@ -112,13 +112,15 @@ impl AesBlock { } } + /// /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` #[inline(always)] - pub(crate) fn pre_enc_last(self, round_key: Self) -> Self { + pub fn pre_enc_last(self, round_key: Self) -> Self { Self(unsafe { vaeseq_u8(self.0, round_key.0) }) } + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` -> `MixColumns` #[inline(always)] - pub(crate) fn pre_enc(self, round_key: Self) -> Self { + pub fn pre_enc(self, round_key: Self) -> Self { self.pre_enc_last(round_key).mc() } @@ -128,17 +130,19 @@ impl AesBlock { self.pre_enc(Self::zero()) ^ round_key } + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` #[inline(always)] - pub(crate) fn pre_dec_last(self, round_key: Self) -> Self { + pub fn pre_dec_last(self, round_key: Self) -> Self { Self(unsafe { vaesdq_u8(self.0, round_key.0) }) } + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` -> `InvMixColumns` #[inline(always)] - pub(crate) fn pre_dec(self, round_key: Self) -> Self { + pub fn pre_dec(self, round_key: Self) -> Self { self.pre_dec_last(round_key).imc() } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { self.pre_dec(Self::zero()) ^ round_key @@ -150,7 +154,7 @@ impl AesBlock { self.pre_enc_last(Self::zero()) ^ round_key } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { self.pre_dec_last(Self::zero()) ^ round_key @@ -162,7 +166,7 @@ impl AesBlock { Self(unsafe { vaesmcq_u8(self.0) }) } - /// Performs the `InvMixColumn`s operation + /// Performs the `InvMixColumns` operation #[inline] pub fn imc(self) -> Self { Self(unsafe { vaesimcq_u8(self.0) }) diff --git a/src/aes_default.rs b/src/aes_default.rs index 41c3274..2652415 100644 --- a/src/aes_default.rs +++ b/src/aes_default.rs @@ -149,7 +149,7 @@ impl AesBlock { ) } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { Self( @@ -160,7 +160,7 @@ impl AesBlock { ) } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { Self( @@ -210,7 +210,7 @@ impl AesBlock { ) } - /// Performs the `InvMixColumn`s operation + /// Performs the `InvMixColumns` operation #[inline] pub fn imc(self) -> Self { Self( diff --git a/src/aes_riscv32.rs b/src/aes_riscv32.rs index f360fc7..215c217 100644 --- a/src/aes_riscv32.rs +++ b/src/aes_riscv32.rs @@ -122,8 +122,9 @@ impl AesBlock { (self.0 | self.1 | self.2 | self.3) == 0 } + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` -> `MixColumns` #[inline(always)] - pub(crate) fn pre_enc(self, round_key: Self) -> Self { + pub fn pre_enc(self, round_key: Self) -> Self { outer!(aes32esmi, self, round_key) } @@ -133,8 +134,9 @@ impl AesBlock { self.pre_enc(Self::zero()) ^ round_key } + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` #[inline(always)] - pub(crate) fn pre_enc_last(self, round_key: Self) -> Self { + pub fn pre_enc_last(self, round_key: Self) -> Self { outer!(aes32esi, self, round_key) } @@ -144,23 +146,25 @@ impl AesBlock { self.pre_enc_last(Self::zero()) ^ round_key } + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` -> `InvMixColumns` #[inline(always)] - pub(crate) fn pre_dec(self, round_key: Self) -> Self { + pub fn pre_dec(self, round_key: Self) -> Self { outer!(aes32dsmi, self, round_key) } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { self.pre_dec(Self::zero()) ^ round_key } + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` #[inline(always)] - pub(crate) fn pre_dec_last(self, round_key: Self) -> Self { + pub fn pre_dec_last(self, round_key: Self) -> Self { outer!(aes32dsi, self, round_key) } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { self.pre_dec_last(Self::zero()) ^ round_key @@ -172,7 +176,7 @@ impl AesBlock { self.pre_dec_last(Self::zero()).enc(Self::zero()) } - /// Performs the `InvMixColumn`s operation + /// Performs the `InvMixColumns` operation #[inline] pub fn imc(self) -> Self { self.pre_enc_last(Self::zero()).dec(Self::zero()) diff --git a/src/aes_riscv64.rs b/src/aes_riscv64.rs index f6e6520..e25816f 100644 --- a/src/aes_riscv64.rs +++ b/src/aes_riscv64.rs @@ -102,7 +102,7 @@ impl AesBlock { } } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { unsafe { @@ -124,7 +124,7 @@ impl AesBlock { } } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { unsafe { @@ -144,7 +144,7 @@ impl AesBlock { } } - /// Performs the `InvMixColumn`s operation + /// Performs the `InvMixColumns` operation #[inline] pub fn imc(self) -> Self { unsafe { Self(aes64im(self.0), aes64im(self.1)) } diff --git a/src/aes_x86.rs b/src/aes_x86.rs index 5ec7253..043c840 100644 --- a/src/aes_x86.rs +++ b/src/aes_x86.rs @@ -91,7 +91,7 @@ impl AesBlock { Self(unsafe { _mm_aesenc_si128(self.0, round_key.0) }) } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { Self(unsafe { _mm_aesdec_si128(self.0, round_key.0) }) @@ -103,7 +103,7 @@ impl AesBlock { Self(unsafe { _mm_aesenclast_si128(self.0, round_key.0) }) } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { Self(unsafe { _mm_aesdeclast_si128(self.0, round_key.0) }) @@ -120,7 +120,7 @@ impl AesBlock { }) } - /// Performs the `InvMixColumn`s operation + /// Performs the `InvMixColumns` operation #[inline] pub fn imc(self) -> Self { Self(unsafe { _mm_aesimc_si128(self.0) }) diff --git a/src/aesdefault_x2.rs b/src/aesdefault_x2.rs index 7ec8952..b636187 100644 --- a/src/aesdefault_x2.rs +++ b/src/aesdefault_x2.rs @@ -98,25 +98,55 @@ impl AesBlockX2 { self.0.is_zero() & self.1.is_zero() } + /// Performs the operation `AddRoundKey` -> `SubBytes` -> `ShiftRows` -> `MixColumns` + #[inline] + pub fn pre_enc(self, round_key: Self) -> Self { + Self(self.0.pre_enc(round_key.0), self.1.pre_enc(round_key.1)) + } + /// Performs one round of AES encryption function (`ShiftRows`->`SubBytes`->`MixColumns`->`AddRoundKey`) #[inline] pub fn enc(self, round_key: Self) -> Self { Self(self.0.enc(round_key.0), self.1.enc(round_key.1)) } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` -> `InvMixColumns` + #[inline] + pub fn pre_dec(self, round_key: Self) -> Self { + Self(self.0.pre_dec(round_key.0), self.1.pre_dec(round_key.1)) + } + + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { Self(self.0.dec(round_key.0), self.1.dec(round_key.1)) } + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` + #[inline] + pub fn pre_enc_last(self, round_key: Self) -> Self { + Self( + self.0.pre_enc_last(round_key.0), + self.1.pre_enc_last(round_key.1), + ) + } + /// Performs one round of AES encryption function without `MixColumns` (`ShiftRows`->`SubBytes`->`AddRoundKey`) #[inline] pub fn enc_last(self, round_key: Self) -> Self { Self(self.0.enc_last(round_key.0), self.1.enc_last(round_key.1)) } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` + #[inline] + pub fn pre_dec_last(self, round_key: Self) -> Self { + Self( + self.0.pre_dec_last(round_key.0), + self.1.pre_dec_last(round_key.1), + ) + } + + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { Self(self.0.dec_last(round_key.0), self.1.dec_last(round_key.1)) diff --git a/src/aesdefault_x4.rs b/src/aesdefault_x4.rs index 5699b0f..3a4dd54 100644 --- a/src/aesdefault_x4.rs +++ b/src/aesdefault_x4.rs @@ -121,25 +121,55 @@ impl AesBlockX4 { self.0.is_zero() & self.1.is_zero() } + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` -> `MixColumns` + #[inline] + pub fn pre_enc(self, round_key: Self) -> Self { + Self(self.0.pre_enc(round_key.0), self.1.pre_enc(round_key.1)) + } + /// Performs one round of AES encryption function (`ShiftRows`->`SubBytes`->`MixColumns`->`AddRoundKey`) #[inline] pub fn enc(self, round_key: Self) -> Self { Self(self.0.enc(round_key.0), self.1.enc(round_key.1)) } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` -> `InvMixColumns` + #[inline] + pub fn pre_dec(self, round_key: Self) -> Self { + Self(self.0.pre_dec(round_key.0), self.1.pre_dec(round_key.1)) + } + + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { Self(self.0.dec(round_key.0), self.1.dec(round_key.1)) } + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` + #[inline] + pub fn pre_enc_last(self, round_key: Self) -> Self { + Self( + self.0.pre_enc_last(round_key.0), + self.1.pre_enc_last(round_key.1), + ) + } + /// Performs one round of AES encryption function without `MixColumns` (`ShiftRows`->`SubBytes`->`AddRoundKey`) #[inline] pub fn enc_last(self, round_key: Self) -> Self { Self(self.0.enc_last(round_key.0), self.1.enc_last(round_key.1)) } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` + #[inline] + pub fn pre_dec_last(self, round_key: Self) -> Self { + Self( + self.0.pre_dec_last(round_key.0), + self.1.pre_dec_last(round_key.1), + ) + } + + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { Self(self.0.dec_last(round_key.0), self.1.dec_last(round_key.1)) diff --git a/src/aesni_x2.rs b/src/aesni_x2.rs index 4b737e0..6995c7b 100644 --- a/src/aesni_x2.rs +++ b/src/aesni_x2.rs @@ -4,7 +4,7 @@ use core::arch::x86::*; use core::arch::x86_64::*; use core::ops::{BitAnd, BitOr, BitXor, Not}; -use crate::aes_x86::AesBlock; +use crate::AesBlock; #[derive(Copy, Clone)] #[repr(transparent)] @@ -117,7 +117,7 @@ impl AesBlockX2 { Self(unsafe { _mm256_aesenc_epi128(self.0, round_key.0) }) } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { Self(unsafe { _mm256_aesdec_epi128(self.0, round_key.0) }) @@ -129,7 +129,7 @@ impl AesBlockX2 { Self(unsafe { _mm256_aesenclast_epi128(self.0, round_key.0) }) } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { Self(unsafe { _mm256_aesdeclast_epi128(self.0, round_key.0) }) diff --git a/src/aesni_x4.rs b/src/aesni_x4.rs index 26739c8..0f03ad2 100644 --- a/src/aesni_x4.rs +++ b/src/aesni_x4.rs @@ -4,8 +4,7 @@ use core::arch::x86::*; use core::arch::x86_64::*; use core::ops::{BitAnd, BitOr, BitXor, Not}; -use crate::aes_x86::AesBlock; -use crate::aesni_x2::AesBlockX2; +use crate::{AesBlock, AesBlockX2}; #[derive(Copy, Clone)] #[repr(transparent)] @@ -153,7 +152,7 @@ impl AesBlockX4 { Self(unsafe { _mm512_aesenc_epi128(self.0, round_key.0) }) } - /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumn`s->`AddRoundKey`) + /// Performs one round of AES decryption function (`InvShiftRows`->`InvSubBytes`->`InvMixColumns`->`AddRoundKey`) #[inline] pub fn dec(self, round_key: Self) -> Self { Self(unsafe { _mm512_aesdec_epi128(self.0, round_key.0) }) @@ -165,7 +164,7 @@ impl AesBlockX4 { Self(unsafe { _mm512_aesenclast_epi128(self.0, round_key.0) }) } - /// Performs one round of AES decryption function without `InvMixColumn`s (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) + /// Performs one round of AES decryption function without `InvMixColumns` (`InvShiftRows`->`InvSubBytes`->`AddRoundKey`) #[inline] pub fn dec_last(self, round_key: Self) -> Self { Self(unsafe { _mm512_aesdeclast_epi128(self.0, round_key.0) }) diff --git a/src/lib.rs b/src/lib.rs index ad5dee0..42ec6f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,31 +1,8 @@ #![doc = include_str!("../README.md")] #![no_std] -#![cfg_attr( - all( - feature = "nightly", - any(target_arch = "x86", target_arch = "x86_64"), - target_feature = "vaes" - ), - feature(stdarch_x86_avx512) -)] -#![cfg_attr( - all( - feature = "nightly", - target_arch = "arm", - target_feature = "v8", - target_feature = "aes" - ), - feature(stdarch_arm_neon_intrinsics) -)] -#![cfg_attr( - all( - feature = "nightly", - any(target_arch = "riscv32", target_arch = "riscv64"), - target_feature = "zkne", - target_feature = "zknd" - ), - feature(link_llvm_intrinsics, abi_unadjusted) -)] +#![cfg_attr(aes_x2_impl = "vaes", feature(stdarch_x86_avx512))] +#![cfg_attr(aes_impl = "arm-neon", feature(stdarch_arm_neon_intrinsics))] +#![cfg_attr(aes_impl = "risc-v", feature(link_llvm_intrinsics, abi_unadjusted))] #![allow( internal_features, clippy::identity_op, @@ -41,79 +18,30 @@ use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign}; use cfg_if::cfg_if; -cfg_if! { - if #[cfg(all( - any(target_arch = "x86", target_arch = "x86_64"), - target_feature = "sse4.1", - target_feature = "aes", - ))] { - mod aes_x86; - pub use aes_x86::AesBlock; - use aes_x86::*; - } else if #[cfg(all( - any( - target_arch = "aarch64", - target_arch = "arm64ec", - all(feature = "nightly", target_arch = "arm", target_feature = "v8") - ), - target_feature = "aes" - ))] { - mod aes_arm; - pub use aes_arm::AesBlock; - use aes_arm::*; - } else if #[cfg(all( - feature = "nightly", - target_arch = "riscv64", - target_feature = "zkne", - target_feature = "zknd" - ))] { - mod aes_riscv64; - pub use aes_riscv64::AesBlock; - use aes_riscv64::*; - } else if #[cfg(all( - feature = "nightly", - target_arch = "riscv32", - target_feature = "zkne", - target_feature = "zknd" - ))] { - mod aes_riscv32; - pub use aes_riscv32::AesBlock; - use aes_riscv32::*; - } else { - mod aes_default; - pub use aes_default::AesBlock; - use aes_default::*; - } -} +pub use low::AesBlock; +pub use low_x2::AesBlockX2; +pub use low_x4::AesBlockX4; -cfg_if! { - if #[cfg(all( - feature = "nightly", - any(target_arch = "x86", target_arch = "x86_64"), - target_feature = "vaes" - ))] { - mod aesni_x2; - pub use aesni_x2::AesBlockX2; - } else { - mod aesdefault_x2; - pub use aesdefault_x2::AesBlockX2; - } -} +#[cfg_attr(aes_impl = "x86", path = "./aes_x86.rs")] +#[cfg_attr(any(aes_impl = "neon", aes_impl = "arm-neon"), path = "./aes_arm.rs")] +#[cfg_attr( + all(aes_impl = "risc-v", target_arch = "riscv32"), + path = "./aes_riscv32.rs" +)] +#[cfg_attr( + all(aes_impl = "risc-v", target_arch = "riscv64"), + path = "./aes_riscv64.rs" +)] +#[cfg_attr(aes_impl = "software", path = "./aes_default.rs")] +mod low; -cfg_if! { - if #[cfg(all( - feature = "nightly", - any(target_arch = "x86", target_arch = "x86_64"), - target_feature = "avx512f", - target_feature = "vaes" - ))] { - mod aesni_x4; - pub use aesni_x4::AesBlockX4; - } else { - mod aesdefault_x4; - pub use aesdefault_x4::AesBlockX4; - } -} +#[cfg_attr(aes_x2_impl = "vaes", path = "./aesni_x2.rs")] +#[cfg_attr(aes_x2_impl = "tuple", path = "./aesdefault_x2.rs")] +mod low_x2; + +#[cfg_attr(aes_x4_impl = "avx512f", path = "./aesni_x4.rs")] +#[cfg_attr(aes_x4_impl = "tuple", path = "./aesdefault_x4.rs")] +mod low_x4; #[cfg(test)] mod tests; @@ -413,7 +341,7 @@ impl private::Sealed for Aes128Enc {} impl From<[u8; 16]> for Aes128Enc { fn from(value: [u8; 16]) -> Self { Aes128Enc { - round_keys: keygen_128(value), + round_keys: low::keygen_128(value), } } } @@ -441,7 +369,7 @@ impl private::Sealed for Aes192Enc {} impl From<[u8; 24]> for Aes192Enc { fn from(value: [u8; 24]) -> Self { Aes192Enc { - round_keys: keygen_192(value), + round_keys: low::keygen_192(value), } } } @@ -469,7 +397,7 @@ impl private::Sealed for Aes256Enc {} impl From<[u8; 32]> for Aes256Enc { fn from(value: [u8; 32]) -> Self { Aes256Enc { - round_keys: keygen_256(value), + round_keys: low::keygen_256(value), } } } @@ -510,55 +438,9 @@ fn enc_round_keys(dec_round_keys: &[AesBlock; N]) -> [AesBlock; } cfg_if! { - if #[cfg(any( - all( - any( - target_arch = "aarch64", - target_arch = "arm64ec", - all(feature = "nightly", target_arch = "arm", target_feature = "v8") - ), - target_feature = "aes", - ), all( - feature = "nightly", - target_arch = "riscv32", - target_feature = "zkne", - target_feature = "zknd" - )))] { - macro_rules! aes_intr { - ($($name:ident),*) => {$( - impl $name { - #[inline(always)] - fn pre_enc(self, round_key:Self) -> Self { - let (a, b) = self.into(); - let (rk0, rk1) = round_key.into(); - (a.pre_enc(rk0), b.pre_enc(rk1)).into() - } - - #[inline(always)] - fn pre_enc_last(self, round_key:Self) -> Self { - let (a, b) = self.into(); - let (rk0, rk1) = round_key.into(); - (a.pre_enc_last(rk0), b.pre_enc_last(rk1)).into() - } - - #[inline(always)] - fn pre_dec(self, round_key:Self) -> Self { - let (a, b) = self.into(); - let (rk0, rk1) = round_key.into(); - (a.pre_dec(rk0), b.pre_dec(rk1)).into() - } - - #[inline(always)] - fn pre_dec_last(self, round_key:Self) -> Self { - let (a, b) = self.into(); - let (rk0, rk1) = round_key.into(); - (a.pre_dec_last(rk0), b.pre_dec_last(rk1)).into() - } - } - )*}; - } - - aes_intr!(AesBlockX2, AesBlockX4); + if #[cfg(any(aes_impl = "neon", aes_impl = "arm-neon", all(aes_impl = "risc-v", target_arch = "riscv32")))] { + /// If the implementation of `pre_enc` is faster than `enc` + pub const FAST_PRE_ENC: bool = true; macro_rules! impl_aes { (enc: $round_keys: expr, $plaintext: expr, $max:literal) => {{ @@ -577,6 +459,46 @@ cfg_if! { }}; } } else { + /// If the implementation of `pre_enc` is faster than `enc` + pub const FAST_PRE_ENC: bool = false; + + macro_rules! impl_pre { + ($type:ty) => { + impl $type { + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` -> `MixColumns` + #[inline(always)] + pub fn pre_enc(self, key: Self) -> Self { + (self ^ key).enc(Self::zero()) + } + + /// Performs the operation `AddRoundKey` -> `ShiftRows` -> `SubBytes` + #[inline(always)] + pub fn pre_enc_last(self, key: Self) -> Self { + (self ^ key).enc_last(Self::zero()) + } + + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` -> `InvMixColumns` + #[inline(always)] + pub fn pre_dec(self, key: Self) -> Self { + (self ^ key).dec(Self::zero()) + } + + /// Performs the operation `AddRoundKey` -> `InvShiftRows` -> `InvSubBytes` + #[inline(always)] + pub fn pre_dec_last(self, key: Self) -> Self { + (self ^ key).dec_last(Self::zero()) + } + } + }; + } + + impl_pre!(AesBlock); + + #[cfg(aes_x2_impl = "vaes")] + impl_pre!(AesBlockX2); + #[cfg(aes_x4_impl = "avx512f")] + impl_pre!(AesBlockX4); + macro_rules! impl_aes { (enc: $round_keys: expr, $plaintext: expr, $max:literal) => {{ let mut acc = $plaintext ^ $round_keys[0].into(); @@ -593,7 +515,7 @@ cfg_if! { acc.dec_last($round_keys[$max].into()) }}; } -} + } } impl AesEncrypt<16> for Aes128Enc { diff --git a/src/tests.rs b/src/tests.rs index 6e4bff4..d906ea6 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,6 +1,7 @@ use hex::FromHex; use lazy_static::lazy_static; +use crate::low::*; use crate::*; lazy_static! {