#![cfg(cmac)]
use crate::sys;
use core::mem::MaybeUninit;
pub struct CMAC {
ws_cmac: sys::Cmac,
}
impl CMAC {
#[cfg(aes)]
pub fn generate(key: &[u8], data: &[u8], dout: &mut [u8]) -> Result<(), i32> {
let key_size = key.len() as u32;
let data_size = data.len() as u32;
let mut dout_size = dout.len() as u32;
let rc = unsafe {
sys::wc_AesCmacGenerate(
dout.as_mut_ptr(),
&mut dout_size,
data.as_ptr(),
data_size,
key.as_ptr(),
key_size,
)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn new(key: &[u8]) -> Result<Self, i32> {
Self::new_ex(key, None, None)
}
pub fn new_ex(
key: &[u8],
heap: Option<*mut core::ffi::c_void>,
dev_id: Option<i32>,
) -> Result<Self, i32> {
let key_size = key.len() as u32;
let mut ws_cmac: MaybeUninit<sys::Cmac> = MaybeUninit::uninit();
let typ = sys::CmacType_WC_CMAC_AES as i32;
let heap = match heap {
Some(heap) => heap,
None => core::ptr::null_mut(),
};
let dev_id = match dev_id {
Some(dev_id) => dev_id,
None => sys::INVALID_DEVID,
};
let rc = unsafe {
sys::wc_InitCmac_ex(
ws_cmac.as_mut_ptr(),
key.as_ptr(),
key_size,
typ,
core::ptr::null_mut(),
heap,
dev_id,
)
};
if rc != 0 {
return Err(rc);
}
let ws_cmac = unsafe { ws_cmac.assume_init() };
let cmac = CMAC { ws_cmac };
Ok(cmac)
}
#[cfg(aes)]
pub fn verify(key: &[u8], data: &[u8], check: &[u8]) -> Result<bool, i32> {
let key_size = key.len() as u32;
let data_size = data.len() as u32;
let check_size = check.len() as u32;
let rc = unsafe {
sys::wc_AesCmacVerify(
check.as_ptr(),
check_size,
data.as_ptr(),
data_size,
key.as_ptr(),
key_size,
)
};
if rc < 0 {
return Err(rc);
}
Ok(rc == 0)
}
#[cfg(aes)]
pub fn generate_ex(
&mut self,
key: &[u8],
data: &[u8],
dout: &mut [u8],
heap: Option<*mut core::ffi::c_void>,
dev_id: Option<i32>,
) -> Result<(), i32> {
let key_size = key.len() as u32;
let data_size = data.len() as u32;
let mut dout_size = dout.len() as u32;
let heap = match heap {
Some(heap) => heap,
None => core::ptr::null_mut(),
};
let dev_id = match dev_id {
Some(dev_id) => dev_id,
None => sys::INVALID_DEVID,
};
let rc = unsafe {
sys::wc_AesCmacGenerate_ex(
&mut self.ws_cmac,
dout.as_mut_ptr(),
&mut dout_size,
data.as_ptr(),
data_size,
key.as_ptr(),
key_size,
heap,
dev_id,
)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn update(&mut self, data: &[u8]) -> Result<(), i32> {
let data_size = data.len() as u32;
let rc = unsafe { sys::wc_CmacUpdate(&mut self.ws_cmac, data.as_ptr(), data_size) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
pub fn finalize(mut self, dout: &mut [u8]) -> Result<(), i32> {
let mut dout_size = dout.len() as u32;
let rc = unsafe {
sys::wc_CmacFinalNoFree(&mut self.ws_cmac, dout.as_mut_ptr(), &mut dout_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
#[cfg(aes)]
pub fn verify_ex(
&mut self,
key: &[u8],
data: &[u8],
check: &[u8],
heap: Option<*mut core::ffi::c_void>,
dev_id: Option<i32>,
) -> Result<bool, i32> {
let key_size = key.len() as u32;
let data_size = data.len() as u32;
let check_size = check.len() as u32;
let heap = match heap {
Some(heap) => heap,
None => core::ptr::null_mut(),
};
let dev_id = match dev_id {
Some(dev_id) => dev_id,
None => sys::INVALID_DEVID,
};
let rc = unsafe {
sys::wc_AesCmacVerify_ex(
&mut self.ws_cmac,
check.as_ptr(),
check_size,
data.as_ptr(),
data_size,
key.as_ptr(),
key_size,
heap,
dev_id,
)
};
if rc < 0 {
return Err(rc);
}
Ok(rc == 0)
}
}
impl Drop for CMAC {
fn drop(&mut self) {
unsafe {
sys::wc_CmacFree(&mut self.ws_cmac);
}
}
}