Trust Model
How Livy services generate attestations and how anyone can verify them independently.
Overview
Livy's trust model is built on one guarantee: you never have to trust Livy. Every claim a Livy service makes about a computation is backed by a cryptographic attestation signed by Intel TDX hardware. Anyone — with no special access, no Livy account, and no Livy infrastructure — can verify that:
- A specific binary ran (not some other version).
- Specific inputs were processed.
- Specific outputs were produced.
- The computation happened inside a genuine, unmodified Intel TDX enclave.
This is possible because the attestation's trust root is the Intel CPU itself, not Livy's servers.
The Trust Chain
Intel CPU hardware
└── signs TD report (CPU-only HMAC key)
└── Quoting Enclave converts to DCAP quote (PCK cert chain)
└── Intel Trust Authority verifies + issues JWT
└── ITA JWT + raw quote → anyone can verify independentlyEach layer is verifiable from the one above it. The chain terminates at Intel's Platform Certification Service (PCS), whose root certificates are publicly available.
How a Service Generates an Attestation
Step 1 — Build a structured REPORTDATA payload
Every Livy attestation starts with a 64-byte ReportData struct embedded in the TDX quote's REPORTDATA field. This is the commitment that binds the attestation to specific inputs and outputs.
runtime_data (64 bytes):
Bytes Size Field Description
───── ──── ───── ───────────
00..32 32 payload_hash SHA-256( SHA-256(input) ‖ SHA-256(output) )
32..40 8 build_id SHA-256(TEE binary)[0..8] — identifies the binary
40..44 4 version_code u32 BE — schema version
44..48 4 build_number u32 BE — CI build counter
48..56 8 nonce u64 BE — monotonic counter (replay protection)
56..64 8 reserved Zero-filledThe payload_hash is the core commitment:
payload_hash = SHA-256( SHA-256(input) ‖ SHA-256(output) )This construction is deterministic. Given the original input and output bytes, anyone can recompute it from scratch.
Step 2 — Fetch an ITA verifier nonce
Before generating the quote, the service calls Intel Trust Authority (ITA) to get a fresh verifier nonce:
GET https://portal.trustauthority.intel.com/appraisal/v2/nonce
Headers: x-api-key: <key>
Response: { "val": "<base64>", "iat": "<base64>", "signature": "<base64>" }This nonce is a time-bounded token that ITA issues before the quote. It prevents an attacker from capturing a valid quote from one machine and replaying it against ITA on behalf of a different session.
Step 3 — Generate the DCAP quote
The service calls the TDX hardware via the Linux TSM configfs interface. The CPU produces an ~8 KB DCAP quote where:
REPORTDATA (bytes [568..632] of the quote) = SHA-512( nonce.val ‖ nonce.iat ‖ runtime_data )The quote is signed by the Quoting Enclave using a PCK (Platform Certification Key) whose certificate chain is rooted in Intel's root CA. This signature is unforgeable outside the genuine Intel TDX hardware.
Step 4 — Submit to Intel Trust Authority for verification
The service sends the quote, runtime_data, and verifier nonce to ITA:
POST https://portal.trustauthority.intel.com/appraisal/v2/attest
Body: {
"tdx": {
"quote": "<base64>",
"runtime_data": "<base64>",
"verifier_nonce": { "val": "<base64>", "iat": "<base64>" }
}
}ITA verifies server-side:
- The PCK certificate chain is valid and traces to Intel's root CA.
- The TCB (Trusted Computing Base) is current.
SHA-512(nonce.val ‖ nonce.iat ‖ runtime_data) == REPORTDATA in quote.
If all checks pass, ITA returns a signed JWT (ita_token) containing the MRTD (binary measurement), TCB status, and a hash of the runtime_data.
Step 5 — Publish the proof
The service stores and exposes the following fields so any party can verify independently:
| Field | Description |
|---|---|
ita_token | ITA-signed JWT with MRTD, TCB status, and REPORTDATA binding |
raw_quote | Base64-encoded ~8 KB DCAP quote |
runtime_data | Base64-encoded 64-byte ReportData struct |
verifier_nonce_val | Base64-encoded ITA nonce value |
verifier_nonce_iat | Base64-encoded ITA nonce issued-at |
tee_binary_hash | SHA-256 hex of the TEE binary |
nonce | Monotonic u64 counter for request-level replay protection |
How Anyone Can Verify
Verification requires no Livy infrastructure, no ITA account, and no TDX hardware. All checks are cryptographic operations over public data.
What you need
- The original
inputandoutputbytes (or their SHA-256 hashes). - The proof fields listed above.
- The expected MRTD (published by Livy from deterministic builds — anyone who builds the same binary gets the same value).
Step-by-step verification
1. Verify the REPORTDATA binding
Extract bytes [568..632] from the raw DCAP quote. This is the 64-byte REPORTDATA.
Recompute:
expected_reportdata = SHA-512( nonce_val ‖ nonce_iat ‖ runtime_data )Assert expected_reportdata == quote[568..632]. This confirms the quote is bound to the exact runtime_data you have, and that the ITA nonce matches.
2. Verify the payload hash
Parse the 64-byte runtime_data as a ReportData struct (see wire layout above). Read payload_hash from bytes [0..32].
Recompute:
expected_payload_hash = SHA-256( SHA-256(input) ‖ SHA-256(output) )Assert expected_payload_hash == runtime_data[0..32]. This confirms the quote is bound to the exact input and output bytes you have.
3. Verify the binary identity
Read build_id from runtime_data[32..40]. Recompute from the published binary hash:
build_id = SHA-256(tee_binary_bytes)[0..8]Assert they match. This confirms which version of the server binary processed the request. If you can reproduce the build deterministically, you can verify the binary independently from source.
4. Check replay protection
Read nonce from runtime_data[48..56] (u64 big-endian). Assert it matches the expected monotonic counter for this request. A proof with a nonce you have already seen is a replay.
5. (Optional) Verify the ITA JWT
The ita_token is a JWT signed by Intel Trust Authority. Fetch ITA's public keys:
GET https://portal.trustauthority.intel.com/certsVerify the JWT signature, then check:
tdx_mrtdin the JWT claims matches the expected MRTD.tcb_statusis"UpToDate"(or acceptable for your policy).
This step requires network access to Intel's endpoint but is optional — steps 1–4 above fully verify the data binding without it.
Using livy-tee for verification
If you are writing a Rust verifier, livy-tee provides a verify_quote function that runs steps 1–4 in one call:
use livy_tee::{verify_quote, payload_hash_for};
let ok = verify_quote(
&proof.raw_quote,
&proof.runtime_data,
&proof.verifier_nonce_val,
&proof.verifier_nonce_iat,
input,
output,
)?;
assert!(ok);No TDX hardware or network connection is required to call verify_quote.
Replay Protection
Two distinct nonces protect against two distinct replay attacks.
ITA verifier nonce — quote-level replay
Prevents: capturing a valid quote from any TDX machine and replaying it to ITA on behalf of a different session.
ITA issues this nonce before the quote is generated, and verifies server-side that it is embedded in the quote's REPORTDATA. A quote from a different ITA session will have a different REPORTDATA and be rejected.
Application nonce — request-level replay
Prevents: saving a valid proof for request #1 and presenting it as the response to request #100.
The service maintains a monotonically increasing counter persisted in its database. Each request increments the counter; the current value is embedded in runtime_data[48..56]. Verifiers check that the nonce matches the expected value for that specific request slot.
| ITA verifier nonce | Application nonce | |
|---|---|---|
| Issued by | Intel Trust Authority | The service |
| Prevents | Quote theft across machines/sessions | Proof reuse across requests |
| Verified by | ITA server-side + local verify_quote | Application logic |
| Location | verifier_nonce_val / verifier_nonce_iat | runtime_data[48..56] |
Binary Identity and MRTD
The MRTD (Measurement of Trust Domain) is a 48-byte hash computed by the TDX hardware at TD launch time. It covers all code and configuration loaded into the TD before execution starts.
Because Livy uses deterministic, reproducible builds, anyone can:
- Download the published source at a specific commit.
- Build with the same toolchain and flags.
- Compute the MRTD from the resulting binary.
- Compare against
tdx_mrtdin the ITA JWT.
If the values match, the binary that ran is exactly the binary built from that source. A single bit change in the code produces a different MRTD.
The build_id in the ReportData struct (SHA-256(binary)[0..8]) provides a shorter, directly embeddable fingerprint for use in automated verification pipelines that do not need the full MRTD comparison.
What Livy Cannot Forge
Because the trust root is Intel CPU hardware:
- Livy cannot fake a quote. The PCK private key never leaves the CPU. The Quoting Enclave's signature is hardware-backed and verifiable against Intel's public root CA.
- Livy cannot alter the REPORTDATA. The REPORTDATA is set inside the TD before the Quoting Enclave signs it. An altered REPORTDATA would produce a signature mismatch.
- Livy cannot swap binaries. The MRTD is computed at TD launch. Running a different binary produces a different MRTD, which any verifier comparing against published values will detect.
- Livy cannot replay old proofs. The ITA nonce and application nonce together ensure each proof is bound to a specific ITA session and a specific request slot.
What Livy can do is selectively withhold proofs or decline to process a request. The trust model does not guarantee liveness — only that published proofs are authentic.