Livy Documentation

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 independently

Each 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-filled

The 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:

  1. The PCK certificate chain is valid and traces to Intel's root CA.
  2. The TCB (Trusted Computing Base) is current.
  3. 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:

FieldDescription
ita_tokenITA-signed JWT with MRTD, TCB status, and REPORTDATA binding
raw_quoteBase64-encoded ~8 KB DCAP quote
runtime_dataBase64-encoded 64-byte ReportData struct
verifier_nonce_valBase64-encoded ITA nonce value
verifier_nonce_iatBase64-encoded ITA nonce issued-at
tee_binary_hashSHA-256 hex of the TEE binary
nonceMonotonic 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 input and output bytes (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/certs

Verify the JWT signature, then check:

  • tdx_mrtd in the JWT claims matches the expected MRTD.
  • tcb_status is "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 nonceApplication nonce
Issued byIntel Trust AuthorityThe service
PreventsQuote theft across machines/sessionsProof reuse across requests
Verified byITA server-side + local verify_quoteApplication logic
Locationverifier_nonce_val / verifier_nonce_iatruntime_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:

  1. Download the published source at a specific commit.
  2. Build with the same toolchain and flags.
  3. Compute the MRTD from the resulting binary.
  4. Compare against tdx_mrtd in 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.