use crate::CryptoError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum MacAlgo {
HmacSha256,
HmacSha384,
HmacSha512,
HmacSha3_256,
HmacSha3_512,
Poly1305,
CmacAes128,
CmacAes256,
Kmac128 { output_len: usize },
Kmac256 { output_len: usize },
}
#[cfg(feature = "pure")]
#[must_use]
pub fn mac_impl(algo: MacAlgo) -> oxicrypto_core::Box<dyn oxicrypto_core::Mac + Send + Sync> {
match algo {
MacAlgo::HmacSha256 => oxicrypto_core::Box::new(oxicrypto_mac::HmacSha256),
MacAlgo::HmacSha384 => oxicrypto_core::Box::new(oxicrypto_mac::HmacSha384),
MacAlgo::HmacSha512 => oxicrypto_core::Box::new(oxicrypto_mac::HmacSha512),
MacAlgo::HmacSha3_256 => oxicrypto_core::Box::new(oxicrypto_mac::HmacSha3_256),
MacAlgo::HmacSha3_512 => oxicrypto_core::Box::new(oxicrypto_mac::HmacSha3_512),
MacAlgo::Poly1305 => oxicrypto_core::Box::new(oxicrypto_mac::Poly1305Mac),
MacAlgo::CmacAes128 => oxicrypto_core::Box::new(oxicrypto_mac::CmacAes128),
MacAlgo::CmacAes256 => oxicrypto_core::Box::new(oxicrypto_mac::CmacAes256),
MacAlgo::Kmac128 { output_len } => {
let len = output_len.max(1);
oxicrypto_core::Box::new(
oxicrypto_mac::Kmac128::new(b"", len)
.unwrap_or_else(|_| unreachable!("len >= 1 is always valid")),
)
}
MacAlgo::Kmac256 { output_len } => {
let len = output_len.max(1);
oxicrypto_core::Box::new(
oxicrypto_mac::Kmac256::new(b"", len)
.unwrap_or_else(|_| unreachable!("len >= 1 is always valid")),
)
}
}
}
impl core::fmt::Display for MacAlgo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
MacAlgo::HmacSha256 => f.write_str("HMAC-SHA-256"),
MacAlgo::HmacSha384 => f.write_str("HMAC-SHA-384"),
MacAlgo::HmacSha512 => f.write_str("HMAC-SHA-512"),
MacAlgo::HmacSha3_256 => f.write_str("HMAC-SHA3-256"),
MacAlgo::HmacSha3_512 => f.write_str("HMAC-SHA3-512"),
MacAlgo::Poly1305 => f.write_str("Poly1305"),
MacAlgo::CmacAes128 => f.write_str("CMAC-AES-128"),
MacAlgo::CmacAes256 => f.write_str("CMAC-AES-256"),
MacAlgo::Kmac128 { output_len } => write!(f, "KMAC128/{output_len}"),
MacAlgo::Kmac256 { output_len } => write!(f, "KMAC256/{output_len}"),
}
}
}
impl core::str::FromStr for MacAlgo {
type Err = CryptoError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Some(rest) = s
.strip_prefix("KMAC128/")
.or_else(|| s.strip_prefix("kmac128/"))
{
let output_len = rest
.parse::<usize>()
.map_err(|_| CryptoError::UnsupportedAlgorithm)?;
return Ok(MacAlgo::Kmac128 { output_len });
}
if let Some(rest) = s
.strip_prefix("KMAC256/")
.or_else(|| s.strip_prefix("kmac256/"))
{
let output_len = rest
.parse::<usize>()
.map_err(|_| CryptoError::UnsupportedAlgorithm)?;
return Ok(MacAlgo::Kmac256 { output_len });
}
match s {
"HMAC-SHA-256" | "hmac-sha-256" | "HMACSHA256" => Ok(MacAlgo::HmacSha256),
"HMAC-SHA-384" | "hmac-sha-384" | "HMACSHA384" => Ok(MacAlgo::HmacSha384),
"HMAC-SHA-512" | "hmac-sha-512" | "HMACSHA512" => Ok(MacAlgo::HmacSha512),
"HMAC-SHA3-256" | "hmac-sha3-256" | "HMACSHA3256" => Ok(MacAlgo::HmacSha3_256),
"HMAC-SHA3-512" | "hmac-sha3-512" | "HMACSHA3512" => Ok(MacAlgo::HmacSha3_512),
"Poly1305" | "poly1305" | "POLY1305" => Ok(MacAlgo::Poly1305),
"CMAC-AES-128" | "cmac-aes-128" | "CMACAES128" => Ok(MacAlgo::CmacAes128),
"CMAC-AES-256" | "cmac-aes-256" | "CMACAES256" => Ok(MacAlgo::CmacAes256),
_ => Err(CryptoError::UnsupportedAlgorithm),
}
}
}
impl TryFrom<&str> for MacAlgo {
type Error = CryptoError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
s.parse()
}
}