Trust Model
Mutual hardware attestation — neither side trusts without proof
Mutual Attestation Overview
Trust in the mero-tee system is bidirectional. Both the node and the KMS must prove they are running genuine, untampered code inside a TDX hardware enclave before any sensitive operation (key release) occurs. Neither party relies on network identity, TLS certificates, or operator trust alone.
Plane 1 — Node Verifies KMS
Before requesting a key, the node first verifies the KMS itself is running inside a genuine TDX enclave. This prevents a rogue server from impersonating the KMS and learning which keys nodes are requesting.
Request Attestation
The node sends POST /attest with a freshly generated nonce. The nonce ensures the attestation is fresh (not replayed).
KMS Produces Quote
KMS asks dstack to produce a TDX quote binding nonce || report_data to the quote’s user data field. dstack invokes the TDX guest driver to generate a hardware-signed quote.
Node Verifies Quote
The node receives the raw TDX quote and verifies: (a) the quote signature is valid, (b) the report_data contains the expected nonce binding, (c) MRTD and RTMR values match known-good KMS measurements.
Trust Established
If verification passes, the node trusts this KMS instance is the genuine mero-kms-phala running inside TDX. It proceeds to the key release protocol.
Plane 2 — KMS Verifies Node
The KMS never releases a key without verifying the requesting node. This uses a challenge-response protocol that binds the node’s identity (peerId) to a TDX attestation quote.
Challenge
Node sends POST /challenge { peerId }. KMS generates a cryptographic nonce, stores it with the peerId and an expiry, and returns { challengeId, nonce }.
Quote Generation
The node produces a TDX quote binding the nonce to its report_data. It also signs the nonce with its peer private key to prove identity.
Key Request
Node sends POST /get-key { challengeId, quote, signature }. The challenge is consumed (one-time use).
Signature Verification
KMS verifies the signature against the peerId’s public key. This proves the request originates from the entity that initiated the challenge.
Quote Verification
KMS parses the TDX quote, verifies its cryptographic signature, and checks report_data contains the expected nonce binding.
Policy Check
KMS evaluates the quote’s measurements (MRTD, RTMR0–3) and TCB status against the attestation policy. If any value is not in the allowlist, the request is rejected with 403 PolicyViolation.
Key Derivation
If all checks pass, KMS calls dstack to derive a deterministic key for the node’s namespace. The same inputs always produce the same key.
Policy Enforcement
The attestation policy defines which TDX measurements and TCB statuses are acceptable. It is fetched from GitHub releases on KMS startup and can be pinned by SHA-256 hash.
Policy Fields
allowed_mrtd: Vec<String>, // Allowed VM image measurements
allowed_rtmr0: Vec<String>, // Firmware measurement
allowed_rtmr1: Vec<String>, // OS kernel measurement
allowed_rtmr2: Vec<String>, // Application measurement
allowed_rtmr3: Vec<String>, // Runtime events (profile marker)
allowed_tcb_status: Vec<String>, // e.g. ["UpToDate", "SWHardeningNeeded"]
}
Measurement Registers
MRTD
Measures the initial VM image — the hash of the entire guest TD at launch. Changing any bit in the image changes MRTD. This pins the exact KMS or node binary.
RTMR0
Firmware measurement — extended by the TDVF (TDX Virtual Firmware) during early boot. Pins the firmware version.
RTMR1
OS kernel measurement — extended during kernel boot. Pins the kernel version and configuration.
RTMR2
Application measurement — extended when the application layer is loaded. Pins the merod or KMS application binary and initial config.
RTMR3 — Profile Cohort Separation
RTMR3 is special: it records runtime events that happen after boot. In mero-tee, each image profile writes a distinct event to RTMR3 during startup. This creates cryptographic separation between profiles.
The KMS attestation policy for production only includes the locked-read-only RTMR3 value in its allowlist. A debug node’s RTMR3 will not match, so the KMS rejects its key request with 403 PolicyViolation. This is enforced by hardware — there is no software path to forge an RTMR3 value.
Threat Mitigations
Rogue KMS
A fake KMS cannot produce a valid TDX quote with the expected MRTD. The node’s Plane 1 verification rejects it before revealing any peerId or key request.
Rogue Node
A node running outside TDX cannot produce a valid TDX quote. A tampered node’s MRTD/RTMR values differ from the policy. The KMS rejects the key request.
Replay Attack
Each challenge nonce is single-use and TTL-bound. A replayed /get-key request fails because the challengeId has been consumed. The /attest nonce prevents quote replay.
Profile Escalation
A debug node cannot impersonate a production node. RTMR3 values are hardware-measured and differ between profiles. The KMS policy rejects any RTMR3 not in the allowlist.
Man-in-the-Middle
The nonce binding in TDX quotes ties attestation to a specific session. Even if traffic is intercepted, the attacker cannot produce matching quotes.
Policy Tampering
The policy is fetched from a versioned GitHub release and optionally pinned by SHA-256 hash (MERO_KMS_POLICY_SHA256). Any modification is detected.