use crate::interface_types::algorithm::HashingAlgorithm;
#[cfg(feature = "rustcrypto")]
use {
crate::{Error, Result, WrapperErrorKind, structures::HashAgile},
digest::{Output, OutputSizeUser},
};
pub trait AssociatedHashingAlgorithm {
const TPM_DIGEST: HashingAlgorithm;
}
#[cfg(feature = "sha1")]
impl AssociatedHashingAlgorithm for sha1::Sha1 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sha1;
}
#[cfg(feature = "sha2")]
impl AssociatedHashingAlgorithm for sha2::Sha256 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sha256;
}
#[cfg(feature = "sha2")]
impl AssociatedHashingAlgorithm for sha2::Sha384 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sha384;
}
#[cfg(feature = "sha2")]
impl AssociatedHashingAlgorithm for sha2::Sha512 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sha512;
}
#[cfg(feature = "sm3")]
impl AssociatedHashingAlgorithm for sm3::Sm3 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sm3_256;
}
#[cfg(feature = "sha3")]
impl AssociatedHashingAlgorithm for sha3::Sha3_256 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sha3_256;
}
#[cfg(feature = "sha3")]
impl AssociatedHashingAlgorithm for sha3::Sha3_384 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sha3_384;
}
#[cfg(feature = "sha3")]
impl AssociatedHashingAlgorithm for sha3::Sha3_512 {
const TPM_DIGEST: HashingAlgorithm = HashingAlgorithm::Sha3_512;
}
impl HashAgile {
#[cfg(feature = "rustcrypto")]
#[expect(
clippy::unnecessary_fallible_conversions,
reason = "GenericArray::From<&[T]> will panic if the payload is not the same length"
)]
pub fn to_output<H: AssociatedHashingAlgorithm + OutputSizeUser>(&self) -> Result<Output<H>> {
if self.algorithm == H::TPM_DIGEST {
<&Output<H>>::try_from(self.digest.as_bytes())
.map_err(|_| Error::local_error(WrapperErrorKind::WrongValueFromTpm))
.cloned()
} else {
Err(Error::local_error(WrapperErrorKind::InvalidParam))
}
}
}