use core::arch::asm;
#[derive(Clone)]
#[repr(C, align(64))]
pub(super) struct RvRoundKeys {
rk: [[u8; 16]; 15],
}
impl RvRoundKeys {
pub(super) fn zeroize(&mut self) {
let bytes = unsafe { core::slice::from_raw_parts_mut(self.rk.as_mut_ptr().cast::<u8>(), 15usize.strict_mul(16)) };
crate::traits::ct::zeroize(bytes);
}
}
pub(super) fn from_portable(rk: &[u32; 60]) -> RvRoundKeys {
let mut keys = [[0u8; 16]; 15];
let mut i = 0usize;
while i < 15 {
let base = i.strict_mul(4);
keys[i][0..4].copy_from_slice(&rk[base].to_be_bytes());
keys[i][4..8].copy_from_slice(&rk[base.strict_add(1)].to_be_bytes());
keys[i][8..12].copy_from_slice(&rk[base.strict_add(2)].to_be_bytes());
keys[i][12..16].copy_from_slice(&rk[base.strict_add(3)].to_be_bytes());
i = i.strict_add(1);
}
RvRoundKeys { rk: keys }
}
#[target_feature(enable = "v", enable = "zvkned")]
pub(super) unsafe fn encrypt_block(keys: &RvRoundKeys, block: &mut [u8; 16]) {
unsafe {
let block_ptr = block.as_mut_ptr();
let rk = &keys.rk;
asm!(
"vsetivli zero, 4, e32, m1, ta, ma",
"vle32.v v1, ({block})",
"vle32.v v2, ({rk0})",
"vaesz.vs v1, v2",
"vle32.v v2, ({rk1})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk2})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk3})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk4})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk5})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk6})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk7})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk8})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk9})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk10})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk11})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk12})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk13})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk14})",
"vaesef.vs v1, v2",
"vse32.v v1, ({block})",
block = in(reg) block_ptr,
rk0 = in(reg) rk[0].as_ptr(),
rk1 = in(reg) rk[1].as_ptr(),
rk2 = in(reg) rk[2].as_ptr(),
rk3 = in(reg) rk[3].as_ptr(),
rk4 = in(reg) rk[4].as_ptr(),
rk5 = in(reg) rk[5].as_ptr(),
rk6 = in(reg) rk[6].as_ptr(),
rk7 = in(reg) rk[7].as_ptr(),
rk8 = in(reg) rk[8].as_ptr(),
rk9 = in(reg) rk[9].as_ptr(),
rk10 = in(reg) rk[10].as_ptr(),
rk11 = in(reg) rk[11].as_ptr(),
rk12 = in(reg) rk[12].as_ptr(),
rk13 = in(reg) rk[13].as_ptr(),
rk14 = in(reg) rk[14].as_ptr(),
out("v1") _,
out("v2") _,
options(nostack),
);
}
}
#[target_feature(enable = "v", enable = "zvkned")]
pub(super) unsafe fn encrypt_4blocks(keys: &RvRoundKeys, blocks: &mut [[u8; 16]; 4]) {
unsafe {
let b0 = blocks[0].as_mut_ptr();
let b1 = blocks[1].as_mut_ptr();
let b2 = blocks[2].as_mut_ptr();
let b3 = blocks[3].as_mut_ptr();
let rk = &keys.rk;
asm!(
"vsetivli zero, 4, e32, m1, ta, ma",
"vle32.v v1, ({b0})",
"vle32.v v2, ({b1})",
"vle32.v v3, ({b2})",
"vle32.v v4, ({b3})",
"vle32.v v5, ({rk0})",
"vaesz.vs v1, v5",
"vaesz.vs v2, v5",
"vaesz.vs v3, v5",
"vaesz.vs v4, v5",
"vle32.v v5, ({rk1})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk2})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk3})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk4})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk5})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk6})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk7})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk8})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk9})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk10})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk11})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk12})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk13})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk14})",
"vaesef.vs v1, v5",
"vaesef.vs v2, v5",
"vaesef.vs v3, v5",
"vaesef.vs v4, v5",
"vse32.v v1, ({b0})",
"vse32.v v2, ({b1})",
"vse32.v v3, ({b2})",
"vse32.v v4, ({b3})",
b0 = in(reg) b0,
b1 = in(reg) b1,
b2 = in(reg) b2,
b3 = in(reg) b3,
rk0 = in(reg) rk[0].as_ptr(),
rk1 = in(reg) rk[1].as_ptr(),
rk2 = in(reg) rk[2].as_ptr(),
rk3 = in(reg) rk[3].as_ptr(),
rk4 = in(reg) rk[4].as_ptr(),
rk5 = in(reg) rk[5].as_ptr(),
rk6 = in(reg) rk[6].as_ptr(),
rk7 = in(reg) rk[7].as_ptr(),
rk8 = in(reg) rk[8].as_ptr(),
rk9 = in(reg) rk[9].as_ptr(),
rk10 = in(reg) rk[10].as_ptr(),
rk11 = in(reg) rk[11].as_ptr(),
rk12 = in(reg) rk[12].as_ptr(),
rk13 = in(reg) rk[13].as_ptr(),
rk14 = in(reg) rk[14].as_ptr(),
out("v1") _,
out("v2") _,
out("v3") _,
out("v4") _,
out("v5") _,
options(nostack),
);
}
}
#[derive(Clone)]
#[repr(C, align(64))]
pub(super) struct Rv128RoundKeys {
rk: [[u8; 16]; 11],
}
impl Rv128RoundKeys {
pub(super) fn zeroize(&mut self) {
let bytes = unsafe { core::slice::from_raw_parts_mut(self.rk.as_mut_ptr().cast::<u8>(), 11usize.strict_mul(16)) };
crate::traits::ct::zeroize(bytes);
}
}
pub(super) fn from_portable_128(rk: &[u32; 44]) -> Rv128RoundKeys {
let mut keys = [[0u8; 16]; 11];
let mut i = 0usize;
while i < 11 {
let base = i.strict_mul(4);
keys[i][0..4].copy_from_slice(&rk[base].to_be_bytes());
keys[i][4..8].copy_from_slice(&rk[base.strict_add(1)].to_be_bytes());
keys[i][8..12].copy_from_slice(&rk[base.strict_add(2)].to_be_bytes());
keys[i][12..16].copy_from_slice(&rk[base.strict_add(3)].to_be_bytes());
i = i.strict_add(1);
}
Rv128RoundKeys { rk: keys }
}
#[target_feature(enable = "v", enable = "zvkned")]
pub(super) unsafe fn encrypt_block_128(keys: &Rv128RoundKeys, block: &mut [u8; 16]) {
unsafe {
let block_ptr = block.as_mut_ptr();
let rk = &keys.rk;
asm!(
"vsetivli zero, 4, e32, m1, ta, ma",
"vle32.v v1, ({block})",
"vle32.v v2, ({rk0})",
"vaesz.vs v1, v2",
"vle32.v v2, ({rk1})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk2})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk3})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk4})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk5})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk6})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk7})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk8})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk9})",
"vaesem.vs v1, v2",
"vle32.v v2, ({rk10})",
"vaesef.vs v1, v2",
"vse32.v v1, ({block})",
block = in(reg) block_ptr,
rk0 = in(reg) rk[0].as_ptr(),
rk1 = in(reg) rk[1].as_ptr(),
rk2 = in(reg) rk[2].as_ptr(),
rk3 = in(reg) rk[3].as_ptr(),
rk4 = in(reg) rk[4].as_ptr(),
rk5 = in(reg) rk[5].as_ptr(),
rk6 = in(reg) rk[6].as_ptr(),
rk7 = in(reg) rk[7].as_ptr(),
rk8 = in(reg) rk[8].as_ptr(),
rk9 = in(reg) rk[9].as_ptr(),
rk10 = in(reg) rk[10].as_ptr(),
out("v1") _,
out("v2") _,
options(nostack),
);
}
}
#[target_feature(enable = "v", enable = "zvkned")]
pub(super) unsafe fn encrypt_4blocks_128(keys: &Rv128RoundKeys, blocks: &mut [[u8; 16]; 4]) {
unsafe {
let b0 = blocks[0].as_mut_ptr();
let b1 = blocks[1].as_mut_ptr();
let b2 = blocks[2].as_mut_ptr();
let b3 = blocks[3].as_mut_ptr();
let rk = &keys.rk;
asm!(
"vsetivli zero, 4, e32, m1, ta, ma",
"vle32.v v1, ({b0})",
"vle32.v v2, ({b1})",
"vle32.v v3, ({b2})",
"vle32.v v4, ({b3})",
"vle32.v v5, ({rk0})",
"vaesz.vs v1, v5",
"vaesz.vs v2, v5",
"vaesz.vs v3, v5",
"vaesz.vs v4, v5",
"vle32.v v5, ({rk1})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk2})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk3})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk4})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk5})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk6})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk7})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk8})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk9})",
"vaesem.vs v1, v5",
"vaesem.vs v2, v5",
"vaesem.vs v3, v5",
"vaesem.vs v4, v5",
"vle32.v v5, ({rk10})",
"vaesef.vs v1, v5",
"vaesef.vs v2, v5",
"vaesef.vs v3, v5",
"vaesef.vs v4, v5",
"vse32.v v1, ({b0})",
"vse32.v v2, ({b1})",
"vse32.v v3, ({b2})",
"vse32.v v4, ({b3})",
b0 = in(reg) b0,
b1 = in(reg) b1,
b2 = in(reg) b2,
b3 = in(reg) b3,
rk0 = in(reg) rk[0].as_ptr(),
rk1 = in(reg) rk[1].as_ptr(),
rk2 = in(reg) rk[2].as_ptr(),
rk3 = in(reg) rk[3].as_ptr(),
rk4 = in(reg) rk[4].as_ptr(),
rk5 = in(reg) rk[5].as_ptr(),
rk6 = in(reg) rk[6].as_ptr(),
rk7 = in(reg) rk[7].as_ptr(),
rk8 = in(reg) rk[8].as_ptr(),
rk9 = in(reg) rk[9].as_ptr(),
rk10 = in(reg) rk[10].as_ptr(),
out("v1") _,
out("v2") _,
out("v3") _,
out("v4") _,
out("v5") _,
options(nostack),
);
}
}