diff --git a/dstack/verifier/README.md b/dstack/verifier/README.md index 8529dc1f6..4572e4daf 100644 --- a/dstack/verifier/README.md +++ b/dstack/verifier/README.md @@ -35,7 +35,7 @@ against the returned evidence. "is_valid": true, "details": { "quote_verified": true, - "event_log_verified": true, // See "Verification Process" for semantics + "event_log_verified": true, // app identity decoded; see "Verification Process" "os_image_hash_verified": true, "acpi_tables_verified": true, // true only when TDX ACPI table contents are verified "os_image_is_dev": false, // true=dev image, false=prod, null=unknown/N/A @@ -237,7 +237,7 @@ $ curl -s -d @quote.json localhost:8080/verify | jq The verifier performs the following verification steps: 1. **Quote Verification**: Validates the platform quote using the platform verifier: DCAP for TDX, AMD SNP report verification for SEV-SNP, NSM for Nitro Enclaves, and AWS NitroTPM attestation-document verification for EC2 NitroTPM. -2. **Event Log Verification**: Replays event logs to ensure RTMR/PCR values match and extracts app information. For RTMR3 and AWS NitroTPM PCR14 launch measurements, both the digest and payload integrity are verified. For TDX 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. +2. **Event Log Verification**: Decodes app information (`app_id`, `compose_hash`, ...) from evidence bound to the quote and reports it as `event_log_verified`. On dstack TDX, GCP TDX and AWS NitroTPM it is read from the runtime event log, whose digests and payloads step 1 already replayed against the quoted register (RTMR3, plus TPM PCR14 on GCP; PCR14 on NitroTPM), so a replay mismatch fails quote verification. SEV-SNP has no runtime event log and takes it from `mr_config`, bound through HOST_DATA; Nitro Enclaves derive it from the PCRs. The RTMR 0-2 entries of a TDX event log are not replayed: on dstack TDX those registers are verified in step 3 against measurements recomputed from the OS image, which does not depend on the host's event log, and dstack defines no semantics for their payloads. 3. **OS Image Hash Verification**: - Treats `vm_config` and any attached measurement material as untrusted inputs until they are bound to the hardware quote - For the full-image TDX path, downloads or loads the image identified by `os_image_hash`, checks the image checksum manifest, uses dstack-mr to compute expected MRTD/RTMR0-2, and compares them against the verified measurements from the quote diff --git a/dstack/verifier/src/types.rs b/dstack/verifier/src/types.rs index d9d71442b..5d37d9e15 100644 --- a/dstack/verifier/src/types.rs +++ b/dstack/verifier/src/types.rs @@ -79,13 +79,25 @@ impl PolicyBootInfo { #[derive(Debug, Clone, Default, Serialize)] pub struct VerificationDetails { pub quote_verified: bool, - /// Indicates that the event log was verified against the quote. + /// Indicates that the app identity was decoded from evidence bound to the + /// quote. /// - /// For RTMR3 (runtime measurements), both the digest and payload integrity are verified - /// by replaying the event log and comparing against the quote. For RTMR 0-2 (boot-time - /// measurements), only the digests are verified through replay comparison with the quote; - /// the payload content is not validated. dstack does not define semantics for RTMR 0-2 - /// event log payloads. + /// On dstack TDX, GCP TDX and AWS NitroTPM that evidence is the runtime + /// event log, already replayed during quote verification against RTMR3 + /// (plus TPM PCR14 on GCP) or PCR14 on NitroTPM, so a replay mismatch fails + /// `quote_verified` rather than this flag. Digests and payloads are both + /// covered, because `app_id`, `compose_hash` and the rest are read out of + /// the payloads. SEV-SNP has no runtime event log and takes the identity + /// from `mr_config`, bound through HOST_DATA; Nitro Enclave derives it from + /// the PCRs. + /// + /// It says nothing about the RTMR 0-2 entries a TDX event log carries; + /// nothing replays them. On dstack TDX those registers are verified by + /// comparing the quoted values against measurements recomputed from the OS + /// image (see `os_image_hash_verified`), which does not depend on the + /// host's event log. The TDX lite path only reads the three named ACPI + /// digests from it and requires them to match the recomputed ones; dstack + /// defines no semantics for the other payloads. pub event_log_verified: bool, pub os_image_hash_verified: bool, /// Indicates that TDX ACPI table contents were verified.