use core::ffi::c_void;
use crate::error::{check, len_as_u32, WolfCryptError};
pub struct AesGcmEncStream {
aes: wolfcrypt_rs::WcAes,
}
unsafe impl Send for AesGcmEncStream {}
impl AesGcmEncStream {
pub fn new(key: &[u8], iv: &[u8]) -> Result<Self, WolfCryptError> {
let mut aes = wolfcrypt_rs::WcAes::zeroed();
let rc = unsafe {
wolfcrypt_rs::wc_AesInit(
&mut aes as *mut wolfcrypt_rs::WcAes,
core::ptr::null_mut::<c_void>(),
wolfcrypt_rs::INVALID_DEVID,
)
};
check(rc, "wc_AesInit")?;
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmEncryptInit(
&mut aes as *mut wolfcrypt_rs::WcAes,
key.as_ptr(),
len_as_u32(key.len()),
iv.as_ptr(),
len_as_u32(iv.len()),
)
};
check(rc, "wc_AesGcmEncryptInit")?;
Ok(Self { aes })
}
pub fn update_aad(&mut self, aad: &[u8]) -> Result<(), WolfCryptError> {
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmEncryptUpdate(
&mut self.aes as *mut wolfcrypt_rs::WcAes,
core::ptr::null_mut(),
core::ptr::null(),
0,
aad.as_ptr(),
len_as_u32(aad.len()),
)
};
check(rc, "wc_AesGcmEncryptUpdate")
}
pub fn update(&mut self, plaintext: &[u8], out: &mut [u8]) -> Result<(), WolfCryptError> {
if out.len() < plaintext.len() {
return Err(WolfCryptError::InvalidInput);
}
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmEncryptUpdate(
&mut self.aes as *mut wolfcrypt_rs::WcAes,
out.as_mut_ptr(),
plaintext.as_ptr(),
len_as_u32(plaintext.len()),
core::ptr::null(),
0,
)
};
check(rc, "wc_AesGcmEncryptUpdate")
}
pub fn finalize(mut self, tag: &mut [u8]) -> Result<(), WolfCryptError> {
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmEncryptFinal(
&mut self.aes as *mut wolfcrypt_rs::WcAes,
tag.as_mut_ptr(),
len_as_u32(tag.len()),
)
};
check(rc, "wc_AesGcmEncryptFinal")
}
}
impl Drop for AesGcmEncStream {
fn drop(&mut self) {
unsafe {
wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes);
}
}
}
pub struct AesGcmDecStream {
aes: wolfcrypt_rs::WcAes,
}
unsafe impl Send for AesGcmDecStream {}
impl AesGcmDecStream {
pub fn new(key: &[u8], iv: &[u8]) -> Result<Self, WolfCryptError> {
let mut aes = wolfcrypt_rs::WcAes::zeroed();
let rc = unsafe {
wolfcrypt_rs::wc_AesInit(
&mut aes as *mut wolfcrypt_rs::WcAes,
core::ptr::null_mut::<c_void>(),
wolfcrypt_rs::INVALID_DEVID,
)
};
check(rc, "wc_AesInit")?;
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmDecryptInit(
&mut aes as *mut wolfcrypt_rs::WcAes,
key.as_ptr(),
len_as_u32(key.len()),
iv.as_ptr(),
len_as_u32(iv.len()),
)
};
check(rc, "wc_AesGcmDecryptInit")?;
Ok(Self { aes })
}
pub fn update_aad(&mut self, aad: &[u8]) -> Result<(), WolfCryptError> {
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmDecryptUpdate(
&mut self.aes as *mut wolfcrypt_rs::WcAes,
core::ptr::null_mut(),
core::ptr::null(),
0,
aad.as_ptr(),
len_as_u32(aad.len()),
)
};
check(rc, "wc_AesGcmDecryptUpdate")
}
pub fn update(&mut self, ciphertext: &[u8], out: &mut [u8]) -> Result<(), WolfCryptError> {
if out.len() < ciphertext.len() {
return Err(WolfCryptError::InvalidInput);
}
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmDecryptUpdate(
&mut self.aes as *mut wolfcrypt_rs::WcAes,
out.as_mut_ptr(),
ciphertext.as_ptr(),
len_as_u32(ciphertext.len()),
core::ptr::null(),
0,
)
};
check(rc, "wc_AesGcmDecryptUpdate")
}
pub fn finalize(mut self, tag: &[u8]) -> Result<(), WolfCryptError> {
let rc = unsafe {
wolfcrypt_rs::wc_AesGcmDecryptFinal(
&mut self.aes as *mut wolfcrypt_rs::WcAes,
tag.as_ptr(),
len_as_u32(tag.len()),
)
};
check(rc, "wc_AesGcmDecryptFinal")
}
}
impl Drop for AesGcmDecStream {
fn drop(&mut self) {
unsafe {
wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes);
}
}
}