From ec1aea409c593d449805acad5f6468b2354c4b1d Mon Sep 17 00:00:00 2001 From: Nils Hasenbanck Date: Fri, 9 Aug 2024 16:17:31 +0200 Subject: [PATCH] Rework the backend project structure. This cleans up some old cruft. --- .github/workflows/ci.yml | 28 +- Cargo.toml | 8 +- src/{hardware => backend}/aarch64.rs | 16 +- src/backend/mod.rs | 35 ++ src/{hardware => backend}/riscv64.rs | 30 +- src/{fallback/software.rs => backend/soft.rs} | 409 +++++++----------- src/{hardware => backend}/x86.rs | 14 +- src/fallback/fixed.rs | 157 ------- src/fallback/mod.rs | 50 --- src/hardware/mod.rs | 147 ------- src/implementation.rs | 6 +- src/lib.rs | 243 ++++++++--- src/{fallback => }/runtime.rs | 97 +++-- src/tls.rs | 64 +-- src/verification.rs | 31 +- verification/Cargo.toml | 6 +- 16 files changed, 544 insertions(+), 797 deletions(-) rename src/{hardware => backend}/aarch64.rs (98%) create mode 100644 src/backend/mod.rs rename src/{hardware => backend}/riscv64.rs (97%) rename src/{fallback/software.rs => backend/soft.rs} (72%) rename src/{hardware => backend}/x86.rs (98%) delete mode 100644 src/fallback/fixed.rs delete mode 100644 src/fallback/mod.rs delete mode 100644 src/hardware/mod.rs rename src/{fallback => }/runtime.rs (77%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b778a27..f566e57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,18 +19,22 @@ jobs: - name: Linux x86_64 os: ubuntu-24.04 target: x86_64-unknown-linux-gnu + arguments: "" - name: Linux x86 os: ubuntu-24.04 target: i686-unknown-linux-gnu + arguments: "" - name: Linux riscv64gc os: ubuntu-24.04 target: riscv64gc-unknown-linux-gnu + arguments: "--features=experimental_riscv" - name: MacOS aarch64 os: macos-latest target: aarch64-apple-darwin + arguments: "" name: Clippy ${{ matrix.name }} runs-on: ${{ matrix.os }} @@ -59,7 +63,7 @@ jobs: cargo clippy --target ${{ matrix.target }} --no-default-features # Check with default features - cargo clippy --target ${{ matrix.target }} + cargo clippy --target ${{ matrix.target }} ${{ matrix.arguments }} test: timeout-minutes: 30 @@ -98,37 +102,31 @@ jobs: shell: bash run: | set -e - cargo test + cargo test --lib - - name: Tests (force_fallback) + - name: Tests (force_software) shell: bash run: | set -e - cargo test --features=force_fallback + cargo test --lib --features=force_software - - name: Tests (force_no_runtime_detection) + - name: Tests (force_runtime_detection) shell: bash run: | set -e - cargo test --features=force_fallback,force_no_runtime_detection + cargo test --lib --features=force_runtime_detection - name: Tests no-std shell: bash run: | set -e - cargo test --no-default-features + cargo test --lib --no-default-features - - name: Tests no-std (force_fallback) + - name: Tests no-std (force_software) shell: bash run: | set -e - cargo test --no-default-features --features=force_fallback - - - name: Tests no-std (force_no_runtime_detection) - shell: bash - run: | - set -e - cargo test --no-default-features --features=force_fallback,force_no_runtime_detection + cargo test --lib --no-default-features --features=force_software verification: timeout-minutes: 30 diff --git a/Cargo.toml b/Cargo.toml index b27a2c1..4d409a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ tls = ["std"] experimental_riscv = [] ### The following features are only used internally and are unstable ### -# Forces the compiler to always use the fallback (never using the hardware AES directly). -force_fallback = [] -# Deactivates the runtime target feature detection. Combined with `force_fallback` this forced to always using the software AES. -force_no_runtime_detection = [] +# Forces the compiler to enable the runtime detection. +force_runtime_detection = [] +# Forces the compiler to enable the software backend. +force_software = [] # Enables some functionality used for the verification executable used in CI. verification = ["std"] diff --git a/src/hardware/aarch64.rs b/src/backend/aarch64.rs similarity index 98% rename from src/hardware/aarch64.rs rename to src/backend/aarch64.rs index 132a54e..b14e00f 100644 --- a/src/hardware/aarch64.rs +++ b/src/backend/aarch64.rs @@ -430,19 +430,17 @@ pub unsafe fn aes_key_expansion(key: [u8; L]) -> #[cfg(all( test, - not(any( - not(all( - target_arch = "aarch64", - target_feature = "neon", - target_feature = "aes", - )), - feature = "force_fallback" - )) + all( + target_arch = "aarch64", + target_feature = "neon", + target_feature = "aes", + ), + not(feature = "verification") ))] mod tests { use super::*; use crate::constants::{AES128_KEY_COUNT, AES128_KEY_SIZE, AES_BLOCK_SIZE}; - use crate::hardware::tests::{aes128_key_expansion_test, aes256_key_expansion_test}; + use crate::tests::{aes128_key_expansion_test, aes256_key_expansion_test}; #[test] fn test_aes128_key_expansion() { diff --git a/src/backend/mod.rs b/src/backend/mod.rs new file mode 100644 index 0000000..10ff0dd --- /dev/null +++ b/src/backend/mod.rs @@ -0,0 +1,35 @@ +#[cfg(all(target_arch = "aarch64", not(feature = "force_software")))] +pub(crate) mod aarch64; + +#[cfg(all( + target_arch = "riscv64", + feature = "experimental_riscv", + not(feature = "force_software") +))] +pub(crate) mod riscv64; + +#[cfg(all( + any(target_arch = "x86_64", target_arch = "x86"), + not(feature = "force_software") +))] +pub(crate) mod x86; + +#[cfg(any( + not(any( + all( + any(target_arch = "x86_64", target_arch = "x86"), + target_feature = "sse2", + target_feature = "aes", + ), + all(target_arch = "riscv64", feature = "experimental_riscv"), + all( + target_arch = "aarch64", + target_feature = "neon", + target_feature = "aes", + ), + )), + feature = "force_runtime_detection", + feature = "force_software", + feature = "verification", +))] +pub(crate) mod soft; diff --git a/src/hardware/riscv64.rs b/src/backend/riscv64.rs similarity index 97% rename from src/hardware/riscv64.rs rename to src/backend/riscv64.rs index 1440f5f..ad62893 100644 --- a/src/hardware/riscv64.rs +++ b/src/backend/riscv64.rs @@ -1,9 +1,6 @@ -use core::{ - arch::asm, - cell::{Cell, RefCell}, -}; +use core::{arch::asm, cell::Cell}; -use crate::constants::{AES128_KEY_COUNT, AES128_KEY_SIZE, AES256_KEY_COUNT, AES256_KEY_SIZE}; +use crate::constants::{AES128_KEY_COUNT, AES256_KEY_COUNT}; /// A random number generator based on the AES-128 block cipher that runs in CTR mode and has a /// period of 64-bit. @@ -69,6 +66,7 @@ impl Aes128Ctr64 { } #[inline(always)] + #[allow(unused_assignments)] pub(crate) unsafe fn next_impl(&self) -> u128 { // Increment the lower 64 bits. let counter = self.counter.get(); @@ -80,7 +78,7 @@ impl Aes128Ctr64 { // Initialize the state with the counter. let mut state = counter; - let state_ptr = (&mut state).as_mut_ptr(); + let state_ptr = state.as_mut_ptr(); asm!( "vsetivli x0, 4, e32, m1, ta, ma", @@ -208,6 +206,7 @@ impl Aes128Ctr128 { } #[inline(always)] + #[allow(unused_assignments)] pub(crate) unsafe fn next_impl(&self) -> u128 { // Increment the counter. let counter = self.counter.get(); @@ -339,6 +338,7 @@ impl Aes256Ctr64 { } #[inline(always)] + #[allow(unused_assignments)] pub(crate) unsafe fn next_impl(&self) -> u128 { // Increment the lower 64 bits. let counter = self.counter.get(); @@ -350,7 +350,7 @@ impl Aes256Ctr64 { // Initialize the state with the counter. let mut state = counter; - let state_ptr = (&mut state).as_mut_ptr(); + let state_ptr = state.as_mut_ptr(); asm!( "vsetivli x0, 4, e32, m1, ta, ma", @@ -500,6 +500,7 @@ impl Aes256Ctr128 { } #[inline(always)] + #[allow(unused_assignments)] pub(crate) unsafe fn next_impl(&self) -> u128 { // Increment the counter. let counter = self.counter.get(); @@ -585,10 +586,11 @@ impl Aes256Ctr128 { } } +#[allow(unused_assignments)] unsafe fn aes128_key_expansion(key: u128) -> [u128; AES128_KEY_COUNT] { let mut expanded_keys = [0u128; AES128_KEY_COUNT]; let key_ptr = &key as *const u128; - let mut expanded_ptr = (&mut expanded_keys).as_mut_ptr(); + let mut expanded_ptr = expanded_keys.as_mut_ptr(); asm!( "vsetivli x0, 4, e32, m4, ta, ma", @@ -633,10 +635,11 @@ unsafe fn aes128_key_expansion(key: u128) -> [u128; AES128_KEY_COUNT] { expanded_keys } +#[allow(unused_assignments)] unsafe fn aes256_key_expansion(key: [u128; 2]) -> [u128; AES256_KEY_COUNT] { let mut expanded_keys = [0u128; AES256_KEY_COUNT]; let mut key_ptr = &key as *const u128; - let mut expanded_ptr = (&mut expanded_keys).as_mut_ptr(); + let mut expanded_ptr = expanded_keys.as_mut_ptr(); asm!( "vsetivli x0, 4, e32, m4, ta, ma", @@ -695,11 +698,16 @@ unsafe fn aes256_key_expansion(key: [u128; 2]) -> [u128; AES256_KEY_COUNT] { expanded_keys } -#[cfg(all(test, not(feature = "force_fallback")))] +#[cfg(all( + test, + target_arch = "riscv64", + feature = "experimental_riscv", + not(feature = "verification") +))] mod tests { use super::*; use crate::constants::{AES128_KEY_COUNT, AES128_KEY_SIZE, AES_BLOCK_SIZE}; - use crate::hardware::tests::{aes128_key_expansion_test, aes256_key_expansion_test}; + use crate::tests::{aes128_key_expansion_test, aes256_key_expansion_test}; #[test] fn test_aes128_key_expansion() { diff --git a/src/fallback/software.rs b/src/backend/soft.rs similarity index 72% rename from src/fallback/software.rs rename to src/backend/soft.rs index d0c673c..63efcf7 100644 --- a/src/fallback/software.rs +++ b/src/backend/soft.rs @@ -20,8 +20,11 @@ //! provide also better inner mutability this way (since we want to optimize the fast path, when //! hardware based AES is found). //! + use crate::constants::{AES128_KEY_SIZE, AES256_KEY_SIZE, AES_BLOCK_SIZE}; +use core::cell::RefCell; + const BLOCK_COUNT: usize = 4; const FIX_SLICE_128_KEYS_SIZE: usize = 88; const FIX_SLICE_256_KEYS_SIZE: usize = 120; @@ -42,7 +45,10 @@ type FixsliceKeys256 = [u64; FIX_SLICE_256_KEYS_SIZE]; type State = [u64; 8]; #[derive(Clone)] -pub struct Aes128Ctr64 { +pub struct Aes128Ctr64(RefCell); + +#[derive(Clone)] +struct Aes128Ctr64Inner { counter: [u64; 2], round_keys: FixsliceKeys128, batch_blocks: BatchBlocks, @@ -51,10 +57,11 @@ pub struct Aes128Ctr64 { impl Drop for Aes128Ctr64 { fn drop(&mut self) { - self.counter = [0, 0]; - self.round_keys = [0; FIX_SLICE_128_KEYS_SIZE]; - self.batch_blocks = [Block::default(); BLOCK_COUNT]; - self.batch_num = 0; + let mut inner = self.0.borrow_mut(); + inner.counter = [0, 0]; + inner.round_keys = [0; FIX_SLICE_128_KEYS_SIZE]; + inner.batch_blocks = [Block::default(); BLOCK_COUNT]; + inner.batch_num = 0; core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); } } @@ -62,29 +69,30 @@ impl Drop for Aes128Ctr64 { impl Aes128Ctr64 { #[cfg(feature = "tls")] pub(crate) const fn zeroed() -> Self { - Self { + Self(RefCell::new(Aes128Ctr64Inner { counter: [0; 2], round_keys: [0; FIX_SLICE_128_KEYS_SIZE], batch_blocks: [[0; AES_BLOCK_SIZE]; BLOCK_COUNT], batch_num: BLOCK_COUNT, - } + })) } pub(crate) fn from_seed_impl(key: [u8; 16], nonce: [u8; 8], counter: [u8; 8]) -> Self { let counter = [u64::from_le_bytes(counter), u64::from_le_bytes(nonce)]; let round_keys: FixsliceKeys128 = aes128_key_expansion(key); - Self { + Self(RefCell::new(Aes128Ctr64Inner { counter, round_keys, batch_blocks: [Block::default(); BLOCK_COUNT], batch_num: BLOCK_COUNT, - } + })) } - pub(crate) fn seed_impl(&mut self, key: [u8; 16], nonce: [u8; 8], counter: [u8; 8]) { - self.counter = [u64::from_le_bytes(counter), u64::from_le_bytes(nonce)]; - self.round_keys = aes128_key_expansion(key); + pub(crate) fn seed_impl(&self, key: [u8; 16], nonce: [u8; 8], counter: [u8; 8]) { + let mut inner = self.0.borrow_mut(); + inner.counter = [u64::from_le_bytes(counter), u64::from_le_bytes(nonce)]; + inner.round_keys = aes128_key_expansion(key); } pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { @@ -92,46 +100,52 @@ impl Aes128Ctr64 { } pub(crate) fn counter_impl(&self) -> u64 { - self.counter[0] + let inner = self.0.borrow(); + inner.counter[0] } #[inline(never)] - pub(crate) fn next_impl(&mut self) -> u128 { + pub(crate) fn next_impl(&self) -> u128 { + let mut inner = self.0.borrow_mut(); + // We have blocks left that we can return. - if self.batch_num < BLOCK_COUNT { - let block = self.batch_blocks[self.batch_num]; - self.batch_num = self.batch_num.wrapping_add(1); + if inner.batch_num < BLOCK_COUNT { + let block = inner.batch_blocks[inner.batch_num]; + inner.batch_num = inner.batch_num.wrapping_add(1); return u128::from_le_bytes(block); } // Fill all blocks with the correct data. - let counter_0 = self.counter[0]; - let counter_1 = self.counter[0].wrapping_add(1); - let counter_2 = self.counter[0].wrapping_add(2); - let counter_3 = self.counter[0].wrapping_add(3); - let nonce = self.counter[1]; + let counter_0 = inner.counter[0]; + let counter_1 = inner.counter[0].wrapping_add(1); + let counter_2 = inner.counter[0].wrapping_add(2); + let counter_3 = inner.counter[0].wrapping_add(3); + let nonce = inner.counter[1]; - self.counter[0] = self.counter[0].wrapping_add(4); + inner.counter[0] = inner.counter[0].wrapping_add(4); - self.batch_blocks[0][..8].copy_from_slice(&counter_0.to_le_bytes()); - self.batch_blocks[0][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks[1][..8].copy_from_slice(&counter_1.to_le_bytes()); - self.batch_blocks[1][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks[2][..8].copy_from_slice(&counter_2.to_le_bytes()); - self.batch_blocks[2][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks[3][..8].copy_from_slice(&counter_3.to_le_bytes()); - self.batch_blocks[3][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[0][..8].copy_from_slice(&counter_0.to_le_bytes()); + inner.batch_blocks[0][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[1][..8].copy_from_slice(&counter_1.to_le_bytes()); + inner.batch_blocks[1][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[2][..8].copy_from_slice(&counter_2.to_le_bytes()); + inner.batch_blocks[2][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[3][..8].copy_from_slice(&counter_3.to_le_bytes()); + inner.batch_blocks[3][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks = aes128_encrypt(&self.round_keys, &self.batch_blocks); + inner.batch_blocks = aes128_encrypt(&inner.round_keys, &inner.batch_blocks); // Return the first encrypted counter as u128 - self.batch_num = 1; - u128::from_le_bytes(self.batch_blocks[0]) + inner.batch_num = 1; + u128::from_le_bytes(inner.batch_blocks[0]) } } #[derive(Clone)] -pub struct Aes128Ctr128 { +pub struct Aes128Ctr128(RefCell); + +#[derive(Clone)] +struct Aes128Ctr128Inner { counter: u128, round_keys: FixsliceKeys128, batch_blocks: BatchBlocks, @@ -140,24 +154,27 @@ pub struct Aes128Ctr128 { impl Drop for Aes128Ctr128 { fn drop(&mut self) { - self.counter = 0; - self.round_keys = [0; FIX_SLICE_128_KEYS_SIZE]; - self.batch_blocks = [Block::default(); BLOCK_COUNT]; - self.batch_num = 0; + let mut inner = self.0.borrow_mut(); + inner.counter = 0; + inner.round_keys = [0; FIX_SLICE_128_KEYS_SIZE]; + inner.batch_blocks = [Block::default(); BLOCK_COUNT]; + inner.batch_num = 0; core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); } } impl Aes128Ctr128 { - pub(crate) fn jump_impl(&mut self) -> Self { + pub(crate) fn jump_impl(&self) -> Self { let clone = self.clone(); - self.counter += 1 << 64; + let mut inner = self.0.borrow_mut(); + inner.counter += 1 << 64; clone } - pub(crate) fn long_jump_impl(&mut self) -> Self { + pub(crate) fn long_jump_impl(&self) -> Self { let clone = self.clone(); - self.counter += 1 << 96; + let mut inner = self.0.borrow_mut(); + inner.counter += 1 << 96; clone } @@ -165,17 +182,18 @@ impl Aes128Ctr128 { let counter = u128::from_le_bytes(counter); let round_keys: FixsliceKeys128 = aes128_key_expansion(key); - Self { + Self(RefCell::new(Aes128Ctr128Inner { counter, round_keys, batch_blocks: [Block::default(); BLOCK_COUNT], batch_num: BLOCK_COUNT, - } + })) } - pub(crate) fn seed_impl(&mut self, key: [u8; 16], counter: [u8; 16]) { - self.counter = u128::from_le_bytes(counter); - self.round_keys = aes128_key_expansion(key); + pub(crate) fn seed_impl(&self, key: [u8; 16], counter: [u8; 16]) { + let mut inner = self.0.borrow_mut(); + inner.counter = u128::from_le_bytes(counter); + inner.round_keys = aes128_key_expansion(key); } pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { @@ -183,41 +201,47 @@ impl Aes128Ctr128 { } pub(crate) fn counter_impl(&self) -> u128 { - self.counter + let inner = self.0.borrow(); + inner.counter } #[inline(never)] - pub(crate) fn next_impl(&mut self) -> u128 { + pub(crate) fn next_impl(&self) -> u128 { + let mut inner = self.0.borrow_mut(); + // We have blocks left that we can return. - if self.batch_num < BLOCK_COUNT { - let block = self.batch_blocks[self.batch_num]; - self.batch_num = self.batch_num.wrapping_add(1); + if inner.batch_num < BLOCK_COUNT { + let block = inner.batch_blocks[inner.batch_num]; + inner.batch_num = inner.batch_num.wrapping_add(1); return u128::from_le_bytes(block); } // Fill all blocks with the correct data. - let counter_0 = self.counter; - let counter_1 = self.counter.wrapping_add(1); - let counter_2 = self.counter.wrapping_add(2); - let counter_3 = self.counter.wrapping_add(3); + let counter_0 = inner.counter; + let counter_1 = inner.counter.wrapping_add(1); + let counter_2 = inner.counter.wrapping_add(2); + let counter_3 = inner.counter.wrapping_add(3); - self.counter = self.counter.wrapping_add(4); + inner.counter = inner.counter.wrapping_add(4); - self.batch_blocks[0].copy_from_slice(&counter_0.to_le_bytes()); - self.batch_blocks[1].copy_from_slice(&counter_1.to_le_bytes()); - self.batch_blocks[2].copy_from_slice(&counter_2.to_le_bytes()); - self.batch_blocks[3].copy_from_slice(&counter_3.to_le_bytes()); + inner.batch_blocks[0].copy_from_slice(&counter_0.to_le_bytes()); + inner.batch_blocks[1].copy_from_slice(&counter_1.to_le_bytes()); + inner.batch_blocks[2].copy_from_slice(&counter_2.to_le_bytes()); + inner.batch_blocks[3].copy_from_slice(&counter_3.to_le_bytes()); - self.batch_blocks = aes128_encrypt(&self.round_keys, &self.batch_blocks); + inner.batch_blocks = aes128_encrypt(&inner.round_keys, &inner.batch_blocks); // Return the first encrypted counter as u128 - self.batch_num = 1; - u128::from_le_bytes(self.batch_blocks[0]) + inner.batch_num = 1; + u128::from_le_bytes(inner.batch_blocks[0]) } } #[derive(Clone)] -pub struct Aes256Ctr64 { +pub struct Aes256Ctr64(RefCell); + +#[derive(Clone)] +struct Aes256Ctr64Inner { counter: [u64; 2], round_keys: FixsliceKeys256, batch_blocks: BatchBlocks, @@ -226,10 +250,11 @@ pub struct Aes256Ctr64 { impl Drop for Aes256Ctr64 { fn drop(&mut self) { - self.counter = [0, 0]; - self.round_keys = [0; FIX_SLICE_256_KEYS_SIZE]; - self.batch_blocks = [Block::default(); BLOCK_COUNT]; - self.batch_num = 0; + let mut inner = self.0.borrow_mut(); + inner.counter = [0, 0]; + inner.round_keys = [0; FIX_SLICE_256_KEYS_SIZE]; + inner.batch_blocks = [Block::default(); BLOCK_COUNT]; + inner.batch_num = 0; core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); } } @@ -239,17 +264,18 @@ impl Aes256Ctr64 { let counter = [u64::from_le_bytes(counter), u64::from_le_bytes(nonce)]; let round_keys: FixsliceKeys256 = aes256_key_expansion(key); - Self { + Self(RefCell::new(Aes256Ctr64Inner { counter, round_keys, batch_blocks: [Block::default(); BLOCK_COUNT], batch_num: BLOCK_COUNT, - } + })) } - pub(crate) fn seed_impl(&mut self, key: [u8; 32], nonce: [u8; 8], counter: [u8; 8]) { - self.counter = [u64::from_le_bytes(counter), u64::from_le_bytes(nonce)]; - self.round_keys = aes256_key_expansion(key); + pub(crate) fn seed_impl(&self, key: [u8; 32], nonce: [u8; 8], counter: [u8; 8]) { + let mut inner = self.0.borrow_mut(); + inner.counter = [u64::from_le_bytes(counter), u64::from_le_bytes(nonce)]; + inner.round_keys = aes256_key_expansion(key); } pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { @@ -257,45 +283,51 @@ impl Aes256Ctr64 { } pub(crate) fn counter_impl(&self) -> u64 { - self.counter[0] + let inner = self.0.borrow(); + inner.counter[0] } - pub(crate) fn next_impl(&mut self) -> u128 { + pub(crate) fn next_impl(&self) -> u128 { + let mut inner = self.0.borrow_mut(); + // We have blocks left that we can return. - if self.batch_num < BLOCK_COUNT { - let block = self.batch_blocks[self.batch_num]; - self.batch_num = self.batch_num.wrapping_add(1); + if inner.batch_num < BLOCK_COUNT { + let block = inner.batch_blocks[inner.batch_num]; + inner.batch_num = inner.batch_num.wrapping_add(1); return u128::from_le_bytes(block); } // Fill all blocks with the correct data. - let counter_0 = self.counter[0]; - let counter_1 = self.counter[0].wrapping_add(1); - let counter_2 = self.counter[0].wrapping_add(2); - let counter_3 = self.counter[0].wrapping_add(3); - let nonce = self.counter[1]; + let counter_0 = inner.counter[0]; + let counter_1 = inner.counter[0].wrapping_add(1); + let counter_2 = inner.counter[0].wrapping_add(2); + let counter_3 = inner.counter[0].wrapping_add(3); + let nonce = inner.counter[1]; - self.counter[0] = self.counter[0].wrapping_add(4); + inner.counter[0] = inner.counter[0].wrapping_add(4); - self.batch_blocks[0][..8].copy_from_slice(&counter_0.to_le_bytes()); - self.batch_blocks[0][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks[1][..8].copy_from_slice(&counter_1.to_le_bytes()); - self.batch_blocks[1][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks[2][..8].copy_from_slice(&counter_2.to_le_bytes()); - self.batch_blocks[2][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks[3][..8].copy_from_slice(&counter_3.to_le_bytes()); - self.batch_blocks[3][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[0][..8].copy_from_slice(&counter_0.to_le_bytes()); + inner.batch_blocks[0][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[1][..8].copy_from_slice(&counter_1.to_le_bytes()); + inner.batch_blocks[1][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[2][..8].copy_from_slice(&counter_2.to_le_bytes()); + inner.batch_blocks[2][8..].copy_from_slice(&nonce.to_le_bytes()); + inner.batch_blocks[3][..8].copy_from_slice(&counter_3.to_le_bytes()); + inner.batch_blocks[3][8..].copy_from_slice(&nonce.to_le_bytes()); - self.batch_blocks = aes256_encrypt(&self.round_keys, &self.batch_blocks); + inner.batch_blocks = aes256_encrypt(&inner.round_keys, &inner.batch_blocks); // Return the first encrypted counter as u128 - self.batch_num = 1; - u128::from_le_bytes(self.batch_blocks[0]) + inner.batch_num = 1; + u128::from_le_bytes(inner.batch_blocks[0]) } } #[derive(Clone)] -pub struct Aes256Ctr128 { +pub struct Aes256Ctr128(RefCell); + +#[derive(Clone)] +struct Aes256Ctr128Inner { pub(crate) counter: u128, round_keys: FixsliceKeys256, batch_blocks: BatchBlocks, @@ -304,24 +336,27 @@ pub struct Aes256Ctr128 { impl Drop for Aes256Ctr128 { fn drop(&mut self) { - self.counter = 0; - self.round_keys = [0; FIX_SLICE_256_KEYS_SIZE]; - self.batch_blocks = [Block::default(); BLOCK_COUNT]; - self.batch_num = 0; + let mut inner = self.0.borrow_mut(); + inner.counter = 0; + inner.round_keys = [0; FIX_SLICE_256_KEYS_SIZE]; + inner.batch_blocks = [Block::default(); BLOCK_COUNT]; + inner.batch_num = 0; core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); } } impl Aes256Ctr128 { - pub(crate) fn jump_impl(&mut self) -> Self { + pub(crate) fn jump_impl(&self) -> Self { let clone = self.clone(); - self.counter += 1 << 64; + let mut inner = self.0.borrow_mut(); + inner.counter += 1 << 64; clone } - pub(crate) fn long_jump_impl(&mut self) -> Self { + pub(crate) fn long_jump_impl(&self) -> Self { let clone = self.clone(); - self.counter += 1 << 96; + let mut inner = self.0.borrow_mut(); + inner.counter += 1 << 96; clone } @@ -329,17 +364,18 @@ impl Aes256Ctr128 { let counter = u128::from_le_bytes(counter); let round_keys: FixsliceKeys256 = aes256_key_expansion(key); - Self { + Self(RefCell::new(Aes256Ctr128Inner { counter, round_keys, batch_blocks: [Block::default(); BLOCK_COUNT], batch_num: BLOCK_COUNT, - } + })) } - pub(crate) fn seed_impl(&mut self, key: [u8; 32], counter: [u8; 16]) { - self.counter = u128::from_le_bytes(counter); - self.round_keys = aes256_key_expansion(key); + pub(crate) fn seed_impl(&self, key: [u8; 32], counter: [u8; 16]) { + let mut inner = self.0.borrow_mut(); + inner.counter = u128::from_le_bytes(counter); + inner.round_keys = aes256_key_expansion(key); } pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { @@ -347,36 +383,39 @@ impl Aes256Ctr128 { } pub(crate) fn counter_impl(&self) -> u128 { - self.counter + let inner = self.0.borrow(); + inner.counter } #[inline(never)] - pub(crate) fn next_impl(&mut self) -> u128 { + pub(crate) fn next_impl(&self) -> u128 { + let mut inner = self.0.borrow_mut(); + // We have blocks left that we can return. - if self.batch_num < BLOCK_COUNT { - let block = self.batch_blocks[self.batch_num]; - self.batch_num = self.batch_num.wrapping_add(1); + if inner.batch_num < BLOCK_COUNT { + let block = inner.batch_blocks[inner.batch_num]; + inner.batch_num = inner.batch_num.wrapping_add(1); return u128::from_le_bytes(block); } // Fill all blocks with the correct data. - let counter_0 = self.counter; - let counter_1 = self.counter.wrapping_add(1); - let counter_2 = self.counter.wrapping_add(2); - let counter_3 = self.counter.wrapping_add(3); + let counter_0 = inner.counter; + let counter_1 = inner.counter.wrapping_add(1); + let counter_2 = inner.counter.wrapping_add(2); + let counter_3 = inner.counter.wrapping_add(3); - self.counter = self.counter.wrapping_add(4); + inner.counter = inner.counter.wrapping_add(4); - self.batch_blocks[0].copy_from_slice(&counter_0.to_le_bytes()); - self.batch_blocks[1].copy_from_slice(&counter_1.to_le_bytes()); - self.batch_blocks[2].copy_from_slice(&counter_2.to_le_bytes()); - self.batch_blocks[3].copy_from_slice(&counter_3.to_le_bytes()); + inner.batch_blocks[0].copy_from_slice(&counter_0.to_le_bytes()); + inner.batch_blocks[1].copy_from_slice(&counter_1.to_le_bytes()); + inner.batch_blocks[2].copy_from_slice(&counter_2.to_le_bytes()); + inner.batch_blocks[3].copy_from_slice(&counter_3.to_le_bytes()); - self.batch_blocks = aes256_encrypt(&self.round_keys, &self.batch_blocks); + inner.batch_blocks = aes256_encrypt(&inner.round_keys, &inner.batch_blocks); // Return the first encrypted counter as u128 - self.batch_num = 1; - u128::from_le_bytes(self.batch_blocks[0]) + inner.batch_num = 1; + u128::from_le_bytes(inner.batch_blocks[0]) } } @@ -1103,117 +1142,3 @@ fn rotate_rows_and_columns_2_2(x: u64) -> u64 { const DISTANCE_1: u32 = ror_distance(1, 2); (ror(x, DISTANCE_0) & 0x00FF00FF00FF00FF) | (ror(x, DISTANCE_1) & 0xFF00FF00FF00FF00) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::constants::{AES128_KEY_SIZE, AES256_KEY_SIZE, AES_BLOCK_SIZE}; - - #[test] - fn test_aes128_64_ctr() { - let key: [u8; AES128_KEY_SIZE] = [ - 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, - 0x4F, 0x3C, - ]; - let nonce: [u8; 8] = [0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7]; - - let nonce = u64::from_le_bytes(nonce); - let round_keys = aes128_key_expansion(key); - - let mut prng = Aes128Ctr64 { - counter: [0, nonce], - round_keys, - batch_blocks: [[0; AES_BLOCK_SIZE]; BLOCK_COUNT], - batch_num: BLOCK_COUNT, - }; - - let expected1: u128 = 318787209764863539074968061615330655656; - let expected2: u128 = 326852671706151165476845928255574082697; - - assert_eq!(prng.next_impl().to_le_bytes(), expected1.to_le_bytes()); - assert_eq!(prng.next_impl().to_le_bytes(), expected2.to_le_bytes()); - } - - #[test] - fn test_aes128_128_ctr() { - let key: [u8; AES128_KEY_SIZE] = [ - 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, - 0x4F, 0x3C, - ]; - let nonce: [u8; 16] = [ - 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, - 0xFE, 0xFF, - ]; - - let counter = u128::from_le_bytes(nonce); - let round_keys = aes128_key_expansion(key); - - let mut prng = Aes128Ctr128 { - counter, - round_keys, - batch_blocks: [[0; AES_BLOCK_SIZE]; BLOCK_COUNT], - batch_num: BLOCK_COUNT, - }; - - let expected1: u128 = 303903166029529670262962909209442618604; - let expected2: u128 = 7273797019947380857539426679138531822; - - assert_eq!(prng.next_impl().to_le_bytes(), expected1.to_le_bytes()); - assert_eq!(prng.next_impl().to_le_bytes(), expected2.to_le_bytes()); - } - - #[test] - fn test_aes256_64_ctr() { - let key: [u8; AES256_KEY_SIZE] = [ - 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, - 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, - 0x09, 0x14, 0xDF, 0xF4, - ]; - let nonce: [u8; 8] = [0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7]; - - let nonce = u64::from_le_bytes(nonce); - let round_keys = aes256_key_expansion(key); - - let mut prng = Aes256Ctr64 { - counter: [0, nonce], - round_keys, - batch_blocks: [[0; AES_BLOCK_SIZE]; BLOCK_COUNT], - batch_num: BLOCK_COUNT, - }; - - let expected1: u128 = 117682664062987963529076142802143365131; - let expected2: u128 = 269366866900604671011853374041972895696; - - assert_eq!(prng.next_impl().to_le_bytes(), expected1.to_le_bytes()); - assert_eq!(prng.next_impl().to_le_bytes(), expected2.to_le_bytes()); - } - - #[test] - fn test_aes256_128_ctr() { - let key: [u8; AES256_KEY_SIZE] = [ - 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, - 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, - 0x09, 0x14, 0xDF, 0xF4, - ]; - let nonce: [u8; 16] = [ - 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, - 0xFE, 0xFF, - ]; - - let counter = u128::from_le_bytes(nonce); - let round_keys = aes256_key_expansion(key); - - let mut prng = Aes256Ctr128 { - counter, - round_keys, - batch_blocks: [[0; AES_BLOCK_SIZE]; BLOCK_COUNT], - batch_num: BLOCK_COUNT, - }; - - let expected1: u128 = 3683301436323601079144479715388940043; - let expected2: u128 = 176305260822880786646713066665859703433; - - assert_eq!(prng.next_impl().to_le_bytes(), expected1.to_le_bytes()); - assert_eq!(prng.next_impl().to_le_bytes(), expected2.to_le_bytes()); - } -} diff --git a/src/hardware/x86.rs b/src/backend/x86.rs similarity index 98% rename from src/hardware/x86.rs rename to src/backend/x86.rs index bb69a3a..5acf817 100644 --- a/src/hardware/x86.rs +++ b/src/backend/x86.rs @@ -478,19 +478,15 @@ pub unsafe fn aes256_key_expansion(key: [u8; AES256_KEY_SIZE]) -> [__m128i; AES2 #[cfg(all( test, - not(any( - not(all( - target_arch = "x86_64", - target_feature = "sse2", - target_feature = "aes", - )), - feature = "force_fallback" - )) + target_arch = "x86_64", + target_feature = "sse2", + target_feature = "aes", + not(feature = "verification") ))] mod tests { use super::*; use crate::constants::AES_BLOCK_SIZE; - use crate::hardware::tests::{aes128_key_expansion_test, aes256_key_expansion_test}; + use crate::tests::{aes128_key_expansion_test, aes256_key_expansion_test}; #[test] fn test_aes128_key_expansion() { diff --git a/src/fallback/fixed.rs b/src/fallback/fixed.rs deleted file mode 100644 index ba5058c..0000000 --- a/src/fallback/fixed.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! The fixed fallback, when STD is not available or the platform has no hardware based AES support. -use core::cell::RefCell; - -use super::software::Aes128Ctr128 as Aes128Ctr128Software; -use super::software::Aes128Ctr64 as Aes128Ctr64Software; -use super::software::Aes256Ctr128 as Aes256Ctr128Software; -use super::software::Aes256Ctr64 as Aes256Ctr64Software; - -/// A random number generator based on the AES-128 block cipher that runs in CTR mode and has a -/// period of 64-bit. -/// -/// The full 10 rounds of encryption are used. -#[derive(Clone)] -pub struct Aes128Ctr64(RefCell); - -impl Aes128Ctr64 { - #[cfg(feature = "tls")] - pub(crate) fn zeroed() -> Self { - let software = Aes128Ctr64Software::zeroed(); - Self(RefCell::new(software)) - } - - pub(crate) fn from_seed_impl(key: [u8; 16], nonce: [u8; 8], counter: [u8; 8]) -> Self { - let software = Aes128Ctr64Software::from_seed_impl(key, nonce, counter); - Self(RefCell::new(software)) - } - - pub(crate) fn seed_impl(&self, key: [u8; 16], nonce: [u8; 8], counter: [u8; 8]) { - self.0.borrow_mut().seed_impl(key, nonce, counter); - } - - pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { - self.0.borrow_mut().is_hardware_accelerated_impl() - } - - pub(crate) fn counter_impl(&self) -> u64 { - self.0.borrow_mut().counter_impl() - } - - #[inline(always)] - pub(crate) fn next_impl(&self) -> u128 { - self.0.borrow_mut().next_impl() - } -} - -/// A random number generator based on the AES-128 block cipher that runs in CTR mode and has a -/// period of 128-bit. -/// -/// The full 10 rounds of encryption are used. -#[derive(Clone)] -pub struct Aes128Ctr128(RefCell); - -impl Aes128Ctr128 { - pub(crate) fn jump_impl(&self) -> Self { - let clone = self.0.borrow_mut().jump_impl(); - Self(RefCell::new(clone)) - } - - pub(crate) fn long_jump_impl(&self) -> Self { - let clone = self.0.borrow_mut().long_jump_impl(); - Self(RefCell::new(clone)) - } - - pub(crate) fn from_seed_impl(key: [u8; 16], counter: [u8; 16]) -> Self { - let software = Aes128Ctr128Software::from_seed_impl(key, counter); - Self(RefCell::new(software)) - } - - pub(crate) fn seed_impl(&self, key: [u8; 16], counter: [u8; 16]) { - self.0.borrow_mut().seed_impl(key, counter); - } - - pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { - self.0.borrow_mut().is_hardware_accelerated_impl() - } - - pub(crate) fn counter_impl(&self) -> u128 { - self.0.borrow_mut().counter_impl() - } - - #[inline(always)] - pub(crate) fn next_impl(&self) -> u128 { - self.0.borrow_mut().next_impl() - } -} - -/// A random number generator based on the AES-256 block cipher that runs in CTR mode and has a -/// period of 64-bit. -/// -/// The full 14 rounds of encryption are used. -#[derive(Clone)] -pub struct Aes256Ctr64(RefCell); - -impl Aes256Ctr64 { - pub(crate) fn from_seed_impl(key: [u8; 32], nonce: [u8; 8], counter: [u8; 8]) -> Self { - let software = Aes256Ctr64Software::from_seed_impl(key, nonce, counter); - Self(RefCell::new(software)) - } - - pub(crate) fn seed_impl(&self, key: [u8; 32], nonce: [u8; 8], counter: [u8; 8]) { - self.0.borrow_mut().seed_impl(key, nonce, counter); - } - - pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { - self.0.borrow_mut().is_hardware_accelerated_impl() - } - - pub(crate) fn counter_impl(&self) -> u64 { - self.0.borrow_mut().counter_impl() - } - - #[inline(always)] - pub(crate) fn next_impl(&self) -> u128 { - self.0.borrow_mut().next_impl() - } -} - -/// A random number generator based on the AES-256 block cipher that runs in CTR mode and has a -/// period of 128-bit. -/// -/// The full 14 rounds of encryption are used. -#[derive(Clone)] -pub struct Aes256Ctr128(RefCell); - -impl Aes256Ctr128 { - pub(crate) fn jump_impl(&self) -> Self { - let clone = self.0.borrow_mut().jump_impl(); - Self(RefCell::new(clone)) - } - - pub(crate) fn long_jump_impl(&self) -> Self { - let clone = self.0.borrow_mut().long_jump_impl(); - Self(RefCell::new(clone)) - } - - pub(crate) fn from_seed_impl(key: [u8; 32], counter: [u8; 16]) -> Self { - let software = Aes256Ctr128Software::from_seed_impl(key, counter); - Self(RefCell::new(software)) - } - - pub(crate) fn seed_impl(&self, key: [u8; 32], counter: [u8; 16]) { - self.0.borrow_mut().seed_impl(key, counter); - } - - pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { - self.0.borrow_mut().is_hardware_accelerated_impl() - } - - pub(crate) fn counter_impl(&self) -> u128 { - self.0.borrow_mut().counter_impl() - } - - #[inline(always)] - pub(crate) fn next_impl(&self) -> u128 { - self.0.borrow_mut().next_impl() - } -} diff --git a/src/fallback/mod.rs b/src/fallback/mod.rs deleted file mode 100644 index 1b09ed8..0000000 --- a/src/fallback/mod.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! We have two fallbacks: -//! - Runtime: Uses the STD library for targets that support hardware based AES to query if the -//! current CPU has hardware based AES. If not, it will fall back to the software -//! AES implementation. -//! - Fixed: Always uses the software AES implementation. -#[cfg(all( - any( - not(all( - feature = "std", - any(target_arch = "aarch64", target_arch = "x86_64", target_arch = "x86") - )), - feature = "force_no_runtime_detection" - ), - not(feature = "verification") -))] -mod fixed; - -#[cfg(all( - not(any( - not(all( - feature = "std", - any(target_arch = "aarch64", target_arch = "x86_64", target_arch = "x86") - )), - feature = "force_no_runtime_detection" - )), - not(feature = "verification") -))] -mod runtime; - -pub(crate) mod software; - -#[cfg(all( - feature = "std", - any(target_arch = "aarch64", target_arch = "x86_64", target_arch = "x86"), - not(feature = "force_no_runtime_detection"), - not(feature = "verification") -))] -pub use runtime::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; - -#[cfg(all( - any( - not(all( - feature = "std", - any(target_arch = "aarch64", target_arch = "x86_64", target_arch = "x86") - )), - feature = "force_no_runtime_detection" - ), - not(feature = "verification") -))] -pub use fixed::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; diff --git a/src/hardware/mod.rs b/src/hardware/mod.rs deleted file mode 100644 index b0e41b0..0000000 --- a/src/hardware/mod.rs +++ /dev/null @@ -1,147 +0,0 @@ -#[cfg(target_arch = "aarch64")] -pub mod aarch64; -#[cfg(target_arch = "riscv64")] -pub mod riscv64; -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] -pub mod x86; - -#[cfg(target_arch = "aarch64")] -pub use aarch64::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; -#[cfg(target_arch = "riscv64")] -pub use riscv64::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; -#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] -pub use x86::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; - -#[cfg(all( - test, - not(any( - not(any( - all( - any(target_arch = "x86_64", target_arch = "x86"), - target_feature = "sse2", - target_feature = "aes", - ), - all(target_arch = "riscv64", feature = "experimental_riscv"), - all( - target_arch = "aarch64", - target_feature = "neon", - target_feature = "aes", - ), - )), - feature = "force_fallback" - )) -))] -mod tests { - use super::*; - use crate::constants::{ - AES128_KEY_COUNT, AES128_KEY_SIZE, AES256_KEY_COUNT, AES256_KEY_SIZE, AES_BLOCK_SIZE, - }; - use hex_literal::hex; - - // From NIST FIPS 197 - const TV_AES128_KEY: [u8; AES128_KEY_SIZE] = hex!("000102030405060708090a0b0c0d0e0f"); - const TV_AES128_IV: [u8; AES_BLOCK_SIZE] = hex!("00112233445566778899aabbccddeeff"); - const TV_AES128_ROUND_KEYS: [[u8; AES_BLOCK_SIZE]; AES128_KEY_COUNT] = [ - hex!("000102030405060708090a0b0c0d0e0f"), - hex!("d6aa74fdd2af72fadaa678f1d6ab76fe"), - hex!("b692cf0b643dbdf1be9bc5006830b3fe"), - hex!("b6ff744ed2c2c9bf6c590cbf0469bf41"), - hex!("47f7f7bc95353e03f96c32bcfd058dfd"), - hex!("3caaa3e8a99f9deb50f3af57adf622aa"), - hex!("5e390f7df7a69296a7553dc10aa31f6b"), - hex!("14f9701ae35fe28c440adf4d4ea9c026"), - hex!("47438735a41c65b9e016baf4aebf7ad2"), - hex!("549932d1f08557681093ed9cbe2c974e"), - hex!("13111d7fe3944a17f307a78b4d2b30c5"), - ]; - const TV_AES128_NEXT_0: [u8; AES_BLOCK_SIZE] = hex!("69c4e0d86a7b0430d8cdb78070b4c55a"); - const TV_AES128_NEXT_1: [u8; AES_BLOCK_SIZE] = hex!("a556156c72876577f67f95a9d9e640a7"); - - // From NIST FIPS 197 - const TV_AES256_KEY: [u8; AES256_KEY_SIZE] = - hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); - const TV_AES256_IV: [u8; AES_BLOCK_SIZE] = hex!("00112233445566778899aabbccddeeff"); - const TV_AES256_ROUND_KEYS: [[u8; AES_BLOCK_SIZE]; AES256_KEY_COUNT] = [ - hex!("000102030405060708090a0b0c0d0e0f"), - hex!("101112131415161718191a1b1c1d1e1f"), - hex!("a573c29fa176c498a97fce93a572c09c"), - hex!("1651a8cd0244beda1a5da4c10640bade"), - hex!("ae87dff00ff11b68a68ed5fb03fc1567"), - hex!("6de1f1486fa54f9275f8eb5373b8518d"), - hex!("c656827fc9a799176f294cec6cd5598b"), - hex!("3de23a75524775e727bf9eb45407cf39"), - hex!("0bdc905fc27b0948ad5245a4c1871c2f"), - hex!("45f5a66017b2d387300d4d33640a820a"), - hex!("7ccff71cbeb4fe5413e6bbf0d261a7df"), - hex!("f01afafee7a82979d7a5644ab3afe640"), - hex!("2541fe719bf500258813bbd55a721c0a"), - hex!("4e5a6699a9f24fe07e572baacdf8cdea"), - hex!("24fc79ccbf0979e9371ac23c6d68de36"), - ]; - const TV_AES256_NEXT_0: [u8; AES_BLOCK_SIZE] = hex!("8ea2b7ca516745bfeafc49904b496089"); - const TV_AES256_NEXT_1: [u8; AES_BLOCK_SIZE] = hex!("81ae7d5e4138bf730d2a8871fec2cd0c"); - - pub(crate) fn aes128_key_expansion_test(expansion: F) - where - F: FnOnce([u8; AES128_KEY_SIZE]) -> [[u8; AES_BLOCK_SIZE]; AES128_KEY_COUNT], - { - let expanded = expansion(TV_AES128_KEY); - - for (exp, act) in TV_AES128_ROUND_KEYS.iter().zip(expanded.iter()) { - assert_eq!(exp, act); - } - } - - pub(crate) fn aes256_key_expansion_test(expansion: F) - where - F: FnOnce([u8; AES256_KEY_SIZE]) -> [[u8; AES_BLOCK_SIZE]; AES256_KEY_COUNT], - { - let expanded = expansion(TV_AES256_KEY); - - for (exp, act) in TV_AES256_ROUND_KEYS.iter().zip(expanded.iter()) { - assert_eq!(exp, act); - } - } - - #[test] - fn test_aes128_64_ctr() { - let mut ctr = [0u8; 8]; - let mut nonce = [0u8; 8]; - ctr.copy_from_slice(&TV_AES128_IV[0..8]); - nonce.copy_from_slice(&TV_AES128_IV[8..16]); - - let prng = unsafe { Aes128Ctr64::from_seed_impl(TV_AES128_KEY, nonce, ctr) }; - - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_0); - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_1); - } - - #[test] - fn test_aes128_128_ctr() { - let prng = unsafe { Aes128Ctr128::from_seed_impl(TV_AES128_KEY, TV_AES128_IV) }; - - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_0); - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_1); - } - - #[test] - fn test_aes256_64_ctr() { - let mut ctr = [0u8; 8]; - let mut nonce = [0u8; 8]; - ctr.copy_from_slice(&TV_AES256_IV[0..8]); - nonce.copy_from_slice(&TV_AES256_IV[8..16]); - - let prng = unsafe { Aes256Ctr64::from_seed_impl(TV_AES256_KEY, nonce, ctr) }; - - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_0); - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_1); - } - - #[test] - fn test_aes256_128_ctr() { - let prng = unsafe { Aes256Ctr128::from_seed_impl(TV_AES256_KEY, TV_AES256_IV) }; - - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_0); - assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_1); - } -} diff --git a/src/implementation.rs b/src/implementation.rs index a4cdd23..91bd161 100644 --- a/src/implementation.rs +++ b/src/implementation.rs @@ -19,7 +19,8 @@ macro_rules! safely_call { target_feature = "aes", ), )), - feature = "force_fallback" + feature = "force_runtime_detection", + feature = "force_software" )))] unsafe { $what @@ -39,7 +40,8 @@ macro_rules! safely_call { target_feature = "aes", ), )), - feature = "force_fallback" + feature = "force_runtime_detection", + feature = "force_software" ))] $what }; diff --git a/src/lib.rs b/src/lib.rs index 2cafc24..415541d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,26 +71,32 @@ pub mod tls; mod traits; -#[cfg(any( - not(any( - all( - any(target_arch = "x86_64", target_arch = "x86"), - target_feature = "sse2", - target_feature = "aes", - ), - all(target_arch = "riscv64", feature = "experimental_riscv"), - all( - target_arch = "aarch64", - target_feature = "neon", - target_feature = "aes", - ), - )), - feature = "force_fallback", - feature = "verification", +mod backend; + +#[cfg(all( + feature = "std", + not(target_arch = "riscv64"), + any( + not(any( + all( + any(target_arch = "x86_64", target_arch = "x86"), + target_feature = "sse2", + target_feature = "aes", + ), + all( + target_arch = "aarch64", + target_feature = "neon", + target_feature = "aes", + ), + )), + feature = "force_runtime_detection", + ), ))] -pub(crate) mod fallback; +pub(crate) mod runtime; #[cfg(all( + feature = "std", + not(target_arch = "riscv64"), any( not(any( all( @@ -98,71 +104,59 @@ pub(crate) mod fallback; target_feature = "sse2", target_feature = "aes", ), - all(target_arch = "riscv64", feature = "experimental_riscv"), all( target_arch = "aarch64", target_feature = "neon", target_feature = "aes", ), )), - feature = "force_fallback" + feature = "force_runtime_detection", ), +))] +pub use runtime::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; + +#[cfg(all( + target_arch = "aarch64", + target_feature = "neon", + target_feature = "aes", + not(feature = "force_runtime_detection"), + not(feature = "force_software"), not(feature = "verification"), ))] -pub use fallback::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; +pub use backend::aarch64::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; + +#[cfg(all( + target_arch = "riscv64", + feature = "experimental_riscv", + not(feature = "force_runtime_detection"), + not(feature = "force_software"), + not(feature = "verification"), +))] +pub use backend::riscv64::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; + +#[cfg(all( + any(target_arch = "x86_64", target_arch = "x86"), + target_feature = "sse2", + target_feature = "aes", + not(feature = "force_runtime_detection"), + not(feature = "force_software"), + not(feature = "verification"), +))] +pub use backend::x86::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; #[cfg(all( any( - all( - any(target_arch = "x86_64", target_arch = "x86"), - target_feature = "sse2", - target_feature = "aes", - ), - all(target_arch = "riscv64", feature = "experimental_riscv"), - all( + not(any( target_arch = "aarch64", - target_feature = "neon", - target_feature = "aes", - ), + all(target_arch = "riscv64", feature = "experimental_riscv"), + any(target_arch = "x86_64", target_arch = "x86"), + )), + feature = "force_software", ), - not(feature = "force_fallback"), + not(feature = "force_runtime_detection"), not(feature = "verification"), ))] -pub use hardware::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; - -#[cfg(any( - not(all( - any( - not(any( - all( - any(target_arch = "x86_64", target_arch = "x86"), - target_feature = "sse2", - target_feature = "aes", - ), - all(target_arch = "riscv64", feature = "experimental_riscv"), - all( - target_arch = "aarch64", - target_feature = "neon", - target_feature = "aes", - ), - )), - feature = "force_fallback" - ), - any( - not(all( - feature = "std", - any( - target_arch = "aarch64", - target_arch = "riscv64", - any(target_arch = "x86_64", target_arch = "x86"), - ) - )), - feature = "force_no_runtime_detection" - ) - )), - feature = "verification" -))] -mod hardware; +pub use backend::soft::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64}; #[cfg(not(feature = "verification"))] mod implementation; @@ -192,3 +186,120 @@ pub(crate) fn secure_bytes() -> [u8; N] { getrandom::getrandom(&mut bytes).expect("Can't get random bytes from OS"); bytes } + +#[cfg(all(test, not(feature = "verification")))] +#[allow(unused)] +mod tests { + use super::*; + use crate::constants::{ + AES128_KEY_COUNT, AES128_KEY_SIZE, AES256_KEY_COUNT, AES256_KEY_SIZE, AES_BLOCK_SIZE, + }; + use hex_literal::hex; + + // From NIST FIPS 197 + const TV_AES128_KEY: [u8; AES128_KEY_SIZE] = hex!("000102030405060708090a0b0c0d0e0f"); + const TV_AES128_IV: [u8; AES_BLOCK_SIZE] = hex!("00112233445566778899aabbccddeeff"); + const TV_AES128_ROUND_KEYS: [[u8; AES_BLOCK_SIZE]; AES128_KEY_COUNT] = [ + hex!("000102030405060708090a0b0c0d0e0f"), + hex!("d6aa74fdd2af72fadaa678f1d6ab76fe"), + hex!("b692cf0b643dbdf1be9bc5006830b3fe"), + hex!("b6ff744ed2c2c9bf6c590cbf0469bf41"), + hex!("47f7f7bc95353e03f96c32bcfd058dfd"), + hex!("3caaa3e8a99f9deb50f3af57adf622aa"), + hex!("5e390f7df7a69296a7553dc10aa31f6b"), + hex!("14f9701ae35fe28c440adf4d4ea9c026"), + hex!("47438735a41c65b9e016baf4aebf7ad2"), + hex!("549932d1f08557681093ed9cbe2c974e"), + hex!("13111d7fe3944a17f307a78b4d2b30c5"), + ]; + const TV_AES128_NEXT_0: [u8; AES_BLOCK_SIZE] = hex!("69c4e0d86a7b0430d8cdb78070b4c55a"); + const TV_AES128_NEXT_1: [u8; AES_BLOCK_SIZE] = hex!("a556156c72876577f67f95a9d9e640a7"); + + // From NIST FIPS 197 + const TV_AES256_KEY: [u8; AES256_KEY_SIZE] = + hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"); + const TV_AES256_IV: [u8; AES_BLOCK_SIZE] = hex!("00112233445566778899aabbccddeeff"); + const TV_AES256_ROUND_KEYS: [[u8; AES_BLOCK_SIZE]; AES256_KEY_COUNT] = [ + hex!("000102030405060708090a0b0c0d0e0f"), + hex!("101112131415161718191a1b1c1d1e1f"), + hex!("a573c29fa176c498a97fce93a572c09c"), + hex!("1651a8cd0244beda1a5da4c10640bade"), + hex!("ae87dff00ff11b68a68ed5fb03fc1567"), + hex!("6de1f1486fa54f9275f8eb5373b8518d"), + hex!("c656827fc9a799176f294cec6cd5598b"), + hex!("3de23a75524775e727bf9eb45407cf39"), + hex!("0bdc905fc27b0948ad5245a4c1871c2f"), + hex!("45f5a66017b2d387300d4d33640a820a"), + hex!("7ccff71cbeb4fe5413e6bbf0d261a7df"), + hex!("f01afafee7a82979d7a5644ab3afe640"), + hex!("2541fe719bf500258813bbd55a721c0a"), + hex!("4e5a6699a9f24fe07e572baacdf8cdea"), + hex!("24fc79ccbf0979e9371ac23c6d68de36"), + ]; + const TV_AES256_NEXT_0: [u8; AES_BLOCK_SIZE] = hex!("8ea2b7ca516745bfeafc49904b496089"); + const TV_AES256_NEXT_1: [u8; AES_BLOCK_SIZE] = hex!("81ae7d5e4138bf730d2a8871fec2cd0c"); + + pub(crate) fn aes128_key_expansion_test(expansion: F) + where + F: FnOnce([u8; AES128_KEY_SIZE]) -> [[u8; AES_BLOCK_SIZE]; AES128_KEY_COUNT], + { + let expanded = expansion(TV_AES128_KEY); + + for (exp, act) in TV_AES128_ROUND_KEYS.iter().zip(expanded.iter()) { + assert_eq!(exp, act); + } + } + + pub(crate) fn aes256_key_expansion_test(expansion: F) + where + F: FnOnce([u8; AES256_KEY_SIZE]) -> [[u8; AES_BLOCK_SIZE]; AES256_KEY_COUNT], + { + let expanded = expansion(TV_AES256_KEY); + + for (exp, act) in TV_AES256_ROUND_KEYS.iter().zip(expanded.iter()) { + assert_eq!(exp, act); + } + } + + #[test] + fn test_aes128_64_ctr() { + let mut ctr = [0u8; 8]; + let mut nonce = [0u8; 8]; + ctr.copy_from_slice(&TV_AES128_IV[0..8]); + nonce.copy_from_slice(&TV_AES128_IV[8..16]); + + let prng = unsafe { Aes128Ctr64::from_seed_impl(TV_AES128_KEY, nonce, ctr) }; + + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_0); + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_1); + } + + #[test] + fn test_aes128_128_ctr() { + let prng = unsafe { Aes128Ctr128::from_seed_impl(TV_AES128_KEY, TV_AES128_IV) }; + + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_0); + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES128_NEXT_1); + } + + #[test] + fn test_aes256_64_ctr() { + let mut ctr = [0u8; 8]; + let mut nonce = [0u8; 8]; + ctr.copy_from_slice(&TV_AES256_IV[0..8]); + nonce.copy_from_slice(&TV_AES256_IV[8..16]); + + let prng = unsafe { Aes256Ctr64::from_seed_impl(TV_AES256_KEY, nonce, ctr) }; + + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_0); + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_1); + } + + #[test] + fn test_aes256_128_ctr() { + let prng = unsafe { Aes256Ctr128::from_seed_impl(TV_AES256_KEY, TV_AES256_IV) }; + + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_0); + assert_eq!(unsafe { prng.next_impl().to_le_bytes() }, TV_AES256_NEXT_1); + } +} diff --git a/src/fallback/runtime.rs b/src/runtime.rs similarity index 77% rename from src/fallback/runtime.rs rename to src/runtime.rs index 9a5de0c..d4e5cd0 100644 --- a/src/fallback/runtime.rs +++ b/src/runtime.rs @@ -1,15 +1,27 @@ -//! The runtime fallback, when STD is available or the platform has hardware based AES support. -use core::cell::RefCell; +//! The runtime fallback, when std is available or the platform has hardware based AES support. -use crate::hardware::{ +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +use crate::backend::x86::{ Aes128Ctr128 as Aes128Ctr128Hardware, Aes128Ctr64 as Aes128Ctr64Hardware, Aes256Ctr128 as Aes256Ctr128Hardware, Aes256Ctr64 as Aes256Ctr64Hardware, }; -use crate::fallback::software::Aes128Ctr128 as Aes128Ctr128Software; -use crate::fallback::software::Aes128Ctr64 as Aes128Ctr64Software; -use crate::fallback::software::Aes256Ctr128 as Aes256Ctr128Software; -use crate::fallback::software::Aes256Ctr64 as Aes256Ctr64Software; +#[cfg(all(target_arch = "riscv64", feature = "experimental_riscv"))] +use crate::backend::riscv64::{ + Aes128Ctr128 as Aes128Ctr128Hardware, Aes128Ctr64 as Aes128Ctr64Hardware, + Aes256Ctr128 as Aes256Ctr128Hardware, Aes256Ctr64 as Aes256Ctr64Hardware, +}; + +#[cfg(target_arch = "aarch64")] +use crate::backend::aarch64::{ + Aes128Ctr128 as Aes128Ctr128Hardware, Aes128Ctr64 as Aes128Ctr64Hardware, + Aes256Ctr128 as Aes256Ctr128Hardware, Aes256Ctr64 as Aes256Ctr64Hardware, +}; + +use crate::backend::soft::{ + Aes128Ctr128 as Aes128Ctr128Software, Aes128Ctr64 as Aes128Ctr64Software, + Aes256Ctr128 as Aes256Ctr128Software, Aes256Ctr64 as Aes256Ctr64Software, +}; #[allow(unused)] pub(crate) fn has_hardware_acceleration() -> bool { @@ -30,7 +42,7 @@ pub(crate) fn has_hardware_acceleration() -> bool { #[derive(Clone)] enum Aes128Ctr64Inner { Hardware(Box), - Software(Box>), + Software(Box), } /// A random number generator based on the AES-128 block cipher that runs in CTR mode and has a @@ -45,13 +57,12 @@ impl Aes128Ctr64 { pub(crate) fn zeroed() -> Self { match has_hardware_acceleration() { true => { - // Safety: We checked that the hardware acceleration is available. let hardware = Aes128Ctr64Hardware::zeroed(); Self(Aes128Ctr64Inner::Hardware(Box::new(hardware))) } false => { let software = Aes128Ctr64Software::zeroed(); - Self(Aes128Ctr64Inner::Software(Box::new(RefCell::new(software)))) + Self(Aes128Ctr64Inner::Software(Box::new(software))) } } } @@ -65,7 +76,7 @@ impl Aes128Ctr64 { } false => { let software = Aes128Ctr64Software::from_seed_impl(key, nonce, counter); - Self(Aes128Ctr64Inner::Software(Box::new(RefCell::new(software)))) + Self(Aes128Ctr64Inner::Software(Box::new(software))) } } } @@ -77,7 +88,7 @@ impl Aes128Ctr64 { unsafe { this.seed_impl(key, nonce, counter) }; } Aes128Ctr64Inner::Software(this) => { - this.borrow_mut().seed_impl(key, nonce, counter); + this.seed_impl(key, nonce, counter); } } } @@ -85,14 +96,14 @@ impl Aes128Ctr64 { pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { match &self.0 { Aes128Ctr64Inner::Hardware(this) => this.is_hardware_accelerated_impl(), - Aes128Ctr64Inner::Software(this) => this.borrow().is_hardware_accelerated_impl(), + Aes128Ctr64Inner::Software(this) => this.is_hardware_accelerated_impl(), } } pub(crate) fn counter_impl(&self) -> u64 { match &self.0 { Aes128Ctr64Inner::Hardware(this) => this.counter_impl(), - Aes128Ctr64Inner::Software(this) => this.borrow().counter_impl(), + Aes128Ctr64Inner::Software(this) => this.counter_impl(), } } @@ -103,7 +114,7 @@ impl Aes128Ctr64 { // Safety: We checked that the hardware acceleration is available. unsafe { this.next_impl() } } - Aes128Ctr64Inner::Software(this) => this.borrow_mut().next_impl(), + Aes128Ctr64Inner::Software(this) => this.next_impl(), } } } @@ -111,7 +122,7 @@ impl Aes128Ctr64 { #[derive(Clone)] enum Aes128Ctr128Inner { Hardware(Box), - Software(Box>), + Software(Box), } /// A random number generator based on the AES-128 block cipher that runs in CTR mode and has a @@ -128,7 +139,7 @@ impl Aes128Ctr128 { Aes128Ctr128Inner::Hardware(Box::new(this.jump_impl())) } Aes128Ctr128Inner::Software(this) => { - Aes128Ctr128Inner::Software(Box::new(RefCell::new(this.borrow_mut().jump_impl()))) + Aes128Ctr128Inner::Software(Box::new(this.jump_impl())) } }; Self(inner) @@ -139,9 +150,9 @@ impl Aes128Ctr128 { Aes128Ctr128Inner::Hardware(this) => { Aes128Ctr128Inner::Hardware(Box::new(this.long_jump_impl())) } - Aes128Ctr128Inner::Software(this) => Aes128Ctr128Inner::Software(Box::new( - RefCell::new(this.borrow_mut().long_jump_impl()), - )), + Aes128Ctr128Inner::Software(this) => { + Aes128Ctr128Inner::Software(Box::new(this.long_jump_impl())) + } }; Self(inner) } @@ -155,9 +166,7 @@ impl Aes128Ctr128 { } false => { let software = Aes128Ctr128Software::from_seed_impl(key, counter); - Self(Aes128Ctr128Inner::Software(Box::new(RefCell::new( - software, - )))) + Self(Aes128Ctr128Inner::Software(Box::new(software))) } } } @@ -169,7 +178,7 @@ impl Aes128Ctr128 { unsafe { this.seed_impl(key, counter) }; } Aes128Ctr128Inner::Software(this) => { - this.borrow_mut().seed_impl(key, counter); + this.seed_impl(key, counter); } } } @@ -177,14 +186,14 @@ impl Aes128Ctr128 { pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { match &self.0 { Aes128Ctr128Inner::Hardware(this) => this.is_hardware_accelerated_impl(), - Aes128Ctr128Inner::Software(this) => this.borrow().is_hardware_accelerated_impl(), + Aes128Ctr128Inner::Software(this) => this.is_hardware_accelerated_impl(), } } pub(crate) fn counter_impl(&self) -> u128 { match &self.0 { Aes128Ctr128Inner::Hardware(this) => this.counter_impl(), - Aes128Ctr128Inner::Software(this) => this.borrow().counter_impl(), + Aes128Ctr128Inner::Software(this) => this.counter_impl(), } } @@ -195,7 +204,7 @@ impl Aes128Ctr128 { // Safety: We checked that the hardware acceleration is available. unsafe { this.next_impl() } } - Aes128Ctr128Inner::Software(this) => this.borrow_mut().next_impl(), + Aes128Ctr128Inner::Software(this) => this.next_impl(), } } } @@ -203,7 +212,7 @@ impl Aes128Ctr128 { #[derive(Clone)] enum Aes256Ctr64Inner { Hardware(Box), - Software(Box>), + Software(Box), } /// A random number generator based on the AES-256 block cipher that runs in CTR mode and has a @@ -223,7 +232,7 @@ impl Aes256Ctr64 { } false => { let software = Aes256Ctr64Software::from_seed_impl(key, nonce, counter); - Self(Aes256Ctr64Inner::Software(Box::new(RefCell::new(software)))) + Self(Aes256Ctr64Inner::Software(Box::new(software))) } } } @@ -235,7 +244,7 @@ impl Aes256Ctr64 { unsafe { this.seed_impl(key, nonce, counter) }; } Aes256Ctr64Inner::Software(this) => { - this.borrow_mut().seed_impl(key, nonce, counter); + this.seed_impl(key, nonce, counter); } } } @@ -243,14 +252,14 @@ impl Aes256Ctr64 { pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { match &self.0 { Aes256Ctr64Inner::Hardware(this) => this.is_hardware_accelerated_impl(), - Aes256Ctr64Inner::Software(this) => this.borrow().is_hardware_accelerated_impl(), + Aes256Ctr64Inner::Software(this) => this.is_hardware_accelerated_impl(), } } pub(crate) fn counter_impl(&self) -> u64 { match &self.0 { Aes256Ctr64Inner::Hardware(this) => this.counter_impl(), - Aes256Ctr64Inner::Software(this) => this.borrow().counter_impl(), + Aes256Ctr64Inner::Software(this) => this.counter_impl(), } } @@ -261,7 +270,7 @@ impl Aes256Ctr64 { // Safety: We checked that the hardware acceleration is available. unsafe { this.next_impl() } } - Aes256Ctr64Inner::Software(this) => this.borrow_mut().next_impl(), + Aes256Ctr64Inner::Software(this) => this.next_impl(), } } } @@ -269,7 +278,7 @@ impl Aes256Ctr64 { #[derive(Clone)] enum Aes256Ctr128Inner { Hardware(Box), - Software(Box>), + Software(Box), } /// A random number generator based on the AES-256 block cipher that runs in CTR mode and has a @@ -286,7 +295,7 @@ impl Aes256Ctr128 { Aes256Ctr128Inner::Hardware(Box::new(this.jump_impl())) } Aes256Ctr128Inner::Software(this) => { - Aes256Ctr128Inner::Software(Box::new(RefCell::new(this.borrow_mut().jump_impl()))) + Aes256Ctr128Inner::Software(Box::new(this.jump_impl())) } }; Self(inner) @@ -297,9 +306,9 @@ impl Aes256Ctr128 { Aes256Ctr128Inner::Hardware(this) => { Aes256Ctr128Inner::Hardware(Box::new(this.long_jump_impl())) } - Aes256Ctr128Inner::Software(this) => Aes256Ctr128Inner::Software(Box::new( - RefCell::new(this.borrow_mut().long_jump_impl()), - )), + Aes256Ctr128Inner::Software(this) => { + Aes256Ctr128Inner::Software(Box::new(this.long_jump_impl())) + } }; Self(inner) } @@ -313,9 +322,7 @@ impl Aes256Ctr128 { } false => { let software = Aes256Ctr128Software::from_seed_impl(key, counter); - Self(Aes256Ctr128Inner::Software(Box::new(RefCell::new( - software, - )))) + Self(Aes256Ctr128Inner::Software(Box::new(software))) } } } @@ -323,7 +330,7 @@ impl Aes256Ctr128 { pub(crate) fn counter_impl(&self) -> u128 { match &self.0 { Aes256Ctr128Inner::Hardware(this) => this.counter_impl(), - Aes256Ctr128Inner::Software(this) => this.borrow().counter_impl(), + Aes256Ctr128Inner::Software(this) => this.counter_impl(), } } @@ -334,7 +341,7 @@ impl Aes256Ctr128 { unsafe { this.seed_impl(key, counter) }; } Aes256Ctr128Inner::Software(this) => { - this.borrow_mut().seed_impl(key, counter); + this.seed_impl(key, counter); } } } @@ -342,7 +349,7 @@ impl Aes256Ctr128 { pub(crate) fn is_hardware_accelerated_impl(&self) -> bool { match &self.0 { Aes256Ctr128Inner::Hardware(this) => this.is_hardware_accelerated_impl(), - Aes256Ctr128Inner::Software(this) => this.borrow().is_hardware_accelerated_impl(), + Aes256Ctr128Inner::Software(this) => this.is_hardware_accelerated_impl(), } } @@ -353,7 +360,7 @@ impl Aes256Ctr128 { // Safety: We checked that the hardware acceleration is available. unsafe { this.next_impl() } } - Aes256Ctr128Inner::Software(this) => this.borrow_mut().next_impl(), + Aes256Ctr128Inner::Software(this) => this.next_impl(), } } } diff --git a/src/tls.rs b/src/tls.rs index bbefd39..abb8354 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -10,41 +10,47 @@ use core::ops::RangeBounds; use crate::seeds::Aes128Ctr64Seed; use crate::Random; -#[cfg(not(any( +#[cfg(any( not(any( - all( - any(target_arch = "x86_64", target_arch = "x86"), - target_feature = "sse2", - target_feature = "aes", - ), - all(target_arch = "riscv64", feature = "experimental_riscv"), - all( - target_arch = "aarch64", - target_feature = "neon", - target_feature = "aes", - ), + not(any( + all( + any(target_arch = "x86_64", target_arch = "x86"), + target_feature = "sse2", + target_feature = "aes", + ), + all(target_arch = "riscv64", feature = "experimental_riscv"), + all( + target_arch = "aarch64", + target_feature = "neon", + target_feature = "aes", + ), + )), + feature = "force_runtime_detection" )), - feature = "force_fallback" -)))] + feature = "force_software" +))] thread_local! { pub(super) static RNG: crate::Aes128Ctr64 = const { crate::Aes128Ctr64::zeroed() }; } -#[cfg(any( - not(any( - all( - any(target_arch = "x86_64", target_arch = "x86"), - target_feature = "sse2", - target_feature = "aes", - ), - all(target_arch = "riscv64", feature = "experimental_riscv"), - all( - target_arch = "aarch64", - target_feature = "neon", - target_feature = "aes", - ), - )), - feature = "force_fallback" +#[cfg(all( + any( + not(any( + all( + any(target_arch = "x86_64", target_arch = "x86"), + target_feature = "sse2", + target_feature = "aes", + ), + all(target_arch = "riscv64", feature = "experimental_riscv"), + all( + target_arch = "aarch64", + target_feature = "neon", + target_feature = "aes", + ), + )), + feature = "force_runtime_detection" + ), + not(feature = "force_software") ))] thread_local! { pub(super) static RNG: core::cell::LazyCell = core::cell::LazyCell::new(crate::Aes128Ctr64::zeroed); diff --git a/src/verification.rs b/src/verification.rs index 5428fe2..6426681 100644 --- a/src/verification.rs +++ b/src/verification.rs @@ -1,14 +1,29 @@ //! Test that verify that the software backend and the hardware backends produce the same random numbers for a given seed. use crate::constants::{AES128_KEY_SIZE, AES256_KEY_SIZE, AES_BLOCK_SIZE}; -use crate::fallback::software::Aes128Ctr128 as Aes128Ctr128Software; -use crate::fallback::software::Aes128Ctr64 as Aes128Ctr64Software; -use crate::fallback::software::Aes256Ctr128 as Aes256Ctr128Software; -use crate::fallback::software::Aes256Ctr64 as Aes256Ctr64Software; -use crate::hardware::Aes128Ctr128 as Aes128Ctr128Hardware; -use crate::hardware::Aes128Ctr64 as Aes128Ctr64Hardware; -use crate::hardware::Aes256Ctr128 as Aes256Ctr128Hardware; -use crate::hardware::Aes256Ctr64 as Aes256Ctr64Hardware; + +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +use crate::backend::x86::{ + Aes128Ctr128 as Aes128Ctr128Hardware, Aes128Ctr64 as Aes128Ctr64Hardware, + Aes256Ctr128 as Aes256Ctr128Hardware, Aes256Ctr64 as Aes256Ctr64Hardware, +}; + +#[cfg(all(target_arch = "riscv64", feature = "experimental_riscv"))] +use crate::backend::riscv64::{ + Aes128Ctr128 as Aes128Ctr128Hardware, Aes128Ctr64 as Aes128Ctr64Hardware, + Aes256Ctr128 as Aes256Ctr128Hardware, Aes256Ctr64 as Aes256Ctr64Hardware, +}; + +#[cfg(target_arch = "aarch64")] +use crate::backend::aarch64::{ + Aes128Ctr128 as Aes128Ctr128Hardware, Aes128Ctr64 as Aes128Ctr64Hardware, + Aes256Ctr128 as Aes256Ctr128Hardware, Aes256Ctr64 as Aes256Ctr64Hardware, +}; + +use crate::backend::soft::{ + Aes128Ctr128 as Aes128Ctr128Software, Aes128Ctr64 as Aes128Ctr64Software, + Aes256Ctr128 as Aes256Ctr128Software, Aes256Ctr64 as Aes256Ctr64Software, +}; /// Runs the verification testsuite. Will panic once it finds an error. /// diff --git a/verification/Cargo.toml b/verification/Cargo.toml index b71929f..9f9905d 100644 --- a/verification/Cargo.toml +++ b/verification/Cargo.toml @@ -6,11 +6,11 @@ publish = false [features] experimental_riscv = ["rand_aes/experimental_riscv"] -force_fallback = ["rand_aes/force_fallback"] -force_no_runtime_detection = ["rand_aes/force_no_runtime_detection"] +force_runtime_detection = ["rand_aes/force_runtime_detection"] +force_software = ["rand_aes/force_software"] [dependencies] -rand_aes = { path = "..", features = ["verification"] } +rand_aes = { path = "..", default-features = false, features = ["verification"] } [[bin]] name = "verification"