aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/aesround.rs43
-rw-r--r--src/block.rs58
-rw-r--r--src/lib.rs2
3 files changed, 92 insertions, 11 deletions
diff --git a/src/aesround.rs b/src/aesround.rs
index 169c125..6f63243 100644
--- a/src/aesround.rs
+++ b/src/aesround.rs
@@ -80,15 +80,42 @@ pub mod x86_64 {
null: __m128i,
}
+ #[cfg(feature = "simd")]
+ fn to_simd(block: Block) -> __m128i {
+ block.simd().into()
+ }
+
+ #[cfg(not(feature = "simd"))]
+ fn to_simd(block: Block) -> __m128i {
+ let bytes = block.bytes();
+ // SAFETY: loadu can load from unaligned memory
+ unsafe { _mm_loadu_si128(bytes.as_ptr() as *const _) }
+ }
+
+ #[cfg(feature = "simd")]
+ fn from_simd(simd: __m128i) -> Block {
+ Block::from_simd(simd.into())
+ }
+
+ #[cfg(not(feature = "simd"))]
+ fn from_simd(simd: __m128i) -> Block {
+ let mut bytes = [0; 16];
+ // SAFETY: storeu can store to unaligned memory
+ unsafe {
+ _mm_storeu_si128(bytes.as_mut_ptr() as *mut _, simd);
+ }
+ Block::from(bytes)
+ }
+
impl AesRound for AesNi {
fn new(key_i: Block, key_j: Block, key_l: Block) -> Self {
Self {
support: cpuid_aes::init(),
fallback: AesSoft::new(key_i, key_j, key_l),
- key_i: key_i.simd().into(),
- key_j: key_j.simd().into(),
- key_l: key_l.simd().into(),
- null: Block::null().simd().into(),
+ key_i: to_simd(key_i),
+ key_j: to_simd(key_j),
+ key_l: to_simd(key_l),
+ null: to_simd(Block::null()),
}
}
@@ -99,12 +126,12 @@ pub mod x86_64 {
// SAFETY: Nothing should go wrong when calling AESENC
unsafe {
- let mut block = value.simd().into();
+ let mut block = to_simd(value);
block = _mm_aesenc_si128(block, self.key_j);
block = _mm_aesenc_si128(block, self.key_i);
block = _mm_aesenc_si128(block, self.key_l);
block = _mm_aesenc_si128(block, self.null);
- Block::from_simd(block.into())
+ from_simd(block)
}
}
@@ -115,7 +142,7 @@ pub mod x86_64 {
// SAFETY: Nothing should go wrong when calling AESENC
unsafe {
- let mut block = value.simd().into();
+ let mut block = to_simd(value);
block = _mm_aesenc_si128(block, self.key_i);
block = _mm_aesenc_si128(block, self.key_j);
block = _mm_aesenc_si128(block, self.key_l);
@@ -126,7 +153,7 @@ pub mod x86_64 {
block = _mm_aesenc_si128(block, self.key_j);
block = _mm_aesenc_si128(block, self.key_l);
block = _mm_aesenc_si128(block, self.key_i);
- Block::from_simd(block.into())
+ from_simd(block)
}
}
}
diff --git a/src/block.rs b/src/block.rs
index b485b17..bde60fc 100644
--- a/src/block.rs
+++ b/src/block.rs
@@ -1,10 +1,17 @@
use std::ops::{BitAnd, BitOr, BitXor, Index, IndexMut, Mul, Shl, Shr};
+#[cfg(feature = "simd")]
use std::simd::prelude::*;
/// A block, the unit of work that AEZ divides the message into.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[cfg(feature = "simd")]
pub struct Block(u8x16);
+/// A block, the unit of work that AEZ divides the message into.
+#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[cfg(not(feature = "simd"))]
+pub struct Block([u8; 16]);
+
impl Block {
pub fn null() -> Block {
Block([0; 16].into())
@@ -19,13 +26,19 @@ impl Block {
}
pub fn write_to(&self, output: &mut [u8; 16]) {
+ #[cfg(feature = "simd")]
self.0.copy_to_slice(output);
+
+ #[cfg(not(feature = "simd"))]
+ output.copy_from_slice(&self.0);
}
+ #[cfg(feature = "simd")]
pub(crate) fn simd(&self) -> u8x16 {
self.0
}
+ #[cfg(feature = "simd")]
pub(crate) fn from_simd(value: u8x16) -> Self {
Block(value)
}
@@ -102,9 +115,34 @@ impl From<u128> for Block {
impl BitXor<Block> for Block {
type Output = Block;
+ #[cfg(feature = "simd")]
fn bitxor(self, rhs: Block) -> Block {
Block(self.0 ^ rhs.0)
}
+
+ #[cfg(not(feature = "simd"))]
+ fn bitxor(self, rhs: Block) -> Block {
+ // We unroll here because XOR is by far the operation that is used the most, and the
+ // int-conversion/bit-operation/int-conversion way is slower (but easier to write)
+ Block([
+ self.0[0] ^ rhs.0[0],
+ self.0[1] ^ rhs.0[1],
+ self.0[2] ^ rhs.0[2],
+ self.0[3] ^ rhs.0[3],
+ self.0[4] ^ rhs.0[4],
+ self.0[5] ^ rhs.0[5],
+ self.0[6] ^ rhs.0[6],
+ self.0[7] ^ rhs.0[7],
+ self.0[8] ^ rhs.0[8],
+ self.0[9] ^ rhs.0[9],
+ self.0[10] ^ rhs.0[10],
+ self.0[11] ^ rhs.0[11],
+ self.0[12] ^ rhs.0[12],
+ self.0[13] ^ rhs.0[13],
+ self.0[14] ^ rhs.0[14],
+ self.0[15] ^ rhs.0[15],
+ ])
+ }
}
impl Shl<u32> for Block {
@@ -124,14 +162,30 @@ impl Shr<u32> for Block {
impl BitAnd<Block> for Block {
type Output = Block;
fn bitand(self, rhs: Block) -> Block {
- Block(self.0 & rhs.0)
+ #[cfg(feature = "simd")]
+ {
+ Block(self.0 & rhs.0)
+ }
+
+ #[cfg(not(feature = "simd"))]
+ {
+ Block::from(self.to_int() & rhs.to_int())
+ }
}
}
impl BitOr<Block> for Block {
type Output = Block;
fn bitor(self, rhs: Block) -> Block {
- Block(self.0 | rhs.0)
+ #[cfg(feature = "simd")]
+ {
+ Block(self.0 | rhs.0)
+ }
+
+ #[cfg(not(feature = "simd"))]
+ {
+ Block::from(self.to_int() | rhs.to_int())
+ }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index a0ddfa9..06e2502 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,4 @@
-#![feature(portable_simd)]
+#![cfg_attr(feature = "simd", feature(portable_simd))]
//! AEZ *\[sic!\]* v5 encryption implemented in Rust.
//!
//! # ☣️ Cryptographic hazmat ☣️