#![allow(unsafe_code)]
#[cfg(target_arch = "aarch64")]
use core::arch::aarch64::*;
#[target_feature(enable = "neon,aes")]
unsafe fn aesl_impl(block: &[u8; 16]) -> [u8; 16] {
let input = vld1q_u8(block.as_ptr());
let zero_key = vdupq_n_u8(0);
let after_sub_shift = vaeseq_u8(input, zero_key);
let result = vaesmcq_u8(after_sub_shift);
let mut output = [0u8; 16];
vst1q_u8(output.as_mut_ptr(), result);
output
}
#[inline]
pub fn aesl(block: &[u8; 16]) -> [u8; 16] {
unsafe { aesl_impl(block) }
}
#[target_feature(enable = "neon")]
unsafe fn xor_block_impl(a: &[u8; 16], b: &[u8; 16]) -> [u8; 16] {
let a_vec = vld1q_u8(a.as_ptr());
let b_vec = vld1q_u8(b.as_ptr());
let result_vec = veorq_u8(a_vec, b_vec);
let mut result = [0u8; 16];
vst1q_u8(result.as_mut_ptr(), result_vec);
result
}
#[inline]
pub fn xor_block(a: &[u8; 16], b: &[u8; 16]) -> [u8; 16] {
unsafe { xor_block_impl(a, b) }
}
#[target_feature(enable = "neon")]
unsafe fn xor_reduce_blocks_impl(blocks: &[[u8; 16]; 16]) -> [u8; 16] {
let mut result = vld1q_u8(blocks[0].as_ptr());
for block in blocks.iter().skip(1) {
let block_vec = vld1q_u8(block.as_ptr());
result = veorq_u8(result, block_vec);
}
let mut output = [0u8; 16];
vst1q_u8(output.as_mut_ptr(), result);
output
}
#[inline]
pub fn xor_reduce_blocks(blocks: &[[u8; 16]; 16]) -> [u8; 16] {
unsafe { xor_reduce_blocks_impl(blocks) }
}
#[target_feature(enable = "neon,aes")]
unsafe fn xaesl_impl(x: &[u8; 16], y: &[u8; 16]) -> [u8; 16] {
let x_vec = vld1q_u8(x.as_ptr());
let y_vec = vld1q_u8(y.as_ptr());
let xor_result = veorq_u8(x_vec, y_vec);
let after_sub_shift = vaeseq_u8(xor_result, vdupq_n_u8(0));
let result = vaesmcq_u8(after_sub_shift);
let mut output = [0u8; 16];
vst1q_u8(output.as_mut_ptr(), result);
output
}
#[inline]
pub fn xaesl(x: &[u8; 16], y: &[u8; 16]) -> [u8; 16] {
unsafe { xaesl_impl(x, y) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_arm_aesl() {
let input = [
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
0xee, 0xff,
];
let expected = [
0x63, 0x79, 0xe6, 0xd9, 0xf4, 0x67, 0xfb, 0x76, 0xad, 0x06, 0x3c, 0xf4, 0xd2, 0xeb,
0x8a, 0xa3,
];
let result = unsafe { aesl_impl(&input) };
assert_eq!(result, expected);
}
#[test]
fn test_arm_xaesl() {
let x = [0x11; 16];
let y = [0x22; 16];
let manual_xor = super::super::xor_block_simd(&x, &y);
let manual_result = unsafe { aesl_impl(&manual_xor) };
let xaesl_result = unsafe { xaesl_impl(&x, &y) };
assert_eq!(xaesl_result, manual_result);
}
}