Skip to content

Commit 70720d5

Browse files
committed
fix(event-log): strip RTMR[0-2] payloads and document semantics
Strip boot-time event log payloads (RTMR 0-2) from GetQuote, Attest, and TdxQuote responses to reduce response size. Only digests are retained for verification purposes; runtime events (RTMR3) keep full payloads. Add documentation explaining event_log_verified semantics: RTMR3 events have both digest and payload verified, while RTMR 0-2 events only have digests verified through replay comparison.
1 parent 743dbc9 commit 70720d5

6 files changed

Lines changed: 39 additions & 16 deletions

File tree

dstack-attest/src/attestation.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,13 @@ impl<T> Attestation<T> {
339339
.map(|q| serde_json::to_vec(&q.event_log).unwrap_or_default())
340340
}
341341

342-
/// Get TDX event log string
342+
/// Get TDX event log string with RTMR[0-2] payloads stripped to reduce size.
343+
/// Only digests are kept for boot-time events; runtime events (RTMR3) retain full payload.
343344
pub fn get_tdx_event_log_string(&self) -> Option<String> {
344-
self.tdx_quote()
345-
.map(|q| serde_json::to_string(&q.event_log).unwrap_or_default())
345+
self.tdx_quote().map(|q| {
346+
let stripped: Vec<_> = q.event_log.iter().map(|e| e.stripped()).collect();
347+
serde_json::to_string(&stripped).unwrap_or_default()
348+
})
346349
}
347350

348351
pub fn get_td10_report(&self) -> Option<TDReport10> {

guest-agent/src/rpc_service.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,10 @@ impl TappdRpc for InternalRpcHandlerV0 {
561561
});
562562
}
563563
let event_log = read_event_log().context("Failed to decode event log")?;
564+
// Strip RTMR[0-2] payloads, keep only digests
565+
let stripped: Vec<_> = event_log.iter().map(|e| e.stripped()).collect();
564566
let event_log =
565-
serde_json::to_string(&event_log).context("Failed to serialize event log")?;
567+
serde_json::to_string(&stripped).context("Failed to serialize event log")?;
566568
let quote = tdx_attest::get_quote(&report_data).context("Failed to get quote")?;
567569
Ok(TdxQuoteResponse {
568570
quote,
@@ -657,12 +659,13 @@ impl WorkerRpc for ExternalRpcHandler {
657659
} else {
658660
let ed25519_quote = tdx_attest::get_quote(&ed25519_report_data)
659661
.context("Failed to get ed25519 quote")?;
660-
let event_log = serde_json::to_string(
661-
&read_event_log().context("Failed to read event log")?,
662-
)?;
662+
let raw_event_log = read_event_log().context("Failed to read event log")?;
663+
// Strip RTMR[0-2] payloads, keep only digests
664+
let stripped: Vec<_> = raw_event_log.iter().map(|e| e.stripped()).collect();
665+
let event_log = serde_json::to_string(&stripped)?;
663666
Ok(GetQuoteResponse {
664667
quote: ed25519_quote,
665-
event_log: event_log.clone(),
668+
event_log,
666669
report_data: ed25519_report_data.to_vec(),
667670
vm_config: self.state.inner.vm_config.clone(),
668671
})
@@ -688,9 +691,10 @@ impl WorkerRpc for ExternalRpcHandler {
688691
} else {
689692
let secp256k1_quote = tdx_attest::get_quote(&secp256k1_report_data)
690693
.context("Failed to get secp256k1 quote")?;
691-
let event_log = serde_json::to_string(
692-
&read_event_log().context("Failed to read event log")?,
693-
)?;
694+
let raw_event_log = read_event_log().context("Failed to read event log")?;
695+
// Strip RTMR[0-2] payloads, keep only digests
696+
let stripped: Vec<_> = raw_event_log.iter().map(|e| e.stripped()).collect();
697+
let event_log = serde_json::to_string(&stripped)?;
694698

695699
Ok(GetQuoteResponse {
696700
quote: secp256k1_quote,

sdk/curl/api-tappd.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,15 @@ curl --unix-socket /var/run/tappd.sock -X POST \
128128
```json
129129
{
130130
"quote": "<hex-encoded-quote>",
131-
"event_log": "quote generation log",
131+
"event_log": "<json-event-log>",
132132
"hash_algorithm": "sha512",
133133
"prefix": "app-data:"
134134
}
135135
```
136136

137+
**Note on Event Log:**
138+
The `event_log` field contains a JSON array of TDX event log entries. For RTMR 0-2 (boot-time measurements), only the digest is included; the payload is stripped to reduce response size. For RTMR3 (runtime measurements), both digest and payload are included.
139+
137140
### 4. Raw Quote
138141

139142
Generates a TDX quote with raw report data. This is a low-level API that should be used with caution.
@@ -166,10 +169,13 @@ curl --unix-socket /var/run/tappd.sock http://localhost/prpc/Tappd.RawQuote?repo
166169
```json
167170
{
168171
"quote": "<hex-encoded-quote>",
169-
"event_log": "quote generation log"
172+
"event_log": "<json-event-log>"
170173
}
171174
```
172175

176+
**Note on Event Log:**
177+
The `event_log` field contains a JSON array of TDX event log entries. For RTMR 0-2 (boot-time measurements), only the digest is included; the payload is stripped to reduce response size. For RTMR3 (runtime measurements), both digest and payload are included.
178+
173179
### 5. Info
174180

175181
Retrieves worker information.

sdk/curl/api.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,15 @@ curl --unix-socket /var/run/dstack.sock http://dstack/GetQuote?report_data=00000
132132
```json
133133
{
134134
"quote": "<hex-encoded-quote>",
135-
"event_log": "quote generation log",
135+
"event_log": "<json-event-log>",
136136
"report_data": "<hex-encoded-report-data>",
137137
"vm_config": "<json-vm-config-string>"
138138
}
139139
```
140140

141+
**Note on Event Log:**
142+
The `event_log` field contains a JSON array of TDX event log entries. For RTMR 0-2 (boot-time measurements), only the digest is included; the payload is stripped to reduce response size. For RTMR3 (runtime measurements), both digest and payload are included. To verify the event log, submit it along with the quote to the [verifier service](../../verifier/README.md).
143+
141144
### 4. Get Info
142145

143146
Retrieves worker information.

verifier/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ or
3131
"is_valid": true,
3232
"details": {
3333
"quote_verified": true,
34-
"event_log_verified": true,
34+
"event_log_verified": true, // See "Verification Process" for semantics
3535
"os_image_hash_verified": true,
3636
"report_data": "hex-encoded-64-byte-report-data",
3737
"tcb_status": "UpToDate",
@@ -178,7 +178,7 @@ $ curl -s -d @quote.json localhost:8080/verify | jq
178178
The verifier performs three main verification steps:
179179

180180
1. **Quote Verification**: Validates the TDX quote using dcap-qvl, checking the quote signature and TCB status
181-
2. **Event Log Verification**: Replays event logs to ensure RTMR values match and extracts app information
181+
2. **Event Log Verification**: Replays event logs to ensure RTMR values match and extracts app information. For RTMR3 (runtime measurements), both the digest and payload integrity are verified. For RTMR 0-2 (boot-time measurements), only the digests are verified; the payload content is not validated as dstack does not define semantics for these payloads
182182
3. **OS Image Hash Verification**:
183183
- Automatically downloads OS images if not cached locally
184184
- Uses dstack-mr to compute expected measurements

verifier/src/types.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ pub struct VerificationResponse {
2828
#[derive(Debug, Clone, Default, Serialize)]
2929
pub struct VerificationDetails {
3030
pub quote_verified: bool,
31+
/// Indicates that the event log was verified against the quote.
32+
///
33+
/// For RTMR3 (runtime measurements), both the digest and payload integrity are verified
34+
/// by replaying the event log and comparing against the quote. For RTMR 0-2 (boot-time
35+
/// measurements), only the digests are verified through replay comparison with the quote;
36+
/// the payload content is not validated. dstack does not define semantics for RTMR 0-2
37+
/// event log payloads.
3138
pub event_log_verified: bool,
3239
pub os_image_hash_verified: bool,
3340
pub report_data: Option<String>,

0 commit comments

Comments
 (0)