Key differences: SEV vs TDX
Quote detection
The system auto-detects the quote type when it arrives from the backend’s/cpu endpoint:
- Try hex-decoding the raw text. If it succeeds and the first 8 bytes match the TDX header (version=4, tee_type=0x81), it is TDX.
- Otherwise, treat as SEV-SNP (base64-encoded).
VerifyQuote() via IsTdxQuote() and determines which portal endpoint to use.
SEV attestation flow
The overallAttestBackend pipeline is identical for both TEE types. The differences are in the details of each step:
Step-by-step details
1. CPU quote fetch and portal verification
The backend returns a base64-encoded SEV-SNP attestation report from the attestation endpoint’s/cpu. The proxy-router detects this is not a TDX quote and routes it to the SEV-specific portal endpoint (/api/quote-parse-sev).
The portal returns the parsed report fields, including report_data and measurement. Unlike TDX, the SEV portal returns report_data as space-separated hex bytes (e.g., "3b 7e ff 4e ..."). The proxy-router normalizes this by stripping spaces before performing TLS and GPU binding checks.
2. TLS binding
Identical to TDX: the first 32 bytes ofreport_data must match a SHA-256 digest of the TLS certificate presented by the attestation endpoint (:21434, falling back to :29343) — either the SPKI digest (current SecretVMs) or the full-certificate digest (legacy). The normalization step (stripping spaces from SEV’s report_data format) is transparent to this check.
3. Workload verification
This is where SEV differs most significantly from TDX: TDX workload verification uses a simple RTMR3 extend chain:- Look up MRTD + RTMR0-2 in the TDX CSV registry to identify the VM build.
- Recalculate RTMR3 by SHA-384-extending
SHA-256(docker-compose.yaml)androotfs_data. - Compare the calculated RTMR3 against the quote’s RTMR3.
- Parse the base64 quote to extract
measurement(48 bytes at offset 0x090),family_id(16 bytes at 0x010), andimage_id(16 bytes at 0x020). - Parse
family_idto determine vm_type, template name, and vCPU count. - Look up matching entries in the SEV JSON registry.
- For each candidate entry, compute the expected GCTX launch digest by:
- Starting from the entry’s
ovmf_hash(SHA-384 of the OVMF firmware). - Processing each OVMF section (zero pages, secrets page, CPUID page, kernel hashes page).
- Building the kernel hashes page from
kernel_hash,initrd_hash, and the kernel cmdline (which includesdocker_compose_hash=SHA-256(compose)androotfs_hash). - Hashing one VMSA page per vCPU (BSP uses EIP=0xFFFFFFF0, APs use
sev_es_reset_eipfrom the registry).
- Starting from the entry’s
- Compare the computed digest against the quote’s
measurement.
/docker-compose response and its HTML-extracted form are tried as compose-hash candidates, so old (HTML-wrapping) and new (raw-serving) attest-rest versions both verify.
4. GPU binding
Identical to TDX: the second 32 bytes ofreport_data must match the GPU attestation nonce. The same space-stripping normalization applies.
5. NRAS verification
Identical to TDX — mandatory, and a failed or unreachable NRAS fails the attestation.SEV trust chain
The SEV trust chain is fundamentally different from TDX. Instead of separate measurement registers (MRTD, RTMR0-3), SEV uses a single cumulative launch digest that covers all measured components.SEV report fields used
GCTX launch digest computation
The GCTX digest is computed as a chain of SHA-384 hashes over 0x70-byte PAGE_INFO structures (AMD SNP spec Section 8.17.2):- Kernel command line (includes
docker_compose_hashandrootfs_hash) - Initrd
- Kernel
docker_compose_hash=<SHA-256 of docker-compose.yaml>.
SEV artifact registry
The SEV registry is a JSON array at sev.json. Each entry contains all the data needed to recompute the GCTX launch digest:Template sizes
Thefamily_id field encodes the VM template name, which maps to a vCPU count:
Configuration
Code structure
All files live inproxy-router/internal/attestation/: