use super::EXPANDED_KEY_WORDS;
#[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]);
}