use crate::arch::Simd;
use std::ops::{BitAnd, BitXor};
use zerocopy::transmute;
pub type Array128 = [u8; 16];
pub const RAW_C0: Array128 = [
0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0d, 0x15, 0x22, 0x37, 0x59, 0x90,
0xe9, 0x79, 0x62,
];
pub const RAW_C1: Array128 = [
0xdb, 0x3d, 0x18, 0x55, 0x6d, 0xc2, 0x2f, 0xf1, 0x20, 0x11, 0x31, 0x42, 0x73,
0xb5, 0x28, 0xdd,
];
const fn make_ctx<const BYTES: usize>(d: usize) -> [u8; BYTES] {
let mut ctx = [0u8; BYTES];
let mut i: usize = 0;
while i < d {
ctx[i * 16] = i as u8;
ctx[i * 16 + 1] = (d - 1) as u8;
i += 1;
}
ctx
}
pub const RAW_CTX_D1: [u8; 16] = make_ctx( 1);
pub const RAW_CTX_D2: [u8; 32] = make_ctx( 2);
pub const RAW_CTX_D4: [u8; 64] = make_ctx( 4);
pub trait Block
where
Self: Copy,
Self: BitXor<Self, Output = Self>,
Self: BitAnd<Self, Output = Self>,
{
type SelfArray: AsRef<[u8]>;
type Simd: Simd;
fn c0(simd: Self::Simd) -> Self;
fn c1(simd: Self::Simd) -> Self;
fn ctx(simd: Self::Simd) -> Self;
fn new(simd: Self::Simd, input: Self::SelfArray) -> Self;
fn from_128_bits(simd: Self::Simd, input: Array128) -> Self;
fn into_bytes(self) -> Self::SelfArray;
#[inline(always)]
fn from_ints(simd: Self::Simd, top: u64, bottom: u64) -> Self {
Self::from_128_bits(
simd,
transmute!([top.to_le_bytes(), bottom.to_le_bytes()]),
)
}
fn xor_down(self) -> Array128;
fn aes_encrypt_round(state: Self, round_key: Self) -> Self;
}
pub trait BlockDoubleRate<const OUTPUT_RATE_BYTES: usize>
where
Self: Block,
{
fn split(simd: Self::Simd, chunk: &[u8; OUTPUT_RATE_BYTES]) -> [Self; 2];
fn concat(first: Self, second: Self) -> [u8; OUTPUT_RATE_BYTES];
}
macro_rules! gen_block_double_rate_blanket {
($width:expr) => {
impl<T> BlockDoubleRate<{ $width * 2 }> for T
where
T: Block<SelfArray = [u8; $width]>,
{
#[inline(always)]
fn split(simd: Self::Simd, chunk: &[u8; $width * 2]) -> [Self; 2] {
let (p1, p2) = transmute!(*chunk);
[Self::new(simd, p1), Self::new(simd, p2)]
}
#[inline(always)]
fn concat(first: Self, second: Self) -> [u8; $width * 2] {
transmute!([first.into_bytes(), second.into_bytes()])
}
}
};
}
gen_block_double_rate_blanket!(16 );
gen_block_double_rate_blanket!(32 );
gen_block_double_rate_blanket!(64 );
macro_rules! gen_shared_block {
($simd_ty:ty) => {
type Simd = $simd_ty;
#[inline(always)]
fn c0(simd: $simd_ty) -> Self {
Self::from_128_bits(simd, crate::base::block::RAW_C0)
}
#[inline(always)]
fn c1(simd: $simd_ty) -> Self {
Self::from_128_bits(simd, crate::base::block::RAW_C1)
}
#[inline(always)]
fn into_bytes(self) -> Self::SelfArray {
transmute!([self.val])
}
#[inline(always)]
fn new(simd: $simd_ty, input: Self::SelfArray) -> Self {
Self {
val: transmute!([input]),
simd,
}
}
};
}
pub(crate) use gen_shared_block;
macro_rules! gen_shared_block128 {
($simd_ty:ty) => {
crate::base::block::gen_shared_block!($simd_ty);
type SelfArray = [u8; 16];
#[inline(always)]
fn ctx(simd: $simd_ty) -> Self {
Self::new(simd, crate::base::block::RAW_CTX_D1)
}
#[inline(always)]
fn from_128_bits(simd: $simd_ty, input: Array128) -> Self {
Self {
val: transmute!([input]),
simd,
}
}
#[inline(always)]
fn xor_down(self) -> Array128 {
Self::into_bytes(self)
}
};
}
pub(crate) use gen_shared_block128;
macro_rules! gen_shared_block256 {
($simd_ty:ty) => {
crate::base::block::gen_shared_block!($simd_ty);
type SelfArray = [u8; 32];
#[inline(always)]
fn ctx(simd: $simd_ty) -> Self {
Self::new(simd, crate::base::block::RAW_CTX_D2)
}
#[inline(always)]
fn from_128_bits(simd: $simd_ty, input: Array128) -> Self {
Self {
val: transmute!([[input, input]]),
simd,
}
}
};
}
pub(crate) use gen_shared_block256;
macro_rules! gen_shared_block512 {
($simd_ty:ty) => {
crate::base::block::gen_shared_block!($simd_ty);
type SelfArray = [u8; 64];
#[inline(always)]
fn ctx(simd: $simd_ty) -> Self {
Self::new(simd, crate::base::block::RAW_CTX_D4)
}
#[inline(always)]
fn from_128_bits(simd: $simd_ty, input: Array128) -> Self {
Self {
val: transmute!([[input, input, input, input]]),
simd,
}
}
};
}
pub(crate) use gen_shared_block512;