Skip to content

Commit 212c2c6

Browse files
committed
attestation: carry report_data payload in TDX quote variant
1 parent 0de3b67 commit 212c2c6

5 files changed

Lines changed: 114 additions & 40 deletions

File tree

dstack-attest/src/attestation.rs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,13 @@ impl VersionedAttestation {
265265
}
266266
}
267267

268+
/// Get report_data payload if present.
269+
pub fn report_data_payload(&self) -> Option<&str> {
270+
match self {
271+
Self::V0 { attestation } => attestation.report_data_payload(),
272+
}
273+
}
274+
268275
/// Get app info
269276
pub fn decode_app_info(&self, boottime_mr: bool) -> Result<AppInfo> {
270277
match self {
@@ -274,7 +281,9 @@ impl VersionedAttestation {
274281

275282
/// Strip data for certificate embedding (e.g. keep RTMR3 event logs only).
276283
pub fn into_stripped(mut self) -> Self {
277-
let VersionedAttestation::V0 { attestation } = &mut self;
284+
let attestation = match &mut self {
285+
VersionedAttestation::V0 { attestation } => attestation,
286+
};
278287
if let Some(tdx_quote) = attestation.tdx_quote_mut() {
279288
tdx_quote.event_log = tdx_quote
280289
.event_log
@@ -290,6 +299,10 @@ impl VersionedAttestation {
290299
#[derive(Clone, Encode, Decode)]
291300
pub enum AttestationQuote {
292301
DstackTdx(TdxQuote),
302+
DstackTdxWithPayload {
303+
quote: TdxQuote,
304+
report_data_payload: String,
305+
},
293306
DstackGcpTdx,
294307
DstackNitroEnclave,
295308
}
@@ -298,6 +311,7 @@ impl AttestationQuote {
298311
pub fn mode(&self) -> AttestationMode {
299312
match self {
300313
AttestationQuote::DstackTdx { .. } => AttestationMode::DstackTdx,
314+
AttestationQuote::DstackTdxWithPayload { .. } => AttestationMode::DstackTdx,
301315
AttestationQuote::DstackGcpTdx => AttestationMode::DstackGcpTdx,
302316
AttestationQuote::DstackNitroEnclave => AttestationMode::DstackNitroEnclave,
303317
}
@@ -324,9 +338,20 @@ pub struct Attestation<R = ()> {
324338
}
325339

326340
impl<T> Attestation<T> {
341+
pub fn report_data_payload(&self) -> Option<&str> {
342+
match &self.quote {
343+
AttestationQuote::DstackTdxWithPayload {
344+
report_data_payload,
345+
..
346+
} => Some(report_data_payload),
347+
_ => None,
348+
}
349+
}
350+
327351
pub fn tdx_quote_mut(&mut self) -> Option<&mut TdxQuote> {
328352
match &mut self.quote {
329353
AttestationQuote::DstackTdx(quote) => Some(quote),
354+
AttestationQuote::DstackTdxWithPayload { quote, .. } => Some(quote),
330355
AttestationQuote::DstackGcpTdx => None,
331356
AttestationQuote::DstackNitroEnclave => None,
332357
}
@@ -335,6 +360,7 @@ impl<T> Attestation<T> {
335360
pub fn tdx_quote(&self) -> Option<&TdxQuote> {
336361
match &self.quote {
337362
AttestationQuote::DstackTdx(quote) => Some(quote),
363+
AttestationQuote::DstackTdxWithPayload { quote, .. } => Some(quote),
338364
AttestationQuote::DstackGcpTdx => None,
339365
AttestationQuote::DstackNitroEnclave => None,
340366
}
@@ -473,7 +499,8 @@ impl<T: GetDeviceId> Attestation<T> {
473499
.context("Failed to decode os image hash")?
474500
.os_image_hash;
475501
let mrs = match &self.quote {
476-
AttestationQuote::DstackTdx(q) => {
502+
AttestationQuote::DstackTdx(q)
503+
| AttestationQuote::DstackTdxWithPayload { quote: q, .. } => {
477504
self.decode_mr_tdx(boottime_mr, &mr_key_provider, q)?
478505
}
479506
AttestationQuote::DstackGcpTdx | AttestationQuote::DstackNitroEnclave => {
@@ -620,7 +647,7 @@ impl Attestation {
620647
}
621648
};
622649
let config = match &quote {
623-
AttestationQuote::DstackTdx(_) => {
650+
AttestationQuote::DstackTdx(_) | AttestationQuote::DstackTdxWithPayload { .. } => {
624651
read_vm_config().context("Failed to read VM config")?
625652
}
626653
AttestationQuote::DstackGcpTdx | AttestationQuote::DstackNitroEnclave => {
@@ -646,7 +673,8 @@ impl Attestation {
646673
_now: Option<SystemTime>,
647674
) -> Result<VerifiedAttestation> {
648675
let report = match &self.quote {
649-
AttestationQuote::DstackTdx(q) => {
676+
AttestationQuote::DstackTdx(q)
677+
| AttestationQuote::DstackTdxWithPayload { quote: q, .. } => {
650678
let report = self.verify_tdx(pccs_url, &q.quote).await?;
651679
DstackVerifiedReport::DstackTdx(report)
652680
}
@@ -669,6 +697,43 @@ impl Attestation {
669697
VersionedAttestation::V0 { attestation: self }
670698
}
671699

700+
/// Wrap into a versioned attestation carrying the report_data payload preimage
701+
/// inside a payload-aware TDX quote variant.
702+
pub fn into_versioned_with_report_data_payload(
703+
self,
704+
report_data_payload: String,
705+
) -> VersionedAttestation {
706+
let Attestation {
707+
quote,
708+
runtime_events,
709+
report_data,
710+
config,
711+
report,
712+
} = self;
713+
let quote = match quote {
714+
AttestationQuote::DstackTdx(quote) => AttestationQuote::DstackTdxWithPayload {
715+
quote,
716+
report_data_payload,
717+
},
718+
AttestationQuote::DstackTdxWithPayload { quote, .. } => {
719+
AttestationQuote::DstackTdxWithPayload {
720+
quote,
721+
report_data_payload,
722+
}
723+
}
724+
other => other,
725+
};
726+
VersionedAttestation::V0 {
727+
attestation: Attestation {
728+
quote,
729+
runtime_events,
730+
report_data,
731+
config,
732+
report,
733+
},
734+
}
735+
}
736+
672737
/// Verify the quote
673738
pub async fn verify_with_ra_pubkey(
674739
self,

guest-agent-simulator/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ mod tests {
173173
let report_data = [0x5a; 64];
174174
let response = platform.attest_response(report_data).unwrap();
175175
let patched = VersionedAttestation::from_scale(&response.attestation).unwrap();
176-
let VersionedAttestation::V0 { attestation } = patched;
176+
let attestation = patched.into_inner();
177177
assert_eq!(attestation.report_data, report_data);
178178
}
179179

@@ -189,7 +189,7 @@ mod tests {
189189
let report_data = [0x5a; 64];
190190
let response = platform.attest_response(report_data).unwrap();
191191
let patched = VersionedAttestation::from_scale(&response.attestation).unwrap();
192-
let VersionedAttestation::V0 { attestation } = patched;
192+
let attestation = patched.into_inner();
193193
assert_eq!(attestation.report_data, original);
194194
assert_ne!(attestation.report_data, report_data);
195195
}

guest-agent-simulator/src/simulator.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ pub fn simulated_quote_response(
2929
vm_config: &str,
3030
patch_report_data: bool,
3131
) -> Result<GetQuoteResponse> {
32-
let VersionedAttestation::V0 { attestation } =
33-
maybe_patch_report_data(attestation, report_data, patch_report_data, "quote");
34-
let mut attestation = attestation;
32+
let mut attestation =
33+
maybe_patch_report_data(attestation, report_data, patch_report_data, "quote").into_inner();
3534
let Some(quote) = attestation.tdx_quote_mut() else {
3635
return Err(anyhow::anyhow!("Quote not found"));
3736
};
@@ -89,19 +88,22 @@ fn maybe_patch_report_data(
8988
return attestation.clone();
9089
}
9190

92-
let VersionedAttestation::V0 { attestation } = attestation.clone();
93-
let mut attestation = attestation;
94-
attestation.report_data = report_data;
95-
if let Some(tdx_quote) = attestation.tdx_quote_mut() {
96-
if tdx_quote.quote.len() >= TDX_QUOTE_REPORT_DATA_RANGE.end {
97-
tdx_quote.quote[TDX_QUOTE_REPORT_DATA_RANGE].copy_from_slice(&report_data);
98-
} else {
99-
warn!(
100-
"TDX quote too short to patch report_data ({} < {})",
101-
tdx_quote.quote.len(),
102-
TDX_QUOTE_REPORT_DATA_RANGE.end
103-
);
91+
fn patch_inner_report_data(attestation: &mut Attestation, report_data: [u8; 64]) {
92+
attestation.report_data = report_data;
93+
if let Some(tdx_quote) = attestation.tdx_quote_mut() {
94+
if tdx_quote.quote.len() >= TDX_QUOTE_REPORT_DATA_RANGE.end {
95+
tdx_quote.quote[TDX_QUOTE_REPORT_DATA_RANGE].copy_from_slice(&report_data);
96+
} else {
97+
warn!(
98+
"TDX quote too short to patch report_data ({} < {})",
99+
tdx_quote.quote.len(),
100+
TDX_QUOTE_REPORT_DATA_RANGE.end
101+
);
102+
}
104103
}
105104
}
105+
106+
let VersionedAttestation::V0 { mut attestation } = attestation.clone();
107+
patch_inner_report_data(&mut attestation, report_data);
106108
VersionedAttestation::V0 { attestation }
107109
}

guest-agent/src/rpc_service.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -814,21 +814,29 @@ pNs85uhOZE8z2jr8Pg==
814814
attestation: &VersionedAttestation,
815815
report_data: [u8; 64],
816816
) -> VersionedAttestation {
817-
let ra_tls::attestation::VersionedAttestation::V0 { attestation } = attestation.clone();
818-
let mut attestation = attestation;
819-
attestation.report_data = report_data;
820-
if let Some(tdx_quote) = attestation.tdx_quote_mut() {
821-
if tdx_quote.quote.len() >= ra_tls::attestation::TDX_QUOTE_REPORT_DATA_RANGE.end {
822-
tdx_quote.quote[ra_tls::attestation::TDX_QUOTE_REPORT_DATA_RANGE]
823-
.copy_from_slice(&report_data);
824-
} else {
825-
tracing::warn!(
826-
"TDX quote too short to patch report_data ({} < {})",
827-
tdx_quote.quote.len(),
828-
ra_tls::attestation::TDX_QUOTE_REPORT_DATA_RANGE.end
829-
);
817+
fn patch_inner_report_data(
818+
attestation: &mut ra_tls::attestation::Attestation,
819+
report_data: [u8; 64],
820+
) {
821+
attestation.report_data = report_data;
822+
if let Some(tdx_quote) = attestation.tdx_quote_mut() {
823+
if tdx_quote.quote.len() >= ra_tls::attestation::TDX_QUOTE_REPORT_DATA_RANGE.end
824+
{
825+
tdx_quote.quote[ra_tls::attestation::TDX_QUOTE_REPORT_DATA_RANGE]
826+
.copy_from_slice(&report_data);
827+
} else {
828+
tracing::warn!(
829+
"TDX quote too short to patch report_data ({} < {})",
830+
tdx_quote.quote.len(),
831+
ra_tls::attestation::TDX_QUOTE_REPORT_DATA_RANGE.end
832+
);
833+
}
830834
}
831835
}
836+
837+
let ra_tls::attestation::VersionedAttestation::V0 { mut attestation } =
838+
attestation.clone();
839+
patch_inner_report_data(&mut attestation, report_data);
832840
ra_tls::attestation::VersionedAttestation::V0 { attestation }
833841
}
834842

@@ -848,9 +856,8 @@ pNs85uhOZE8z2jr8Pg==
848856
report_data: [u8; 64],
849857
vm_config: &str,
850858
) -> Result<GetQuoteResponse> {
851-
let ra_tls::attestation::VersionedAttestation::V0 { attestation } =
852-
patch_report_data(&self.attestation, report_data);
853-
let mut attestation = attestation;
859+
let mut attestation =
860+
patch_report_data(&self.attestation, report_data).into_inner();
854861
let Some(quote) = attestation.tdx_quote_mut() else {
855862
return Err(anyhow::anyhow!("Quote not found"));
856863
};

ra-tls/src/attestation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ pub fn from_ext_getter(
2727
) -> Result<Option<Attestation>> {
2828
// Try to detect attestation mode from certificate extension
2929
if let Some(attestation_bytes) = get_ext(oids::PHALA_RATLS_ATTESTATION)? {
30-
let VersionedAttestation::V0 { attestation } =
31-
VersionedAttestation::from_scale(&attestation_bytes)
32-
.context("Failed to decode attestation from cert extension")?;
30+
let attestation = VersionedAttestation::from_scale(&attestation_bytes)
31+
.context("Failed to decode attestation from cert extension")?
32+
.into_inner();
3333
return Ok(Some(attestation));
3434
}
3535
// Backward compatibility: if PHALA_RATLS_ATTESTATION

0 commit comments

Comments
 (0)