#[cfg(feature = "cpu-tee")]
use crate::PqcError;
use crate::Result;
use serde::{Deserialize, Serialize};
pub trait AttestationVerifier: Send + Sync {
fn verify_cpu_attestation(&self, quote: &[u8], expected_measurement: &[u8]) -> Result<bool>;
fn verify_gpu_attestation(&self, nras_token: &[u8]) -> Result<GpuAttestationResult>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GpuAttestationResult {
pub valid: bool,
pub device_id: String,
pub gpu_model: String,
pub cc_enabled: bool,
pub tee_io_enabled: bool,
pub mig_config: Option<MigConfiguration>,
pub driver_version: String,
pub vbios_version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigConfiguration {
pub enabled: bool,
pub instance_id: String,
pub profile: String,
pub memory_size_gb: u32,
pub compute_units: u32,
}
pub struct MockAttestationVerifier;
impl AttestationVerifier for MockAttestationVerifier {
fn verify_cpu_attestation(&self, _quote: &[u8], _expected_measurement: &[u8]) -> Result<bool> {
Ok(true)
}
fn verify_gpu_attestation(&self, _nras_token: &[u8]) -> Result<GpuAttestationResult> {
Ok(GpuAttestationResult {
valid: true,
device_id: "GPU-MOCK-001".to_string(),
gpu_model: "NVIDIA H100".to_string(),
cc_enabled: true,
tee_io_enabled: false,
mig_config: None,
driver_version: "535.154.05".to_string(),
vbios_version: "96.00.89.00.01".to_string(),
})
}
}
#[cfg(feature = "cpu-tee")]
pub mod sev_snp {
use super::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SevSnpReport {
pub version: u32,
pub guest_svn: u32,
pub policy: u64,
pub family_id: [u8; 16],
pub image_id: [u8; 16],
pub vmpl: u32,
pub signature_algo: u32,
pub platform_version: u64,
pub platform_info: u64,
pub author_key_en: u32,
pub report_data: [u8; 64],
pub measurement: [u8; 48],
pub host_data: [u8; 32],
pub id_key_digest: [u8; 48],
pub author_key_digest: [u8; 48],
pub report_id: [u8; 32],
pub report_id_ma: [u8; 32],
pub reported_tcb: u64,
pub chip_id: [u8; 64],
pub signature: [u8; 512],
}
impl SevSnpReport {
pub fn parse(data: &[u8]) -> Result<Self> {
if data.len() < 1184 {
return Err(PqcError::AttestationError(
"Invalid SEV-SNP report size".into(),
));
}
Ok(Self {
version: u32::from_le_bytes([data[0], data[1], data[2], data[3]]),
guest_svn: u32::from_le_bytes([data[4], data[5], data[6], data[7]]),
policy: u64::from_le_bytes(data[8..16].try_into().unwrap()),
family_id: data[16..32].try_into().unwrap(),
image_id: data[32..48].try_into().unwrap(),
vmpl: u32::from_le_bytes([data[48], data[49], data[50], data[51]]),
signature_algo: u32::from_le_bytes([data[52], data[53], data[54], data[55]]),
platform_version: u64::from_le_bytes(data[56..64].try_into().unwrap()),
platform_info: u64::from_le_bytes(data[64..72].try_into().unwrap()),
author_key_en: u32::from_le_bytes([data[72], data[73], data[74], data[75]]),
report_data: data[76..140].try_into().unwrap(),
measurement: data[140..188].try_into().unwrap(),
host_data: data[188..220].try_into().unwrap(),
id_key_digest: data[220..268].try_into().unwrap(),
author_key_digest: data[268..316].try_into().unwrap(),
report_id: data[316..348].try_into().unwrap(),
report_id_ma: data[348..380].try_into().unwrap(),
reported_tcb: u64::from_le_bytes(data[380..388].try_into().unwrap()),
chip_id: data[388..452].try_into().unwrap(),
signature: data[672..1184].try_into().unwrap(),
})
}
}
}
#[cfg(feature = "cpu-tee")]
pub mod tdx {
use super::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TdxQuote {
pub version: u16,
pub attestation_key_type: u16,
pub tee_type: u32,
pub reserved: [u8; 4],
pub vendor_id: [u8; 16],
pub user_data: [u8; 20],
pub report_data: [u8; 64],
}
impl TdxQuote {
pub fn parse(data: &[u8]) -> Result<Self> {
if data.len() < 584 {
return Err(PqcError::AttestationError("Invalid TDX quote size".into()));
}
Ok(Self {
version: u16::from_le_bytes([data[0], data[1]]),
attestation_key_type: u16::from_le_bytes([data[2], data[3]]),
tee_type: u32::from_le_bytes([data[4], data[5], data[6], data[7]]),
reserved: data[8..12].try_into().unwrap(),
vendor_id: data[12..28].try_into().unwrap(),
user_data: data[28..48].try_into().unwrap(),
report_data: data[48..112].try_into().unwrap(),
})
}
}
}