use std::fmt;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HardwareKind {
WindowsTpm20,
MacSecureEnclave,
LinuxTpm20,
}
impl HardwareKind {
pub const fn wire_id(self) -> u8 {
match self {
Self::WindowsTpm20 => 0x01,
Self::MacSecureEnclave => 0x02,
Self::LinuxTpm20 => 0x03,
}
}
pub const fn from_wire_id(id: u8) -> Option<Self> {
match id {
0x01 => Some(Self::WindowsTpm20),
0x02 => Some(Self::MacSecureEnclave),
0x03 => Some(Self::LinuxTpm20),
_ => None,
}
}
pub const fn label(self) -> &'static str {
match self {
Self::WindowsTpm20 => "Windows TPM 2.0",
Self::MacSecureEnclave => "Apple Secure Enclave",
Self::LinuxTpm20 => "Linux TPM 2.0",
}
}
}
impl fmt::Display for HardwareKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.label())
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DegradeReason {
NoHardwarePresent,
ProbeIndeterminate {
detail: String,
},
HardwareUnusable {
detail: String,
},
NotRequested,
BlobNotWrapped,
}
impl fmt::Display for DegradeReason {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NoHardwarePresent => f.write_str("no hardware trusted component on this host"),
Self::ProbeIndeterminate { detail } => {
write!(f, "could not determine hardware availability: {detail}")
}
Self::HardwareUnusable { detail } => {
write!(f, "hardware present but unusable: {detail}")
}
Self::NotRequested => f.write_str("hardware binding not requested"),
Self::BlobNotWrapped => f.write_str("this key material is not hardware-wrapped"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProtectionTier {
Hardware(HardwareKind),
Software(DegradeReason),
}
impl ProtectionTier {
pub const fn is_hardware_bound(&self) -> bool {
matches!(self, Self::Hardware(_))
}
pub const fn hardware_kind(&self) -> Option<HardwareKind> {
match self {
Self::Hardware(kind) => Some(*kind),
Self::Software(_) => None,
}
}
pub const fn degrade_reason(&self) -> Option<&DegradeReason> {
match self {
Self::Hardware(_) => None,
Self::Software(reason) => Some(reason),
}
}
}
impl fmt::Display for ProtectionTier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Hardware(kind) => write!(f, "hardware-bound ({kind})"),
Self::Software(reason) => write!(f, "software-wrapped ({reason})"),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HardwareProbe {
Available(HardwareKind),
Absent,
Indeterminate {
detail: String,
},
}
impl HardwareProbe {
pub fn indeterminate(detail: impl fmt::Display) -> Self {
Self::Indeterminate {
detail: detail.to_string(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HardwarePolicy {
Required,
#[default]
Preferred,
Optional,
}
impl HardwarePolicy {
pub const fn allows_degrade(self) -> bool {
!matches!(self, Self::Required)
}
pub const fn allows_indeterminate_degrade(self) -> bool {
matches!(self, Self::Optional)
}
}