Skip to content

Validate the e2ee public key against TDX attestation #3

Description

@amiller

Validate the e2ee public key against TDX attestation

e2ee-proxy is the local proxy a client runs to get E2EE; this is a client-side
fix, no service change.

Gap in the attestation chain

The proxy fetches the instance's e2ee public key from /e2e/instances and
encrypts to it without validating it against the TDX attestation. A compromised
or dishonest control plane can return a substituted key, and the proxy will
encrypt the prompt to it.

The binding already exists server-side: the enclave commits
report_data = SHA256(nonce + e2e_pubkey) in its TD quote (confirmed live). The
proxy just never checks it.

Fix

Before encrypting, validate the key against the quote:

  1. pick a nonce, fetch the quote (/chutes/{id}/evidence?nonce=…);
  2. verify the DCAP signature;
  3. verify report_data == SHA256(nonce + e2e_pubkey);
  4. verify non-debug and a pinned-allowlist MRTD.

Drop any instance that fails; if none pass, fail closed (no fallback to the
unverified key). Same checks as the verify_chute.py reference in the docs.

Changes

  • lua/e2ee_attest.lua (new) — nonce → fetch quote → verify
  • lua/e2ee_discovery.lua — cache a key only after it verifies
  • lua/e2ee_crypto.lua + native/e2ee_proxy_api.{c,h} — DCAP signature check
  • Dockerfile / build_protected.sh — Intel DCAP library
  • tests/test_attestation.py — checks the binding against live evidence

Settings

  • CHUTES_GOLDEN_MRTD — accepted MRTD(s); required, from a source you trust
    (signed release / reproducible build), not the API.
  • CHUTES_DISABLE_ATTESTATION=true — explicit opt-out, like ALLOW_NON_CONFIDENTIAL.

Tested

Against live Qwen3-32B-TEE evidence, report_data matched
SHA256(nonce + pubkey) at the expected offset, with debug off and a consistent
MRTD across instances — so the binding/parsing is correct against production. The
DCAP signature path builds through the protected toolchain and still needs your
CI / a TEE host.

Scope

Stops key substitution. Does not address whether the serving code inside a
genuine enclave is measured — separate, server-side.


I have a working branch implementing this and can open a PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions