use super::{BatchBlocks, State, Word};
pub(super) fn broadcast<W: Word>(block: &[u8]) -> BatchBlocks<W> {
debug_assert_eq!(block.len(), 16);
let mut out = BatchBlocks::<W>::default();
for slot in out.iter_mut() {
slot.copy_from_slice(block);
}
out
}
#[inline]
pub(super) fn delta_swap_1<W: Word>(a: &mut W, shift: u32, mask: W) {
let t = (*a ^ ((*a) >> shift)) & mask;
*a ^= t ^ (t << shift);
}
#[inline]
pub(super) fn delta_swap_2<W: Word>(a: &mut W, b: &mut W, shift: u32, mask: W) {
let t = (*a ^ ((*b) >> shift)) & mask;
*a ^= t;
*b ^= t << shift;
}
#[cfg(any(not(aes_backend_soft = "compact"), feature = "hazmat"))]
#[inline]
pub(super) fn shift_rows_1<W: Word>(state: &mut [W]) {
debug_assert_eq!(state.len(), 8);
for x in state.iter_mut() {
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x00, 0x03, 0x0f, 0x0c));
delta_swap_1(x, W::QUARTER_ROW, W::pack_rows(0x00, 0x33, 0x00, 0x33));
}
}
#[inline]
pub(super) fn shift_rows_2<W: Word>(state: &mut [W]) {
debug_assert_eq!(state.len(), 8);
for x in state.iter_mut() {
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x00, 0x0f, 0x00, 0x0f));
}
}
#[inline]
pub(super) fn shift_rows_3<W: Word>(state: &mut [W]) {
debug_assert_eq!(state.len(), 8);
for x in state.iter_mut() {
delta_swap_1(x, W::HALF_ROW, W::pack_rows(0x00, 0x0c, 0x0f, 0x03));
delta_swap_1(x, W::QUARTER_ROW, W::pack_rows(0x00, 0x33, 0x00, 0x33));
}
}
#[inline(always)]
pub(super) fn inv_shift_rows_1<W: Word>(state: &mut [W]) {
shift_rows_3(state);
}
#[inline(always)]
pub(super) fn inv_shift_rows_2<W: Word>(state: &mut [W]) {
shift_rows_2(state);
}
#[cfg(not(aes_backend_soft = "compact"))]
#[inline(always)]
pub(super) fn inv_shift_rows_3<W: Word>(state: &mut [W]) {
shift_rows_1(state);
}
pub(super) fn xor_columns<W: Word>(rkeys: &mut [W], offset: usize, idx_xor: usize, idx_ror: u32) {
for i in 0..8 {
let off_i = offset + i;
let rk = rkeys[off_i - idx_xor] ^ (W::uniform_row(0x03) & rkeys[off_i].ror(idx_ror));
rkeys[off_i] = rk
^ (W::uniform_row(0xfc) & (rk << W::QUARTER_ROW))
^ (W::uniform_row(0xf0) & (rk << W::HALF_ROW))
^ (W::uniform_row(0xc0) & (rk << (3 * W::QUARTER_ROW)));
}
}
pub(super) fn memshift32<W: Word>(buffer: &mut [W], src_offset: usize) {
debug_assert_eq!(src_offset % 8, 0);
let dst_offset = src_offset + 8;
debug_assert!(dst_offset + 8 <= buffer.len());
for i in (0..8).rev() {
buffer[dst_offset + i] = buffer[src_offset + i];
}
}
#[inline]
pub(super) fn add_round_key<W: Word>(state: &mut State<W>, rkey: &[W]) {
debug_assert_eq!(rkey.len(), 8);
for (a, b) in state.iter_mut().zip(rkey) {
*a ^= *b;
}
}
#[inline(always)]
pub(super) fn add_round_constant_bit<W: Word>(state: &mut [W], bit: usize) {
state[bit] ^= W::pack_rows(0x00, 0xc0, 0x00, 0x00);
}