use crate::baseline::{ExpectedPcr, PcrBaseline};
use crate::drift::{DriftDetectionEngine, DriftPolicyMode, DriftReport, DriftSeverity};
use crate::pcr::PcrSemantic;
use crate::secure_boot::{SecureBootEvidence, SecureBootState};
use crate::trust_domains::VerificationDecisionReason;
use alloc::string::String;
use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum PlatformClass {
LinuxServer,
BitcoinNode,
EmbeddedDevice,
CloudVm,
ConfidentialVm,
BareMetalWorkstation,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum PlatformVendor {
Dell,
Lenovo,
HP,
Intel,
AMD,
Coreboot,
Qemu,
Unknown,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct PlatformProfile {
pub profile_id: String,
pub vendor: PlatformVendor,
pub platform_class: PlatformClass,
pub secure_boot_required: bool,
pub expected_pcrs: Vec<ExpectedPcr>,
pub firmware_generation: u64,
pub policy_epoch: u64,
}
impl PlatformProfile {
#[must_use]
pub fn verify(
&self,
actual_pcrs: &crate::pcr::TypedPcrBank,
secure_boot: Option<&SecureBootEvidence>,
drift_mode: DriftPolicyMode,
upgrade_baseline: Option<&PcrBaseline>,
) -> PlatformVerificationReport {
let drift_reports = DriftDetectionEngine::detect_drift(self, actual_pcrs, upgrade_baseline);
let warnings = Vec::new();
let mut decision_reason = VerificationDecisionReason::Success;
let secure_boot_valid = if self.secure_boot_required {
if let Some(sb) = secure_boot {
if sb.state == SecureBootState::Enabled {
true
} else {
decision_reason = VerificationDecisionReason::SecureBootDisabled;
false
}
} else {
decision_reason = VerificationDecisionReason::SecureBootDisabled;
false
}
} else {
true
};
let mut measured_boot_valid = secure_boot_valid; let mut has_critical_drift = false;
let mut has_warning_drift = false;
let mut drift_detected = false;
for report in &drift_reports {
drift_detected = true;
match report.severity {
DriftSeverity::Critical => {
has_critical_drift = true;
}
DriftSeverity::Warning => {
has_warning_drift = true;
}
DriftSeverity::Informational => {}
}
}
if has_critical_drift
&& !DriftDetectionEngine::is_drift_permissible(drift_mode, DriftSeverity::Critical)
{
measured_boot_valid = false;
if decision_reason == VerificationDecisionReason::Success {
decision_reason = VerificationDecisionReason::CriticalDriftDetected;
}
}
if has_warning_drift
&& !DriftDetectionEngine::is_drift_permissible(drift_mode, DriftSeverity::Warning)
{
measured_boot_valid = false;
if decision_reason == VerificationDecisionReason::Success {
decision_reason = VerificationDecisionReason::CriticalDriftDetected;
}
}
let has_kernel_expected = self
.expected_pcrs
.iter()
.any(|m| m.semantic == PcrSemantic::Kernel);
if has_kernel_expected && actual_pcrs.get(PcrSemantic::Kernel).is_none() {
measured_boot_valid = false;
if decision_reason == VerificationDecisionReason::Success {
decision_reason = VerificationDecisionReason::MissingKernelMeasurement;
}
}
let profile_match = secure_boot_valid && measured_boot_valid;
PlatformVerificationReport {
profile_match,
secure_boot_valid,
measured_boot_valid,
drift_detected,
drift_reports,
warnings,
decision_reason,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[allow(clippy::struct_excessive_bools)]
pub struct PlatformVerificationReport {
pub profile_match: bool,
pub secure_boot_valid: bool,
pub measured_boot_valid: bool,
pub drift_detected: bool,
pub drift_reports: Vec<DriftReport>,
pub warnings: Vec<String>,
pub decision_reason: VerificationDecisionReason,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct RuntimeVerificationReport {
pub trusted: bool,
pub evaluations: Vec<crate::trust_domains::TrustEvaluation>,
pub warnings: Vec<String>,
}