The proxy-router supports two TEE platforms for Phase 2 backend attestation: Intel TDX and AMD SEV-SNP. This page describes the SEV-SNP verification flow and highlights the differences from TDX. Both platforms share the same high-level attestation pipeline (CPU quote fetch, portal verification, TLS binding, workload verification, GPU binding), but differ in quote encoding, portal endpoints, report structure, registry format, and measurement computation.

Key differences: SEV vs TDX

Quote detection

The system auto-detects the quote type when it arrives from the backend’s /cpu endpoint:
  1. 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.
  2. Otherwise, treat as SEV-SNP (base64-encoded).
This detection happens in VerifyQuote() via IsTdxQuote() and determines which portal endpoint to use.

SEV attestation flow

The overall AttestBackend 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 of report_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) and rootfs_data.
  • Compare the calculated RTMR3 against the quote’s RTMR3.
SEV workload verification recomputes the entire GCTX launch digest:
  • Parse the base64 quote to extract measurement (48 bytes at offset 0x090), family_id (16 bytes at 0x010), and image_id (16 bytes at 0x020).
  • Parse family_id to 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:
    1. Starting from the entry’s ovmf_hash (SHA-384 of the OVMF firmware).
    2. Processing each OVMF section (zero pages, secrets page, CPUID page, kernel hashes page).
    3. Building the kernel hashes page from kernel_hash, initrd_hash, and the kernel cmdline (which includes docker_compose_hash=SHA-256(compose) and rootfs_hash).
    4. Hashing one VMSA page per vCPU (BSP uses EIP=0xFFFFFFF0, APs use sev_es_reset_eip from the registry).
  • Compare the computed digest against the quote’s measurement.
Both the raw /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 of report_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):
The kernel hashes page is a special OVMF section (type 0x10) that contains a GUID-indexed table with SHA-256 hashes of:
  • Kernel command line (includes docker_compose_hash and rootfs_hash)
  • Initrd
  • Kernel
This is how the docker-compose content gets measured into the SEV launch digest — through the kernel cmdline parameter 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

The family_id field encodes the VM template name, which maps to a vCPU count:

Configuration

Code structure

All files live in proxy-router/internal/attestation/: