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.

merod Node TDX Confidential VM Has peer key pair Produces TDX quote on demand mero-kms-phala TDX Confidential VM + dstack Holds attestation policy Produces TDX quote via dstack Plane 1: Node verifies KMS POST /attest → verify quote → check report_data Plane 2: KMS verifies Node challenge → get-key → sig verify → quote verify → policy check TDX Hardware Root CPU-level tamper evidence
Node → KMS verification
KMS → Node verification
Hardware trust root

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.

1

Request Attestation

The node sends POST /attest with a freshly generated nonce. The nonce ensures the attestation is fresh (not replayed).

2

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.

3

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.

4

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.

1

Challenge

Node sends POST /challenge { peerId }. KMS generates a cryptographic nonce, stores it with the peerId and an expiry, and returns { challengeId, nonce }.

2

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.

3

Key Request

Node sends POST /get-key { challengeId, quote, signature }. The challenge is consumed (one-time use).

4

Signature Verification

KMS verifies the signature against the peerId’s public key. This proves the request originates from the entity that initiated the challenge.

5

Quote Verification

KMS parses the TDX quote, verifies its cryptographic signature, and checks report_data contains the expected nonce binding.

6

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.

7

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

struct AttestationPolicy {
  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.

debug
RTMR3 event A
debug-ro
RTMR3 event B
locked-ro
RTMR3 event C

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.