Skip to content

Commit

Permalink
aes-soft: use fixslicing for AES-128/AES-256 encryption
Browse files Browse the repository at this point in the history
Fixslicing is defined for these operations only, but we can replace
bitslicing in these capacities with the faster fixslicing approach.

This is useful for AES-CTR, which needs only the encryption operation.

AES-192, as well as AES-128/AES-256 encryption, still leverage the
previous bitsliced implementation.
  • Loading branch information
tarcieri committed Oct 25, 2020
1 parent ad0cb54 commit ca9534b
Show file tree
Hide file tree
Showing 9 changed files with 553 additions and 563 deletions.
14 changes: 1 addition & 13 deletions aes/aes-soft/benches/aes128.rs
Expand Up @@ -2,7 +2,7 @@
extern crate test;

use aes_soft::cipher::{BlockCipher, NewBlockCipher};
use aes_soft::{Aes128, Aes128Fixsliced};
use aes_soft::Aes128;

#[bench]
pub fn aes128_encrypt(bh: &mut test::Bencher) {
Expand Down Expand Up @@ -40,18 +40,6 @@ pub fn aes128_encrypt8(bh: &mut test::Bencher) {
bh.bytes = (input[0].len() * input.len()) as u64;
}

#[bench]
pub fn aes128_encrypt2_fixsliced(bh: &mut test::Bencher) {
let cipher = Aes128Fixsliced::new(&Default::default());
let mut input = Default::default();

bh.iter(|| {
cipher.encrypt_blocks(&mut input);
test::black_box(&input);
});
bh.bytes = (input[0].len() * input.len()) as u64;
}

#[bench]
pub fn aes128_decrypt8(bh: &mut test::Bencher) {
let cipher = Aes128::new(&Default::default());
Expand Down
14 changes: 1 addition & 13 deletions aes/aes-soft/benches/aes256.rs
Expand Up @@ -2,7 +2,7 @@
extern crate test;

use aes_soft::cipher::{BlockCipher, NewBlockCipher};
use aes_soft::{Aes256, Aes256Fixsliced};
use aes_soft::Aes256;

#[bench]
pub fn aes256_encrypt(bh: &mut test::Bencher) {
Expand Down Expand Up @@ -40,18 +40,6 @@ pub fn aes256_encrypt8(bh: &mut test::Bencher) {
bh.bytes = (input[0].len() * input.len()) as u64;
}

#[bench]
pub fn aes256_encrypt2_fixsliced(bh: &mut test::Bencher) {
let cipher = Aes256Fixsliced::new(&Default::default());
let mut input = Default::default();

bh.iter(|| {
cipher.encrypt_blocks(&mut input);
test::black_box(&input);
});
bh.bytes = (input[0].len() * input.len()) as u64;
}

#[bench]
pub fn aes256_decrypt8(bh: &mut test::Bencher) {
let cipher = Aes256::new(&Default::default());
Expand Down
94 changes: 94 additions & 0 deletions aes/aes-soft/src/aes128.rs
@@ -0,0 +1,94 @@
//! AES-128

use cipher::{
consts::{U11, U16, U8},
BlockCipher, NewBlockCipher,
};

use crate::{
bitslice::{
bit_slice_1x128_with_u32x4, bit_slice_1x16_with_u16, bit_slice_4x4_with_u16,
bit_slice_fill_4x4_with_u32x4, decrypt_core, un_bit_slice_1x128_with_u32x4,
un_bit_slice_1x16_with_u16, Bs8State,
},
consts::U32X4_0,
expand::expand_key,
fixslice::{self, FixsliceKeys128},
simd::u32x4,
Block, ParBlocks,
};

/// AES-128 key
pub type Key = cipher::block::Key<Aes128>;

/// AES-128 block cipher instance
#[derive(Clone)]
pub struct Aes128 {
enc_keys: FixsliceKeys128,
dec_keys: [Bs8State<u16>; 11],
dec_keys8: [Bs8State<u32x4>; 11],
}

impl NewBlockCipher for Aes128 {
type KeySize = U16;

#[inline]
fn new(key: &Key) -> Self {
let dk = expand_key::<U16, U11>(key).1;

let k8 = Bs8State(
U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0,
);

let mut c = Self {
enc_keys: fixslice::aes128_key_schedule(key),
dec_keys: [Bs8State(0, 0, 0, 0, 0, 0, 0, 0); 11],
dec_keys8: [k8; 11],
};

for i in 0..11 {
c.dec_keys[i] = bit_slice_4x4_with_u16(dk[i][0], dk[i][1], dk[i][2], dk[i][3]);
c.dec_keys8[i] = bit_slice_fill_4x4_with_u32x4(dk[i][0], dk[i][1], dk[i][2], dk[i][3]);
}

c
}
}

impl BlockCipher for Aes128 {
type BlockSize = U16;
type ParBlocks = U8;

#[inline]
fn encrypt_block(&self, block: &mut Block) {
let mut blocks = [Block::default(); 2];
blocks[0].copy_from_slice(block);
fixslice::aes128_encrypt(&self.enc_keys, &mut blocks);
block.copy_from_slice(&blocks[0]);
}

#[inline]
fn decrypt_block(&self, block: &mut Block) {
let mut bs = bit_slice_1x16_with_u16(block);
bs = decrypt_core(&bs, &self.dec_keys);
un_bit_slice_1x16_with_u16(&bs, block);
}

#[inline]
fn encrypt_blocks(&self, blocks: &mut ParBlocks) {
for chunk in blocks.chunks_mut(2) {
fixslice::aes128_encrypt(&self.enc_keys, chunk);
}
}

#[inline]
fn decrypt_blocks(&self, blocks: &mut ParBlocks) {
#[allow(unsafe_code)]
let blocks: &mut [u8; 16 * 8] = unsafe { &mut *(blocks as *mut _ as *mut [u8; 128]) };
let bs = bit_slice_1x128_with_u32x4(blocks);
let bs2 = decrypt_core(&bs, &self.dec_keys8);
un_bit_slice_1x128_with_u32x4(bs2, blocks);
}
}

opaque_debug::implement!(Aes128);
98 changes: 98 additions & 0 deletions aes/aes-soft/src/aes192.rs
@@ -0,0 +1,98 @@
//! AES-192

use cipher::{
consts::{U13, U16, U24, U8},
BlockCipher, NewBlockCipher,
};

use crate::{
bitslice::{
bit_slice_1x128_with_u32x4, bit_slice_1x16_with_u16, bit_slice_4x4_with_u16,
bit_slice_fill_4x4_with_u32x4, decrypt_core, encrypt_core, un_bit_slice_1x128_with_u32x4,
un_bit_slice_1x16_with_u16, Bs8State,
},
consts::U32X4_0,
expand::expand_key,
simd::u32x4,
Block, ParBlocks,
};

/// AES-192 key
pub type Key = cipher::block::Key<Aes192>;

/// AES-192 block cipher instance
#[derive(Clone)]
pub struct Aes192 {
enc_keys: [Bs8State<u16>; 13],
dec_keys: [Bs8State<u16>; 13],
enc_keys8: [Bs8State<u32x4>; 13],
dec_keys8: [Bs8State<u32x4>; 13],
}

impl NewBlockCipher for Aes192 {
type KeySize = U24;

#[inline]
fn new(key: &Key) -> Self {
let (ek, dk) = expand_key::<U24, U13>(key);

let k8 = Bs8State(
U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0,
);

let mut c = Self {
enc_keys: [Bs8State(0, 0, 0, 0, 0, 0, 0, 0); 13],
dec_keys: [Bs8State(0, 0, 0, 0, 0, 0, 0, 0); 13],
enc_keys8: [k8; 13],
dec_keys8: [k8; 13],
};

for i in 0..13 {
c.enc_keys[i] = bit_slice_4x4_with_u16(ek[i][0], ek[i][1], ek[i][2], ek[i][3]);
c.dec_keys[i] = bit_slice_4x4_with_u16(dk[i][0], dk[i][1], dk[i][2], dk[i][3]);
c.enc_keys8[i] = bit_slice_fill_4x4_with_u32x4(ek[i][0], ek[i][1], ek[i][2], ek[i][3]);
c.dec_keys8[i] = bit_slice_fill_4x4_with_u32x4(dk[i][0], dk[i][1], dk[i][2], dk[i][3]);
}

c
}
}

impl BlockCipher for Aes192 {
type BlockSize = U16;
type ParBlocks = U8;

#[inline]
fn encrypt_block(&self, block: &mut Block) {
let mut bs = bit_slice_1x16_with_u16(block);
bs = encrypt_core(&bs, &self.enc_keys);
un_bit_slice_1x16_with_u16(&bs, block);
}

#[inline]
fn decrypt_block(&self, block: &mut Block) {
let mut bs = bit_slice_1x16_with_u16(block);
bs = decrypt_core(&bs, &self.dec_keys);
un_bit_slice_1x16_with_u16(&bs, block);
}

#[inline]
fn encrypt_blocks(&self, blocks: &mut ParBlocks) {
#[allow(unsafe_code)]
let blocks: &mut [u8; 16 * 8] = unsafe { &mut *(blocks as *mut _ as *mut [u8; 128]) };
let bs = bit_slice_1x128_with_u32x4(blocks);
let bs2 = encrypt_core(&bs, &self.enc_keys8);
un_bit_slice_1x128_with_u32x4(bs2, blocks);
}

#[inline]
fn decrypt_blocks(&self, blocks: &mut ParBlocks) {
#[allow(unsafe_code)]
let blocks: &mut [u8; 16 * 8] = unsafe { &mut *(blocks as *mut _ as *mut [u8; 128]) };
let bs = bit_slice_1x128_with_u32x4(blocks);
let bs2 = decrypt_core(&bs, &self.dec_keys8);
un_bit_slice_1x128_with_u32x4(bs2, blocks);
}
}

opaque_debug::implement!(Aes192);
94 changes: 94 additions & 0 deletions aes/aes-soft/src/aes256.rs
@@ -0,0 +1,94 @@
//! AES-256

use cipher::{
consts::{U15, U16, U32, U8},
BlockCipher, NewBlockCipher,
};

use crate::{
bitslice::{
bit_slice_1x128_with_u32x4, bit_slice_1x16_with_u16, bit_slice_4x4_with_u16,
bit_slice_fill_4x4_with_u32x4, decrypt_core, un_bit_slice_1x128_with_u32x4,
un_bit_slice_1x16_with_u16, Bs8State,
},
consts::U32X4_0,
expand::expand_key,
fixslice::{self, FixsliceKeys256},
simd::u32x4,
Block, ParBlocks,
};

/// AES-256 key
pub type Key = cipher::block::Key<Aes256>;

/// AES-256 block cipher instance
#[derive(Clone)]
pub struct Aes256 {
enc_keys: FixsliceKeys256,
dec_keys: [Bs8State<u16>; 15],
dec_keys8: [Bs8State<u32x4>; 15],
}

impl NewBlockCipher for Aes256 {
type KeySize = U32;

#[inline]
fn new(key: &Key) -> Self {
let dk = expand_key::<U32, U15>(key).1;

let k8 = Bs8State(
U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0, U32X4_0,
);

let mut c = Self {
enc_keys: fixslice::aes256_key_schedule(key),
dec_keys: [Bs8State(0, 0, 0, 0, 0, 0, 0, 0); 15],
dec_keys8: [k8; 15],
};

for i in 0..15 {
c.dec_keys[i] = bit_slice_4x4_with_u16(dk[i][0], dk[i][1], dk[i][2], dk[i][3]);
c.dec_keys8[i] = bit_slice_fill_4x4_with_u32x4(dk[i][0], dk[i][1], dk[i][2], dk[i][3]);
}

c
}
}

impl BlockCipher for Aes256 {
type BlockSize = U16;
type ParBlocks = U8;

#[inline]
fn encrypt_block(&self, block: &mut Block) {
let mut blocks = [Block::default(); 2];
blocks[0].copy_from_slice(block);
fixslice::aes256_encrypt(&self.enc_keys, &mut blocks);
block.copy_from_slice(&blocks[0]);
}

#[inline]
fn decrypt_block(&self, block: &mut Block) {
let mut bs = bit_slice_1x16_with_u16(block);
bs = decrypt_core(&bs, &self.dec_keys);
un_bit_slice_1x16_with_u16(&bs, block);
}

#[inline]
fn encrypt_blocks(&self, blocks: &mut ParBlocks) {
for chunk in blocks.chunks_mut(2) {
fixslice::aes256_encrypt(&self.enc_keys, chunk);
}
}

#[inline]
fn decrypt_blocks(&self, blocks: &mut ParBlocks) {
#[allow(unsafe_code)]
let blocks: &mut [u8; 16 * 8] = unsafe { &mut *(blocks as *mut _ as *mut [u8; 128]) };
let bs = bit_slice_1x128_with_u32x4(blocks);
let bs2 = decrypt_core(&bs, &self.dec_keys8);
un_bit_slice_1x128_with_u32x4(bs2, blocks);
}
}

opaque_debug::implement!(Aes256);

0 comments on commit ca9534b

Please sign in to comment.