use core::fmt::Debug;
use crate::traits::{VerificationError, ct};
pub trait Mac: Clone {
const TAG_SIZE: usize;
type Tag: Copy + Eq + Debug + AsRef<[u8]>;
#[must_use]
fn new(key: &[u8]) -> Self;
fn update(&mut self, data: &[u8]);
#[inline]
fn update_vectored(&mut self, bufs: &[&[u8]]) {
for buf in bufs {
self.update(buf);
}
}
#[cfg(feature = "std")]
#[inline]
fn update_io_slices(&mut self, bufs: &[std::io::IoSlice<'_>]) {
for buf in bufs {
self.update(buf);
}
}
#[must_use]
fn finalize(&self) -> Self::Tag;
fn reset(&mut self);
#[inline]
#[must_use]
fn mac(key: &[u8], data: &[u8]) -> Self::Tag {
let mut mac = Self::new(key);
mac.update(data);
mac.finalize()
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
#[inline]
#[must_use]
fn finalize_to_vec(&self) -> alloc::vec::Vec<u8> {
self.finalize().as_ref().to_vec()
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
#[inline]
#[must_use]
fn mac_to_vec(key: &[u8], data: &[u8]) -> alloc::vec::Vec<u8> {
Self::mac(key, data).as_ref().to_vec()
}
#[inline]
#[must_use = "MAC verification must be checked; a dropped Result silently accepts a forged tag"]
fn verify(&self, expected: &Self::Tag) -> Result<(), VerificationError> {
if ct::constant_time_eq(self.finalize().as_ref(), expected.as_ref()) {
Ok(())
} else {
Err(VerificationError::new())
}
}
#[inline]
#[must_use = "MAC verification must be checked; a dropped Result silently accepts a forged tag"]
fn verify_tag(key: &[u8], data: &[u8], expected: &Self::Tag) -> Result<(), VerificationError> {
if ct::constant_time_eq(Self::mac(key, data).as_ref(), expected.as_ref()) {
Ok(())
} else {
Err(VerificationError::new())
}
}
}