use alloc::vec::Vec;
use digest::KeyInit;
use crate::error::{CryptoError, Result};
pub trait Mac {
fn new(key: &[u8]) -> Result<Self>
where
Self: Sized;
fn update(&mut self, data: &[u8]);
fn finalize(self) -> Vec<u8>;
fn output_size() -> usize;
}
#[derive(Clone)]
pub struct HmacMd5 {
inner: hmac::Hmac<md5::Md5>,
}
#[derive(Clone)]
pub struct HmacSha1 {
inner: hmac::Hmac<sha1::Sha1>,
}
#[derive(Clone)]
pub struct HmacSha224 {
inner: hmac::Hmac<sha2::Sha224>,
}
#[derive(Clone)]
pub struct HmacSha256 {
inner: hmac::Hmac<sha2::Sha256>,
}
#[derive(Clone)]
pub struct HmacSha384 {
inner: hmac::Hmac<sha2::Sha384>,
}
#[derive(Clone)]
pub struct HmacSha512 {
inner: hmac::Hmac<sha2::Sha512>,
}
#[derive(Clone)]
pub struct HmacSm3 {
inner: hmac::Hmac<sm3::Sm3>,
}
macro_rules! impl_hmac {
($wrapper:ident, $hash:ty, $size:expr) => {
impl Mac for $wrapper {
fn new(key: &[u8]) -> Result<Self> {
let inner = hmac::Hmac::<$hash>::new_from_slice(key)
.map_err(|_| CryptoError::InvalidKey)?;
Ok(Self { inner })
}
fn update(&mut self, data: &[u8]) {
digest::Mac::update(&mut self.inner, data);
}
fn finalize(self) -> Vec<u8> {
digest::Mac::finalize(self.inner).into_bytes().to_vec()
}
fn output_size() -> usize {
$size
}
}
};
}
impl_hmac!(HmacMd5, md5::Md5, 16);
impl_hmac!(HmacSha1, sha1::Sha1, 20);
impl_hmac!(HmacSha224, sha2::Sha224, 28);
impl_hmac!(HmacSha256, sha2::Sha256, 32);
impl_hmac!(HmacSha384, sha2::Sha384, 48);
impl_hmac!(HmacSha512, sha2::Sha512, 64);
impl_hmac!(HmacSm3, sm3::Sm3, 32);
#[derive(Clone)]
pub struct Aes128Cmac {
inner: cmac::Cmac<aes::Aes128>,
}
#[derive(Clone)]
pub struct Aes192Cmac {
inner: cmac::Cmac<aes::Aes192>,
}
#[derive(Clone)]
pub struct Aes256Cmac {
inner: cmac::Cmac<aes::Aes256>,
}
#[derive(Clone)]
pub struct Sm4Cmac {
inner: cmac::Cmac<sm4::Sm4>,
}
macro_rules! impl_cmac {
($wrapper:ident, $cipher:ty, $size:expr) => {
impl Mac for $wrapper {
fn new(key: &[u8]) -> Result<Self> {
let inner = cmac::Cmac::<$cipher>::new_from_slice(key)
.map_err(|_| CryptoError::InvalidKey)?;
Ok(Self { inner })
}
fn update(&mut self, data: &[u8]) {
digest::Mac::update(&mut self.inner, data);
}
fn finalize(self) -> Vec<u8> {
digest::Mac::finalize(self.inner).into_bytes().to_vec()
}
fn output_size() -> usize {
$size
}
}
};
}
impl_cmac!(Aes128Cmac, aes::Aes128, 16);
impl_cmac!(Aes192Cmac, aes::Aes192, 16);
impl_cmac!(Aes256Cmac, aes::Aes256, 16);
impl_cmac!(Sm4Cmac, sm4::Sm4, 16);
#[derive(Clone)]
pub struct Des3Cmac {
inner: cmac::Cmac<des::TdesEde3>,
}
impl Mac for Des3Cmac {
fn new(key: &[u8]) -> Result<Self> {
let inner = cmac::Cmac::<des::TdesEde3>::new_from_slice(key)
.map_err(|_| CryptoError::InvalidKey)?;
Ok(Self { inner })
}
fn update(&mut self, data: &[u8]) {
digest::Mac::update(&mut self.inner, data);
}
fn finalize(self) -> Vec<u8> {
digest::Mac::finalize(self.inner).into_bytes().to_vec()
}
fn output_size() -> usize {
8
}
}