use {
super::{
IntoMeasurement,
Measurements,
MeasurementsCriteria,
local::Error,
ticket::TdxTicket,
},
crate::{
TicketValidator,
UniqueId,
discovery::PeerEntry,
primitives::{Expiration, InvalidTicket},
},
};
#[derive(Clone)]
pub struct Tdx {
baseline: MeasurementsCriteria,
any: Vec<MeasurementsCriteria>,
}
impl Tdx {
pub const CLASS: UniqueId = super::TICKET_CLASS;
#[must_use]
pub const fn baseline(baseline: MeasurementsCriteria) -> Self {
Self {
baseline,
any: Vec::new(),
}
}
#[must_use]
pub const fn empty() -> Self {
Self::baseline(MeasurementsCriteria::new())
}
#[must_use]
pub const fn new() -> Self {
Self::empty()
}
#[must_use]
pub fn require_mrtd(mut self, mrtd: impl IntoMeasurement) -> Self {
self.baseline = self.baseline.require_mrtd(mrtd.into_measurement());
self
}
#[must_use]
pub fn require_rtmr0(mut self, rtmr0: impl IntoMeasurement) -> Self {
self.baseline = self.baseline.require_rtmr0(rtmr0.into_measurement());
self
}
#[must_use]
pub fn require_rtmr1(mut self, rtmr1: impl IntoMeasurement) -> Self {
self.baseline = self.baseline.require_rtmr1(rtmr1.into_measurement());
self
}
#[must_use]
pub fn require_rtmr2(mut self, rtmr2: impl IntoMeasurement) -> Self {
self.baseline = self.baseline.require_rtmr2(rtmr2.into_measurement());
self
}
#[must_use]
pub fn require_rtmr3(mut self, rtmr3: impl IntoMeasurement) -> Self {
self.baseline = self.baseline.require_rtmr3(rtmr3.into_measurement());
self
}
pub fn from_local() -> Result<Self, Error> {
let local = Measurements::local()?;
Ok(Self::baseline(MeasurementsCriteria::from(&local)))
}
pub fn require_own_mrtd(self) -> Result<Self, Error> {
let local = Measurements::local()?;
Ok(self.require_mrtd(local.mrtd()))
}
pub fn require_own_rtmr0(self) -> Result<Self, Error> {
let local = Measurements::local()?;
Ok(self.require_rtmr0(local.rtmr0()))
}
pub fn require_own_rtmr1(self) -> Result<Self, Error> {
let local = Measurements::local()?;
Ok(self.require_rtmr1(local.rtmr1()))
}
pub fn require_own_rtmr2(self) -> Result<Self, Error> {
let local = Measurements::local()?;
Ok(self.require_rtmr2(local.rtmr2()))
}
pub fn require_own_rtmr3(self) -> Result<Self, Error> {
let local = Measurements::local()?;
Ok(self.require_rtmr3(local.rtmr3()))
}
#[must_use]
pub fn allow_variant(mut self, criteria: MeasurementsCriteria) -> Self {
self.any.push(criteria);
self
}
}
impl Default for Tdx {
fn default() -> Self {
Self::new()
}
}
impl TicketValidator for Tdx {
fn class(&self) -> UniqueId {
Self::CLASS
}
fn signature(&self) -> UniqueId {
self
.any
.iter()
.fold(self.class().derive(self.baseline.signature()), |s, c| {
s.derive(c.signature())
})
}
fn validate(
&self,
bytes: &[u8],
peer: &PeerEntry,
) -> Result<Expiration, InvalidTicket> {
let Ok(ticket) = TdxTicket::try_from(bytes) else {
return Err(InvalidTicket);
};
let measurements = ticket.measurements();
if !self.baseline.matches(&measurements) {
return Err(InvalidTicket);
}
if !self.any.is_empty()
&& !self.any.iter().any(|c| c.matches(&measurements))
{
return Err(InvalidTicket);
}
if ticket.peer_id() != peer.id() {
return Err(InvalidTicket);
}
if ticket.network_id() != peer.network_id() {
return Err(InvalidTicket);
}
if ticket.expiration().is_expired() {
return Err(InvalidTicket);
}
Ok(*ticket.expiration())
}
}