use super::{EXPANDED_KEY_WORDS, EXPANDED_KEY_WORDS_128};
#[derive(Clone)]
#[repr(C, align(8))]
pub(in crate::aead) struct KmKey {
raw: [u8; 32],
rk: [u32; EXPANDED_KEY_WORDS],
}
impl KmKey {
pub(super) fn from_portable(rk: [u32; EXPANDED_KEY_WORDS]) -> Self {
let mut raw = [0u8; 32];
let mut i = 0usize;
while i < 8 {
let off = i.strict_mul(4);
let bytes = rk[i].to_be_bytes();
raw[off] = bytes[0];
raw[off.strict_add(1)] = bytes[1];
raw[off.strict_add(2)] = bytes[2];
raw[off.strict_add(3)] = bytes[3];
i = i.strict_add(1);
}
Self { raw, rk }
}
pub(super) fn zeroize(&mut self) {
crate::traits::ct::zeroize(&mut self.raw);
let bytes =
unsafe { core::slice::from_raw_parts_mut(self.rk.as_mut_ptr().cast::<u8>(), EXPANDED_KEY_WORDS.strict_mul(4)) };
crate::traits::ct::zeroize(bytes);
}
}
pub(super) unsafe fn encrypt_block_raw(raw_key: &[u8; 32], block: &mut [u8; 16]) {
let mut src: [u8; 16] = *block;
let parm = raw_key.as_ptr();
let src_ptr = src.as_ptr();
let dest_ptr = block.as_mut_ptr();
unsafe {
core::arch::asm!(
"0:",
".insn rre, 0xB92E0000, 2, 4",
"jo 0b",
inout("r0") 20u64 => _,
in("r1") parm,
inout("r2") dest_ptr => _,
inout("r3") 16u64 => _,
inout("r4") src_ptr => _,
inout("r5") 16u64 => _,
options(nostack),
);
}
crate::traits::ct::zeroize(&mut src);
}
pub(super) unsafe fn encrypt_block(key: &KmKey, block: &mut [u8; 16]) {
unsafe { encrypt_block_raw(&key.raw, block) }
}
pub(super) unsafe fn encrypt_blocks(key: &KmKey, blocks: &mut [u8], count: usize) {
debug_assert_eq!(blocks.len(), count.strict_mul(16));
let len = count.strict_mul(16);
let mut src = [0u8; 16 * 8]; src[..len].copy_from_slice(&blocks[..len]);
let parm = key.raw.as_ptr();
let src_ptr = src.as_ptr();
let dest_ptr = blocks.as_mut_ptr();
unsafe {
core::arch::asm!(
"0:",
".insn rre, 0xB92E0000, 2, 4",
"jo 0b",
inout("r0") 20u64 => _,
in("r1") parm,
inout("r2") dest_ptr => _,
inout("r3") len as u64 => _,
inout("r4") src_ptr => _,
inout("r5") len as u64 => _,
options(nostack),
);
}
crate::traits::ct::zeroize(&mut src[..len]);
}
#[derive(Clone)]
#[repr(C, align(8))]
pub(in crate::aead) struct Km128Key {
raw: [u8; 16],
rk: [u32; EXPANDED_KEY_WORDS_128],
}
impl Km128Key {
pub(super) fn from_portable(rk: [u32; EXPANDED_KEY_WORDS_128]) -> Self {
let mut raw = [0u8; 16];
let mut i = 0usize;
while i < 4 {
let off = i.strict_mul(4);
let bytes = rk[i].to_be_bytes();
raw[off] = bytes[0];
raw[off.strict_add(1)] = bytes[1];
raw[off.strict_add(2)] = bytes[2];
raw[off.strict_add(3)] = bytes[3];
i = i.strict_add(1);
}
Self { raw, rk }
}
pub(super) fn zeroize(&mut self) {
crate::traits::ct::zeroize(&mut self.raw);
let bytes = unsafe {
core::slice::from_raw_parts_mut(self.rk.as_mut_ptr().cast::<u8>(), EXPANDED_KEY_WORDS_128.strict_mul(4))
};
crate::traits::ct::zeroize(bytes);
}
}
pub(super) unsafe fn encrypt_block_raw_128(raw_key: &[u8; 16], block: &mut [u8; 16]) {
let mut src: [u8; 16] = *block;
let parm = raw_key.as_ptr();
let src_ptr = src.as_ptr();
let dest_ptr = block.as_mut_ptr();
unsafe {
core::arch::asm!(
"0:",
".insn rre, 0xB92E0000, 2, 4",
"jo 0b",
inout("r0") 18u64 => _,
in("r1") parm,
inout("r2") dest_ptr => _,
inout("r3") 16u64 => _,
inout("r4") src_ptr => _,
inout("r5") 16u64 => _,
options(nostack),
);
}
crate::traits::ct::zeroize(&mut src);
}
pub(super) unsafe fn encrypt_block_128(key: &Km128Key, block: &mut [u8; 16]) {
unsafe { encrypt_block_raw_128(&key.raw, block) }
}
#[cfg(any(feature = "aes-gcm", feature = "aes-gcm-siv"))]
pub(super) unsafe fn encrypt_blocks_128(key: &Km128Key, blocks: &mut [u8], count: usize) {
debug_assert_eq!(blocks.len(), count.strict_mul(16));
let len = count.strict_mul(16);
let mut src = [0u8; 16 * 8];
src[..len].copy_from_slice(&blocks[..len]);
let parm = key.raw.as_ptr();
let src_ptr = src.as_ptr();
let dest_ptr = blocks.as_mut_ptr();
unsafe {
core::arch::asm!(
"0:",
".insn rre, 0xB92E0000, 2, 4",
"jo 0b",
inout("r0") 18u64 => _,
in("r1") parm,
inout("r2") dest_ptr => _,
inout("r3") len as u64 => _,
inout("r4") src_ptr => _,
inout("r5") len as u64 => _,
options(nostack),
);
}
crate::traits::ct::zeroize(&mut src[..len]);
}