Skip to content

Commit ca0f577

Browse files
committed
fix: upgrade to V1 msgpack attestation when v2 events present
Root cause of a live RTMR3-mismatch observed during v2 CVM testing: `Attestation::into_versioned()` unconditionally wrapped as `VersionedAttestation::V0`, which SCALE-encodes the payload. But `RuntimeEvent::version` and `TdxEvent::version` carry `#[codec(skip)]` (added for V0 binary compat), so the `version` field is dropped on the wire. The KMS-side decoder then defaults each event to V1, replays with the V1 digest algorithm, and fails against the guest's V2-extended RTMR3. Fix: when any runtime event reports a non-V1 version, force V1 msgpack encoding (where `version` is a normal serde field and round-trips). Callers with only V1 events still get V0/SCALE, preserving wire-format compatibility with existing consumers. `from_bytes` already detects the encoding by leading byte (msgpack map prefix -> V1, else SCALE -> V0), so receivers don't need changes. Verified end-to-end: deployed a CVM with `event_log_version: 2`, boot now progresses past `get_app_key` without an RTMR3 mismatch; KMS replay sees `version=V2` and matches the quoted RTMR3.
1 parent 5b6b57d commit ca0f577

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

dstack-attest/src/attestation.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ pub const TDX_QUOTE_REPORT_DATA_RANGE: std::ops::Range<usize> = 568..632;
1212
use std::{borrow::Cow, time::SystemTime};
1313

1414
use anyhow::{anyhow, bail, Context, Result};
15-
#[cfg(feature = "quote")]
16-
use cc_eventlog::EventLogVersion;
17-
use cc_eventlog::{RuntimeEvent, TdxEvent};
15+
use cc_eventlog::{EventLogVersion, RuntimeEvent, TdxEvent};
1816
use dcap_qvl::{
1917
quote::{EnclaveReport, Quote, Report, TDReport10, TDReport15},
2018
verify::VerifiedReport as TdxVerifiedReport,
@@ -1143,9 +1141,24 @@ impl Attestation {
11431141
})
11441142
}
11451143

1146-
/// Wrap into a versioned attestation for encoding
1144+
/// Wrap into a versioned attestation for encoding.
1145+
///
1146+
/// When any runtime event uses a non-V1 event-log version, force the V1
1147+
/// msgpack wire format so the `version` field is preserved (SCALE
1148+
/// V0 skips it for legacy binary compat). Otherwise default to V0 for
1149+
/// backward compat with callers that expect the SCALE format.
11471150
pub fn into_versioned(self) -> VersionedAttestation {
1148-
VersionedAttestation::V0 { attestation: self }
1151+
let has_v2 = self
1152+
.runtime_events
1153+
.iter()
1154+
.any(|e| !matches!(e.version, EventLogVersion::V1));
1155+
if has_v2 {
1156+
VersionedAttestation::V1 {
1157+
attestation: self.into(),
1158+
}
1159+
} else {
1160+
VersionedAttestation::V0 { attestation: self }
1161+
}
11491162
}
11501163

11511164
/// Verify the quote

0 commit comments

Comments
 (0)