Layr-Labs / Layr-Labs/ecloud

Runtime attestation with extraData fails on mainnet-alpha: TPM nonce mismatch (KMS likely pre-eigenx-kms#17)

Open
#169 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
7
Forks
3
PR merge metrics
No merged PRs in 30d

Description

TPM nonce mismatch on extraData attestations (mainnet-alpha) — KMS version skew

Summary

Per-action runtime attestation (extraData set) fails on mainnet-alpha with 401: TPM nonce mismatch; plain attestation (no extraData) succeeds on the same instance. Client SDK is correct against current main of all three repos involved. Root cause (medium-high confidence): the deployed KMS predates eigenx-kms PR#17 (commit 248f9d1d, 2026-04-23) — it accepts the extra_data request field but passes nil to VerifyTPM, so its expected nonce omits the extraData term the in-TEE launcher bakes into the quote.

Ask: confirm the KMS binary behind mainnet-alpha KMS_SERVER_URL is post-248f9d1d, and the launcher image on the affected TDX host is post-bbd228942d4a (go-tpm-tools PR#3). If both are current, next step is capturing a raw quote from this host on the extraData path.

Repro

  • App: proxy-arena 0x477F18816EdEAc206E0ecA970Bb33649a219e068, mainnet-alpha, Intel TDX, image built 2026-07-10 from public repo mmurrs/proxy-arena.
  • Client: @layr-labs/ecloud-sdk@1.0.0 (npm latest; byte-identical to 1.0.0-dev.8).
  • Call: new JwtProvider(new AttestClient({kmsServerURL, kmsPublicKey, audience})).getToken(extraData) with extraData = 64-byte SHA-512 Buffer.
  • Error (verbatim): KMS attest failed (401): {"error":"Attestation verification failed: TPM verification failed: TPM nonce mismatch: quote contains different nonce than expected"}
  • Control: same instance, same provider, getToken() without extraData → JWT mints fine (used for AI-gateway auth).

Root-cause trace (file:line, all current main unless noted)

Nonce formula — defined once, used by both sides:

  • Layr-Labs/go-tpm-tools internal/nonce/nonce.go:19-37:
    nonce = SHA256("WORKLOAD_ATTESTATION" || platformTag || SHA256(challenge) || SHA256(extraData)?) — extraData term included iff non-empty.

Prover (inside the TEE) — includes the term:

  • launcher/teeserver/tee_server.go:140-183/v1/bound_evidence decodes extra_data, forwards.
  • launcher/agent/agent.go:404ComputeTPMNonce(challenge, platformTag, opts.ExtraData).

Verifier (KMS) — where the skew bites:

  • Layr-Labs/eigenx-kms internal/handlers/attest.go:101-116 — decodes req.ExtraData, passes to verifier.
  • pkg/attestation/bound_attestation_evidence.go:64-69VerifyTPM(challenge, extraData). Pre-PR#17 this line was VerifyTPM(challenge, nil) — field accepted, term dropped → expected nonce ≠ quote nonce, exactly the observed error (go-tpm-tools sdk/attest/attestation.go:50-64 emits the string).

Client SDK — correct, nothing to fix:

  • ecloud-sdk dist/attest.js:22 — challenge = SHA256("COMPUTE_APP_JWT_REQUEST_RSA_KEY_V1" || 0x00 || rsa_pem); extraData deliberately not in the challenge (it binds via the quote nonce instead).
  • dist/attest.js:24-25, 60-62, 99-101 — same extraData Buffer to the socket and, base64, to /v1/bound_evidence and /auth/attest. Mirrors eigenx-kms pkg/types/server.go:74-80 and pkg/crypto/crypto.go:24,166-173.

Why the asymmetry proves the shape: with no extraData, both sides compute the term-less nonce → agree. With extraData, prover adds the term, a pre-PR#17 verifier doesn't → mismatch. No client-side change can fix this (the nonce is stamped by the launcher inside the TEE; SDK 1.0.0 is the newest published version).

Verification requested

  1. KMS binary commit behind mainnet-alpha KMS_SERVER_URLeigenx-kms@248f9d1d (2026-04-23)?
  2. Launcher/COS image on the affected host ≥ go-tpm-tools@bbd228942d4a (PR#3, 2026-02-25)?
  3. If both yes: capture one raw attestation from this host with extraData set and inspect the quote's qualifying data directly.

Machine-readable references

error         : 401 "TPM verification failed: TPM nonce mismatch: quote contains different nonce than expected"
app_id        : 0x477F18816EdEAc206E0ecA970Bb33649a219e068  (mainnet-alpha, Intel TDX)
client_sdk    : @layr-labs/ecloud-sdk@1.0.0  (== 1.0.0-dev.8)
client_paths  : dist/attest.js:22,24-25,60-62,99-101
nonce_formula : go-tpm-tools internal/nonce/nonce.go:19-37
prover_paths  : go-tpm-tools launcher/teeserver/tee_server.go:140-183 ; launcher/agent/agent.go:404
verifier_paths: eigenx-kms internal/handlers/attest.go:101-116 ; pkg/attestation/bound_attestation_evidence.go:64-69
error_source  : go-tpm-tools sdk/attest/attestation.go:50-64
fix_commits   : eigenx-kms 248f9d1d (PR#17, 2026-04-23) ; go-tpm-tools bbd228942d4a (PR#3, 2026-02-25)
works         : getToken() without extraData (same instance)
fails         : getToken(extraData) — any non-empty extraData

Separate, previously reported issue on the same app (not the same bug): all enclave→AI-gateway model calls return 502 with an HTML body while the same endpoints answer clean JSON 401s from outside — egress-proxy layer, also needs a platform look.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by checking the KMS binary behind mainnet-alpha KMS_SERVER_URL and the launcher image versions against the listed commits. Read go-tpm-tools/internal/nonce/nonce.go, launcher/agent/agent.go, and eigenx-kms/pkg/attestation/bound_attestation_evidence.go; done means confirming compatible versions or capturing a raw extraData quote for comparison.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, typescript
Domain
backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.