use borsh::{BorshDeserialize, BorshSerialize};
pub use rialo_tee_types::TeeType;
use serde::{Deserialize, Serialize};
pub use crate::crypto::{PublicKey, TeeUserData, TEE_USER_DATA_SIZE, X25519_KEY_SIZE};
#[derive(
Clone, Default, Eq, PartialEq, Serialize, Deserialize, BorshSerialize, BorshDeserialize,
)]
pub struct AttestationEvidence {
pub tee_type: TeeType,
pub evidence_data: Vec<u8>,
}
impl std::fmt::Debug for AttestationEvidence {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let truncated_data = if self.evidence_data.len() <= 16 {
format!("{:?}", self.evidence_data)
} else {
format!(
"{:?}... (truncated, total: {} bytes)",
&self.evidence_data[..16],
self.evidence_data.len()
)
};
f.debug_struct("AttestationEvidence")
.field("tee_type", &self.tee_type)
.field("evidence_data", &truncated_data)
.finish()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SevSnpEvidenceData {
pub report: Vec<u8>,
pub vek_certificate: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AzureSnpVtpmEvidence {
pub quote: Vec<u8>,
pub nonce: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AzureSnpHclEvidence {
pub report: Vec<u8>,
pub vek_certificate: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AzureSevSnpEvidenceData {
pub snp_evidence: AzureSnpHclEvidence,
pub vtpm_evidence: AzureSnpVtpmEvidence,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AwsNitroCoseEvidence {
pub report: Vec<u8>,
pub nonce: Vec<u8>,
pub time: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AwsSevSnpEvidenceData {
pub snp_evidence: SevSnpEvidenceData,
pub aws_nitro_cose_evidence: AwsNitroCoseEvidence,
}
#[derive(Debug, thiserror::Error)]
pub enum TeeEvidenceError {
#[error("Invalid evidence: {0}")]
InvalidEvidence(String),
}
impl TryFrom<&AttestationEvidence> for SevSnpEvidenceData {
type Error = TeeEvidenceError;
fn try_from(evidence: &AttestationEvidence) -> Result<Self, Self::Error> {
parse_evidence(evidence, &[TeeType::SevSnp])
}
}
impl TryFrom<&AttestationEvidence> for AwsSevSnpEvidenceData {
type Error = TeeEvidenceError;
fn try_from(evidence: &AttestationEvidence) -> Result<Self, Self::Error> {
parse_evidence(evidence, &[TeeType::AwsSevSnp])
}
}
impl TryFrom<&AttestationEvidence> for AzureSevSnpEvidenceData {
type Error = TeeEvidenceError;
fn try_from(evidence: &AttestationEvidence) -> Result<Self, Self::Error> {
parse_evidence(evidence, &[TeeType::AzureSevSnp])
}
}
pub fn parse_evidence<T>(
evidence: &AttestationEvidence,
expected_tee_types: &[TeeType],
) -> Result<T, TeeEvidenceError>
where
T: for<'de> Deserialize<'de>,
{
if !expected_tee_types.contains(&evidence.tee_type) {
return Err(TeeEvidenceError::InvalidEvidence(format!(
"Expected TEE types {:?}, got {:?}",
expected_tee_types, evidence.tee_type
)));
}
serde_json::from_slice(&evidence.evidence_data)
.map_err(|e| TeeEvidenceError::InvalidEvidence(format!("Failed to parse evidence: {e}")))
}