use super::cpu::HaveCryptoExt;
use crate::low;
unsafe extern "C" {
#[link_name = aws_lc_symbol!("aes_hw_set_encrypt_key")]
fn aes_hw_set_encrypt_key(user_key: *const u8, bits: i32, key: *mut AesHwKey) -> i32;
#[link_name = aws_lc_symbol!("aes_hw_encrypt")]
fn aes_hw_encrypt(input: *const u8, output: *mut u8, key: *const AesHwKey);
#[link_name = aws_lc_symbol!("aes_hw_ctr32_encrypt_blocks")]
fn aes_hw_ctr32_encrypt_blocks(
input: *const u8,
output: *mut u8,
blocks: usize,
key: *const AesHwKey,
ivec: *const [u8; 16],
);
}
core::arch::global_asm!(
".text",
".fpu neon",
".code 32",
include_str!("aws_lc/aesv8-armx.s"),
".fpu vfpv3",
aes_hw_set_encrypt_key = sym aes_hw_set_encrypt_key,
aes_hw_encrypt = sym aes_hw_encrypt,
aes_hw_ctr32_encrypt_blocks = sym aes_hw_ctr32_encrypt_blocks,
);
#[repr(C, align(16))]
pub(crate) struct AesHwKey {
rd_key: [u32; 60],
rounds: u32,
}
impl AesHwKey {
pub(crate) fn new(key: &[u8], _: HaveCryptoExt) -> Self {
let bits = match key.len() {
16 => 128,
32 => 256,
_ => unreachable!("callers check the AES key length"),
};
let mut r = Self {
rd_key: [0; 60],
rounds: 0,
};
let ret = unsafe { aes_hw_set_encrypt_key(key.as_ptr(), bits, &mut r) };
debug_assert_eq!(ret, 0);
r
}
pub(crate) fn encrypt_block(&self, inout: &mut [u8; 16]) {
unsafe { aes_hw_encrypt(inout.as_ptr(), inout.as_mut_ptr(), self) }
}
pub(crate) fn ctr32(&self, ivec: &[u8; 16], inout: &mut [[u8; 16]]) {
unsafe {
aes_hw_ctr32_encrypt_blocks(
inout.as_ptr().cast(),
inout.as_mut_ptr().cast(),
inout.len(),
self,
ivec,
)
}
}
}
impl Drop for AesHwKey {
fn drop(&mut self) {
low::zeroise_value(self);
}
}
impl low::generic::zeroise::Zeroable for AesHwKey {}