Skip to Content
AI agents & assistants — machine-readable index at /llms.txt
Engineering BlogIntel TDX Remote Attestation Verifier Without Intel Trust Authority

Intel TDX Remote Attestation Verifier Without Intel Trust Authority

Date: September 7, 2026 · Author: Dmitrii Zatona 


TL;DR

  • Verifying a TDX quote is five decisions: the signature chain and TCB status, delegated to a verification library; and four the operator makes, on collateral, measurement policy, binding to a key and a nonce, and the credential issued (Section 1).
  • Intel’s DCAP library checks the chain to Intel’s root and returns a TCB status; which statuses and which advisories to accept is policy, not cryptography (Section 4).
  • Collateral changes on Intel’s schedule, can be mirrored and served offline, and needs a runbook for TCB recovery and a guard against rollback (Section 5).
  • REPORTDATA binds the certificate key and a verifier-issued nonce into the quote; on Azure the binding travels through the vTPM instead (Sections 6 and 7).
  • The manifest of approved measurements needs signed provenance, versioning and per-register coverage; the credential is a short-lived certificate from a CA hierarchy the relying parties can check (Sections 7 and 8).
  • Attestation does not prove that the code is correct, the platform safe, the host powerless, or the verifier trustworthy (Section 9).

Intel TDX remote attestation produces a signed statement about a virtual machine: which code it started with, which firmware and TDX module it runs on, and sixty-four bytes the VM chose to include. Most accounts of verification make it one operation, and Intel offers it as a service: Intel Trust Authority describes itself as “a neutral third-party verifier” that “collects evidence from the TEE or other attestable technology in the form of a quote” (Intel Trust Authority documentation ). Some deployments cannot use it: the quote must not leave the network, verification has to work without Intel’s endpoint, or the policy over what counts as an acceptable machine is the operator’s to write. In those cases the verifier is yours to build.

This article takes the verifier apart into five decisions. One is delegated to a verification library and is cryptographic. Four stay with the operator and are policy: where the collateral comes from, which measurements are acceptable, how the quote is bound to a key and a moment, and what to issue when the check passes. I run an attestation service converging on this design for Thunderwind, a sealed-execution platform on TDX; Section 10 describes what that service does, and nothing before it depends on it.

1. Five decisions a TDX attestation verifier makes, one library

A verifier receives a quote and has to answer, in order:

  1. Is the quote genuine: signed by a Quoting Enclave whose key chains to Intel’s root, on a platform whose TCB Intel still endorses?
  2. Where does the material for that check, the collateral, come from, and what happens when the network is not there?
  3. Are the measurements in the quote the ones an approved image should have?
  4. Is the quote about this request: does it bind the key being certified and a challenge the verifier issued, and is it recent?
  5. What does the attester get: a certificate, valid for how long, renewed on what evidence, and withdrawn by what mechanism?

Three names in that list come from Intel’s documentation. A TD, or trust domain, is the confidential virtual machine being attested. The Quoting Enclave is the enclave on the platform that holds the attestation key and signs quotes about a TD. The TCB, the trusted computing base, is the set of TDX module and firmware versions Intel currently endorses for a platform.

Decision 1 is what Intel’s DCAP Quote Verification Library does, and the library’s own documentation draws the line: “the QVL does not verify the data contained in the TD Quote Body,” and the verifier “is responsible to define what data needs to be checked to establish trust” (Intel TDX DCAP Quoting Library API , Section 2.3.2). Decisions 2 through 5 are that responsibility.

2. The parties to a remote attestation

RFC 9334, the IETF’s architecture for remote attestation, names the roles, and the names make the five decisions easier to place (RFC 9334 , Section 4.1). The Attester is the entity “whose Evidence must be appraised”: the TD and the agent inside it, with the quote as the Evidence. The Verifier “appraises the validity of Evidence about an Attester and produces Attestation Results.” The Endorser is “typically a manufacturer” whose endorsements “may help Verifiers appraise the authenticity of Evidence”: Intel, through the certificates and TCB data it signs. The Reference Value Provider supplies the values that “help Verifiers appraise Evidence to determine if acceptable known Claims” are present: the operator’s own manifest of approved measurements. The Relying Party “depends on the validity of information about an Attester”: whatever consumes the certificate the verifier issues.

Intel TDX remote attestation parties: attester, Intel as endorser, operator manifest as reference values, verifier, relying party

Two of the five roles are not the operator’s to design. Intel is the endorser whether the verifier is Intel’s or yours; that trust is not removed by running your own service, only relocated. The attester is the machine being checked. The verifier, the reference values, and the relying party’s policy are the operator’s, and a self-built verifier is the decision to own all three.

3. What is in a TDX quote

A TDX quote in the version-4 ECDSA format is a 48-byte header, a 584-byte body, and a variable-length signature section, little-endian throughout (Intel TDX DCAP Quoting Library API , Appendix A.3). The header carries the version, the attestation key type (ECDSA over P-256), a TEE type of 0x81 for TDX, and the Quoting Enclave vendor ID. The body is the TD quote body: the TD’s attestable properties, taken from the 1024-byte TDREPORT structure the TDX module produces (Intel TDX Module 1.5 ABI Specification , Section 4.7.2), and it is the part the verifier’s policy reads.

FieldSizeWhat it holdsWho sets it
TEE_TCB_SVN16 BTCB components of TDX, compared byte by byte with the TCB infoReported by the TDX module
MRSEAM48 BMeasurement of the TDX module itselfReported by the TDX module
TDATTRIBUTES, XFAM8 B eachTD attribute bits (including a debug bit that marks the TD untrusted) and the extended-features maskSet at TD creation
MRTD48 B”Measurement of the initial contents of the TD”The TDX module, as the host adds and measures the initial pages
MRCONFIGID, MROWNER, MROWNERCONFIG48 B eachSoftware-defined identifiers for configuration and ownerThe host, at TD creation
RTMR0RTMR348 B eachRuntime-extendable measurement registersFirmware and guest software, by extension
REPORTDATA64 B”The TD is free to provide 64 bytes of custom data”The guest, per report

The signature section holds the ECDSA signature over header and body by the attestation key, the attestation key itself, and the certification data that lets a verifier check that key: the Quoting Enclave’s report, signed by the platform’s Provisioning Certification Key, and the PCK certificate chain up to Intel’s root (Appendix A.3.8–A.3.9). The QVL supports one certification-data type, the concatenated PCK chain (Section 4.1.1).

Three of these fields carry most of a verifier’s policy.

MRTD is fixed before the TD runs. The TDX Module’s ABI specifies the operations that build it: adding a private page extends the measurement with the page’s address, TDH.MR.EXTEND “updates the MRTD measurement register in the TDCS with the measurement of the indicated chunk,” 256 bytes at a time, and TDH.MR.FINALIZE “completes the measurement of the initial TD contents and marks the TD as finalized” (Intel TDX Module 1.5 ABI Specification , Sections 6.3.20, 6.3.44, 6.3.45). By the virtual-firmware convention it identifies the firmware image the TD was launched with, and because the page addresses are part of it, its placement in guest memory as well.

RTMR0RTMR3 are extended after launch. The guest calls TDG.MR.RTMR.EXTEND, which “extends one of the RTMR measurement registers in TDCS with the provided extension data” by hashing the current value and the new data together with SHA-384 (Section 6.4.4). What each register holds is convention, not architecture. Intel’s virtual-firmware guide assigns RTMR0 to firmware configuration, RTMR1 to the loaded OS loader, RTMR2 to “the OS component, such as OS kernel, initrd, and application,” and reserves RTMR3 (Intel TDX Virtual Firmware Design Guide , Section 8.1); the DCAP library’s own text says only that RTMR0 and RTMR1 “are updated by the TD virtual firmware/BIOS” and RTMR2 and RTMR3 “are measurements generated by the OS and runtime code” (Section 2.3.2). A verifier that checks RTMRs is checking whatever the firmware and guest software in that particular image chose to extend, and the manifest has to be built from that image’s actual boot chain.

REPORTDATA is the guest’s sixty-four bytes. The library documentation says it can hold “a nonce, a public key, or a hash of a larger block,” and that “the signature of a TD Quote covers the REPORTDATA field” (Appendix A.3.2). It is the only field the guest fills directly with data of its own choosing, where the RTMRs it can only extend, and Section 6 is about what to put in it.

4. What Intel’s DCAP quote verification library decides

The DCAP Quoting Library API lists what a verifier does with the certification data, and Intel’s library performs “at least the following checks” (Section 2.2): the PCK certificate’s signature chain and its absence from the CRL; the signature chains of the collateral itself, the TCB info and QE identity chains; whether any collateral certificate is on a CRL; the Quoting Enclave’s report signature and the attestation-key hash inside it against the PCK certificate; the Quoting Enclave’s own measurements; the quote’s signature with the attestation key; and “evaluate the TDX TCB information contained in the TD Quote” against Intel’s TCB info for that platform.

The output is a status, not a verdict. Intel’s reference enumeration has nine values (Intel SGX ECDSA Quote Library Reference , Appendix A), and TDX adds two:

  • OK, the quote “passed and is at the latest TCB level”.
  • CONFIG_NEEDED.
  • OUT_OF_DATE, where “the Quote is good but the TCB level of the platform is out of date”.
  • OUT_OF_DATE_CONFIG_NEEDED.
  • SW_HARDENING_NEEDED.
  • CONFIG_AND_SW_HARDENING_NEEDED.
  • INVALID_SIGNATURE, terminal.
  • REVOKED, terminal.
  • UNSPECIFIED, terminal.
  • TD_RELAUNCH_ADVISED and TD_RELAUNCH_ADVISED_CONFIG_NEEDED, TDX-specific, for a TD “launched prior to the application of new TDX TCB components” (DCAP Quoting Library API, Section 4.1.1).

Alongside the status comes supplemental data, which “will allow the caller to implement a different quote verification policy” (Section 3.6.2): the TCB level’s date, the earliest expiry among the collateral, and a comma-separated list of Intel security-advisory identifiers that apply to the platform’s current TCB.

Every non-terminal result other than OK is a valid quote with a condition attached: a configuration Intel wants applied, software hardening Intel wants in the enclave, or a TCB level that is out of date. Which of those statuses to accept, and whether a specific advisory identifier is disqualifying, is decision 1’s policy half, and it belongs to the operator. Intel’s guidance for the strictest posture is to accept only OK, with a trusted current time supplied and no collateral expired (DCAP Quoting Library API, Section 4.1.1); a fleet that has not applied a firmware update will fail that policy on the day the TCB info changes, so the choice is between a stricter check and a longer maintenance window, and it has to be made before the first quote arrives.

In Rust, the dcap-qvl crate reimplements the signature-chain and TCB-level checks in pure Rust, parses version-4 and version-5 quotes, and exposes the policy half as a type: QuotePolicy::strict(now) accepts only UpToDate, and each further status is added explicitly (dcap-qvl , version 0.6.3). It is not Intel’s library, and a verifier built on it makes a different supply-chain statement from one built on Intel’s signed Quote Verification Enclave; it also has no relaunch-advised result and rejects Revoked before any policy runs. The example in Section 6 uses it.

5. TDX attestation collateral, and running without the network

The library’s checks need material that is not in the quote: Intel’s root CA CRL, the PCK CRL, the TCB info for the platform’s family, and the Quoting Enclave identity, the last three each with an issuer chain. The DCAP API calls this the collateral, notes that the PCK chain “is in the Quote thus there is no need to provide it in the collateral,” and defines a structure with those members (DCAP Quoting Library API, sgx_ql_qve_collateral_t). Intel serves it from the Provisioning Certification Service, and the TCB info carries a nextUpdate field, “date and time by which next TCB information will be issued” (Intel PCS API ).

Two properties of the collateral shape a self-hosted verifier.

It changes on Intel’s schedule, not yours. When Intel discloses a platform issue it publishes new TCB info, and a quote that was OK yesterday is OUT_OF_DATE today with no change on the machine. The PCS API exposes this as a monotonically increasing tcbEvaluationDataNumber, “changed when Intel updates the content,” and distinguishes an early track, “commonly the day of public disclosure,” from a standard track “commonly 12 months after public disclosure.” A verifier’s policy has to say which track it follows, and the operating sequence for a recovery has to exist before the first one: patch the hosts, refresh the hosts’ PCK certificates for the new security versions, then advance the verifier’s collateral. Between disclosure and the last patched host the verifier either holds the accepted collateral generation, by pinning the tcbEvaluationDataNumber it accepts, or accepts OUT_OF_DATE under a grace period with a deadline; dcap-qvl exposes both as policy fields. TDs that were running before the update report the old security version until they are relaunched, which is what the relaunch-advised results of Section 4 report, and the policy has to say how long that is tolerated.

It can be cached and served offline. Intel’s Provisioning Certificate Caching Service, the PCCS, exists “to enable SGX attestation run-time workloads without a dependence on the Intel services,” fills either lazily on first miss or ahead of time, and has an OFFLINE mode in which an administrator fetches collateral from Intel and loads it by hand (PCCS Design Guide , Sections 2, 5, 7, 8.3). The same guide is explicit that on a TCB recovery the cache “needs to be updated with the new PCK Certs” and “all verification collaterals” (Section 8.2). For a sealed deployment, one whose verifier has no route to the internet, this is the mechanism: a mirror that is refreshed from outside on a schedule shorter than the collateral’s validity, with an alarm on mirror age well before nextUpdate, because dcap-qvl refuses expired TCB info and QE identity unconditionally, and a missed refresh combined with short-lived certificates ends renewals for the TDs whose collateral has expired.

Two more facts about the collateral decide whether the mechanism holds up. PCK certificates for a platform are issued by Intel’s Provisioning Certification Service after the platform is registered, a step that talks to Intel (PCS API, registration section), and after a TCB recovery the cache “needs to be updated with the new PCK Certs” (PCCS Design Guide, Section 8.2), so a recovery is a per-platform certificate event and not only a collateral refresh. And nextUpdate bounds staleness, not rollback: whoever operates the sync path into a sealed network can load collateral that predates a recovery and is still inside its window, so the verifier pins the tcbEvaluationDataNumber it has already accepted and refuses to go below it, and mirror imports are signed by the party that fetched them.

In dcap-qvl the collateral is a value, QuoteCollateralV3, with the CRLs, TCB info, QE identity and their issuer chains as fields; it can be fetched from a PCCS with CollateralClient::with_default_http(url)?.fetch(&quote).await or deserialized from a file the operator maintains, and the verifier is handed the value either way. The verification call takes the collateral as a value and never fetches it, which is the property an offline design needs. The crate’s documentation also notes that for quotes carrying an encrypted platform identifier, the PPID, instead of the PCK chain, the chain is fetched from the verifier’s PCCS instead; that moves the network dependency from every host to the verifier, and is the shape a sealed deployment tends toward.

6. Binding the quote to a key and a moment

A genuine quote with approved measurements is still a quote about a machine. Two things make it a quote about this request.

The first is the key. A verifier that issues a certificate has to know that the key in the certificate request belongs to the TD that produced the quote, and REPORTDATA is the only field the guest fills with data of its own choosing, per report. Putting a hash of the request’s public key there, and checking it, is what ties the two together; without it, a quote from any approved TD can accompany a certificate request from anywhere.

The second is time. RFC 9334 describes the mechanism: “an unpredictable nonce is sent by the appraising entity and the nonce is then signed” into the evidence, so that “the appraising entity knows that the Claims were signed after the nonce was generated” (Section 10.2). The nonce has to come from the verifier, be unpredictable, and be used once. A timestamp written by the attester’s own clock, or a nonce the attester chose, gives the verifier an assertion, not evidence, and a window based on it is a window against replay of the same attester’s own quotes, not against a quote captured and resubmitted by someone else. The nonce service is its own small design: a store shared by every verifier replica, or a stateless nonce carrying a MAC plus a replay set; consumption on first use, atomically; a lifetime sized to how long quote generation takes on the platform; and a cap on outstanding nonces per source, because the endpoint allocates state for anonymous callers.

The two bindings share the sixty-four bytes. One arrangement is REPORTDATA[0..32] = SHA-256(tag || public_key || nonce), with the remaining bytes zero, where the tag keeps this hash from being confused with any other use of the field. The example below verifies a quote in that arrangement against the dcap-qvl crate. It compiles; it has not been exercised against hardware here.

use dcap_qvl::verify::QuoteVerifier; use dcap_qvl::{QuoteClaims, QuoteCollateralV3, QuotePolicy, TcbStatus}; use sha2::{Digest, Sha256}; /// The reference values for one approved TD image. Who signs this, and how it /// changes when the image is rebuilt, is the operator's decision (Section 7). struct Manifest { mr_td: [u8; 48], rt_mr: [[u8; 48]; 4], /// Advisory identifiers this operator has reviewed and accepts. Anything /// else in the platform's advisory list is disqualifying. reviewed_advisories: Vec<String>, } fn verify_td( raw_quote: &[u8], collateral: &QuoteCollateralV3, // fetched live, mirrored, or loaded from a file now_secs: u64, manifest: &Manifest, csr_public_key_der: &[u8], nonce: &[u8; 32], ) -> Result<QuoteClaims, String> { // Decision 1, delegated to the verification library (dcap-qvl here, // reimplementing the QVL's checks): signature chain to the Intel root, // QE identity, TCB level against the collateral, collateral validity. // The policy says which TCB statuses this verifier accepts. The three // PCK flags describe the platform (SMT enabled, dynamic platform, cached // keys); `strict` rejects a platform that reports any of them, so accepting // them is a stated choice for the fleet you run. let policy = QuotePolicy::strict(now_secs) .allow_status(TcbStatus::SWHardeningNeeded) .allow_smt(true) .allow_dynamic_platform(true) .allow_cached_keys(true); let claims = QuoteVerifier::new_prod() .verify_with_policy(raw_quote, collateral, now_secs, &policy) .map_err(|e| format!("quote rejected by verification library: {e:?}"))?; // Still decision 1: a status is a list of advisories. Fail closed on any // advisory the operator has not reviewed. for id in &claims.tcb.advisory_ids { if !manifest.reviewed_advisories.iter().any(|r| r == id) { return Err(format!("unreviewed advisory {id}")); } } // Decision 3, the operator's: measurements against the manifest. let td = claims.report.as_td10().ok_or("not a TDX report")?; if td.mr_td != manifest.mr_td { return Err("MRTD is not an approved image".into()); } for (i, rt) in [td.rt_mr0, td.rt_mr1, td.rt_mr2, td.rt_mr3].iter().enumerate() { if *rt != manifest.rt_mr[i] { return Err(format!("RTMR{i} does not match the manifest")); } } // Decision 4, the operator's: the quote must bind the key being certified // and the nonce this verifier issued for this request. let mut h = Sha256::new(); h.update(b"attestation-binding-v1"); h.update(csr_public_key_der); h.update(nonce); let expected: [u8; 32] = h.finalize().into(); if td.report_data[..32] != expected || td.report_data[32..] != [0u8; 32] { return Err("REPORTDATA does not bind this key and nonce".into()); } Ok(claims) }

The example compares all four RTMRs; a real manifest says which registers it covers (Section 7), and the loop follows that. Three things the example leaves to the surrounding service. Issuing the nonce and consuming it. Checking the certificate request’s own signature, so that the public key in it is one the requester holds, and constraining its algorithm and size. And ordering the work so that attacker-supplied bytes cost little before they cost much: size caps on the quote and the request, a nonce lookup and the request’s self-signature first, the library call, which carries the certificate chains, the ECDSA verifications and the TCB policy, second, and the measurement and binding comparisons after it. The library call also runs before any measurement is read, so that the comparisons operate on a body whose signature has been verified.

On Azure this arrangement does not apply, because the guest does not write REPORTDATA there; Section 7 describes what the field holds and where the binding goes instead.

7. Measurement policy

Decision 3 needs a source of truth for what an approved image measures to, and that source is the reference-value provider of Section 2. In practice it is a manifest: for each image the deployment allows, its MRTD, the RTMR values its boot chain produces, its TDATTRIBUTES and XFAM, and the registers it does not cover. Four properties decide whether the manifest constrains anything.

Provenance

The values come from a build, and the build has to be the thing that publishes them. A manifest that an operator can edit by hand is a manifest whose measurements mean “whatever was approved,” and the approval is the weak point. Two signatures are needed, and they say different things: the build system’s, which says this build produced these values, and a release approver’s, which says these values are approved for this application in production. The verifier pins both signing keys in its own configuration, with a rotation plan, checks both signatures before trusting any value in the manifest, and refuses a manifest whose version number is lower than one it has already accepted, so that an older, vulnerable image cannot be re-approved by republishing its manifest. Who can add a measurement, and how that act is logged, is part of the policy.

Versioning

Images are rebuilt, and for a period two versions run at once. A manifest with one active measurement per application forces a choice between rejecting the old version the moment the new one is published and delaying the new version until every instance has been replaced. A manifest that lists several accepted measurements with validity windows lets the fleet roll, and its expiry of the old value is the only mechanism by which a running TD on the old image loses its ability to renew.

Which registers

MRTD alone identifies the firmware image, and it depends on the host’s firmware build and page layout, which a cloud customer does not control. Whether the guest OS and application are in the measurement depends on whether the boot chain in that image extends the RTMRs, and on what it extends them with; Section 3 gives Intel’s two stated conventions. The values are reproducible only if the image is built for it: RTMR0 covers the firmware configuration and the launch-time data the host passes in, so it changes with the VM’s shape and the host’s firmware version; the registers the loader and OS extend change with anything they measure that varies per boot, unless the image fixes it. A manifest is therefore keyed by image, VM shape and host stack version; its values are predicted from the build and reconciled against one real boot, never copied from a running VM on first sight; and it states, per register, whether it is covered and why. A verifier that checks only MRTD is trusting the firmware to have loaded the right kernel; a verifier that checks RTMR2 is trusting the firmware and loader to have measured it; and a verifier that receives a quote whose covered registers it cannot compare refuses it.

Attributes

The TD attributes include a debug bit, and the DCAP documentation states that if any bit in that group is set “the TD is untrusted” (Appendix A.3.4). dcap-qvl rejects a debug TD and a service TD unless the caller opts in with allow_debug and allow_service_td; the manifest pins the whole TDATTRIBUTES and XFAM values rather than one bit, because two images with the same MRTD and different extended-features masks are different execution environments. MROWNER and MRCONFIGID are written by the host at TD creation and are tags the host can set to anything; comparing them is not evidence about the guest, and their one use in a verifier is to let the host bind a TD to an identity the verifier already expects. The TDX module’s version is what the TCB check covers, through TEE_TCB_SVN; MRSEAM itself is not compared by the verification library, and pinning it is a manifest decision like any other.

On Azure the measurement path runs through a different chain. Azure’s confidential VMs on TDX sit behind a Microsoft-built guest paravisor, the component in which the virtual TPM runs, and the guest-attestation design puts “the measurement of Microsoft-built guest paravisor where the vTPM runs” in the hardware report, with UEFI also covered by the hardware report and the guest OS covered by “TPM Quote (PCRs)” rather than by RTMRs (Azure guest attestation design ). The vTPM’s attestation public key “is captured in the hardware report.” A verifier that wants the guest OS measurement therefore checks two things: the TD report, for the hardware-report measurements, and a TPM quote signed by that key, for the PCRs. The raw TD report is readable from a reserved NV index, and the TDX payload there is 1024 bytes.

REPORTDATA on Azure is not the guest’s: the design page states that “the report_data field of the report captures the hash of the Runtime Claims,” which contain the vTPM’s public keys and a 64-byte user-data value read from a second reserved NV index. The freshness binding of Section 6 therefore travels through the TPM: the TPM quote’s own challenge field, extraData, “external information supplied by caller” in TPM 2.0’s attestation structure (TCG TPM 2.0 Library, Part 2 , Section 10.12.12), carries the verifier’s nonce. The key binding has no direct equivalent: the guest-chosen data that reaches the hardware report is the 64-byte user-data value the runtime claims include, and binding the certificate key through that value, or through the vTPM’s own key hierarchy, is the deployment’s design, not something Azure’s documentation specifies. Azure’s FAQ states that a VM created with the NonPersistedTPM security type lets the customer “bring your own disk encryption, key management, and attestation solution,” and scopes that option to the Intel TDX public preview (Azure confidential VM FAQ ). The manifest for such a deployment has two parts: the hardware-report measurements, which Microsoft controls, and the PCR values the customer’s own image produces.

8. Issuing the credential

Decision 5 is what the attester walks away with. A verifier that returns “valid” and nothing else forces every relying party to repeat the whole check. The alternative is to issue what RFC 9334 calls Attestation Results in a form ordinary infrastructure already knows how to check. The RFC prescribes no format; an X.509 certificate, signed by the verifier’s own CA, for the key the quote bound, is one choice, and the rest of this section assumes it.

Four decisions follow. Each is an ordinary certificate-authority decision, and each turns on something attestation supplies.

Lifetime. The certificate is a statement that a quote with approved measurements existed at issuance. It says nothing about the TD an hour later. A short lifetime, hours rather than months, bounds how long a TD can keep a credential after its image is no longer approved or its platform’s TCB status changes, and makes renewal the point where policy is re-applied. Revocation lists are the alternative and are harder to distribute to relying parties inside a sealed network; non-renewal is the cheaper mechanism, and it works only if the lifetime is short. The lifetime also couples the fleet to the verifier’s availability: a lifetime of several times the longest verifier or mirror outage the operator will tolerate, renewal attempted at half to two thirds of the lifetime with jittered retries, and applications that reload a certificate without a restart are what keep a short lifetime from becoming an outage. The kill switch is removing a manifest entry; exposure after that is bounded by the lifetime.

Renewal. A renewing TD presents a new quote and the same key, or a new key; either way it repeats decisions 1 through 4 in full. What renewal may skip is the initial enrollment step, the one-time proof that this application is allowed to exist at all, and the verifier has to decide what evidence stands in for it: an unexpired earlier certificate, a record of the previous attestation bound to the key that REPORTDATA proved, or nothing. That record is where stale trust accumulates. A renewal path that consults such a record without checking that the record itself has expired will renew a TD indefinitely on the strength of one old attestation. Enrollment itself has a threat model that is usually left unstated: anything delivered to a TD before its first attestation, through cloud-init, a configuration disk or user data, passes through the host and is readable by the party the TEE is meant to exclude. The authorization to exist is the measurement’s mapping to an application in the manifest; a token delivered before attestation prevents squatting and accounting drift and nothing more, unless it is bound to the TD through an identifier the verifier compares or delivered only after a first attestation.

Names, and what the certificate says. The subject and names identify the application, and the verifier derives them from the manifest’s mapping of measurement to application; the certificate request is proof of possession of the key and nothing else, because a quote proves an image, not a name, and a TD running application A’s image must not obtain a certificate for application B by asking. Whether the certificate also carries the measurement, the TCB status at issuance, or a hash of the quote is a choice between a certificate any TLS stack can consume and one a relying party can appraise further. A non-critical extension under the operator’s own object identifier can carry any of them; a certificate shown to untrusted peers that carries measurements or advisory identifiers discloses fleet composition and patch state, so measurements belong in certificates shown only to the operator’s own relying parties.

The CA itself. The verifier’s signing key is the root of trust for every relying party, and it is a more attractive target than any single TD. Leaf certificates are issued by an online intermediate with a short validity, name constraints and an extended-key-usage restriction, under a root that stays offline; rotation is an overlap, two roots trusted for a window, planned before the first certificate; and where the intermediate’s key lives, an HSM or a TD attested by the same design, is a decision the operator states. Every issuance leaves evidence in an append-only audit trail: the quote, the collateral generation and CRL numbers, the manifest version, the TCB status and advisory list, the policy version, the nonce, and the certificate, retained for longer than the lifetime plus the time an investigation takes, so that a certificate can be re-verified a week later. The root’s public key reaches relying parties out of band; a relying party that fetches the verifier’s root from the verifier’s own endpoint has removed Intel from the trust path and put an HTTP server in its place. And the attester pins the verifier: the host is the network, so a TD that does not carry the verifier’s CA in its measured image can be handed a certificate by an impostor, and every later call the TD makes uses the issued certificate over mutual TLS.

9. What attestation does not prove

  • That the code is correct. A measurement identifies an image. It does not say the image has no vulnerability. A TD whose approved image contains an exploitable service still attests successfully, and the verifier has no ground on which to refuse it.
  • That the platform is safe. A TCB status of OUT_OF_DATE or SW_HARDENING_NEEDED is a fact about Intel’s current view of the platform, and a verifier that accepts it has decided to run on a platform Intel has published an advisory about. The status is not a risk assessment; it is an input to one.
  • That the host is powerless. TDX removes the host’s ability to read and modify TD memory. The host still invokes the TDX module’s functions that create, run and tear down a TD (Intel TDX Module 1.5 ABI Specification , Section 6.3), so it controls scheduling, I/O, and whether the TD runs at all, and it can decline to produce a quote.
  • That side channels are closed. What the hardware’s threat model covers, and what Intel’s advisories say it does not, is the boundary of the guarantee. A verifier repeats that boundary; it does not widen it.
  • That Intel is out of the loop. Every check in decision 1 terminates at an Intel root certificate and Intel’s TCB data. Running your own verifier changes who applies the policy, not who endorses the hardware; and when Intel’s root rotates, or the Quoting Enclave’s identity changes with an update, the verifier’s pinned root and its collateral change with them.
  • That the verifier is trustworthy. The relying party gets no evidence about the verifier. Its CA key, its manifest source and its mirror sit on infrastructure the same operator runs, often on the same hosts; where the verifier runs and who attests it is a design statement the relying party has to be given.
  • That the collateral is current. A verifier reading a stale mirror reports OK for a platform Intel has since moved to OUT_OF_DATE. nextUpdate bounds how long that can last; detecting a recovery inside the window needs a refresh keyed to Intel’s announcements and the tcbEvaluationDataNumber.
  • That the verifier’s clock is right. Every expiry check and every nonce lifetime depends on now, and in a sealed network the time source is the operator’s, or the host’s.
  • What the guest does after the quote. Measurements describe the boot chain. Software loaded after the last RTMR extension, or a binary replaced on disk after attestation, is outside the quote unless the guest measures it and the manifest covers it.

10. One assembly

The Intel TDX remote attestation service I run for Thunderwind is one instance of the five decisions, and this is what it does today. It is a Rust service that receives a certificate request and a TDX quote, fetches the application’s manifest from a control plane where the build pipeline published it, verifies the quote with the dcap-qvl crate against collateral from a PCCS mirror or from a file, compares the measurement to the manifest, and issues a 24-hour certificate from its own root. Renewal repeats the verification and skips the one-time enrollment token when a record of a previous attestation exists; trust ends with the certificate’s expiry, and there is no revocation list. On Azure the service verifies the TPM quote chain: the attestation key from the paravisor’s report, the TPM quote’s signature and nonce, and the PCR that carries the guest measurement.


If you are putting a workload on TDX and the verifier, its policy, its collateral and its certificate authority have to be built rather than bought, that is contract work I take on.

Last updated on