Intel TDX Overview
Intel Trust Domain Extensions (TDX) is a confidential computing technology that creates isolated virtual machine environments called Trust Domains (TDs). TDX provides hardware-enforced memory encryption and integrity protection for entire VMs.
Key TDX Components
Trust Domain (TD) : An isolated VM with encrypted memory
TD Quote : A cryptographically signed attestation statement
RTMR (Runtime Measurement Register) : Registers that store measurement hashes (similar to TPM PCRs)
MRTD (Measurement of Trust Domain) : Hash of the initial TD configuration
DCAP (Data Center Attestation Primitives) : Intel’s attestation verification library
Quote Generation Process
Umbra’s attestation service generates TDX quotes using the dstack SDK:
1. Report Data Computation
The report_data field binds the attestation to a specific TLS session:
def compute_report_data ( nonce_hex : str , ekm_hex : str ) -> bytes :
"""
Compute report_data from nonce and EKM using SHA512.
This implements TLS channel binding for attestation.
The nonce provides freshness and the EKM binds to the specific TLS session.
Clients will verify that the same nonce and EKM were used.
Args:
nonce_hex: 64-character hex string (32 bytes)
ekm_hex: 64-character hex string (32 bytes)
Returns:
64-byte SHA512 hash suitable for TDX report_data
"""
if len (nonce_hex) != 64 :
raise ValueError ( "nonce_hex must be exactly 64 hex characters (32 bytes)" )
if len (ekm_hex) != 64 :
raise ValueError ( "ekm_hex must be exactly 64 hex characters (32 bytes)" )
nonce = bytes .fromhex(nonce_hex)
ekm = bytes .fromhex(ekm_hex)
return hashlib.sha512(nonce + ekm).digest()
Security Properties:
Freshness : Client-generated nonce prevents replay attacks
Session Binding : EKM cryptographically binds the quote to the TLS session
Integrity : SHA512 ensures collision resistance
2. Quote Request Flow
The attestation service endpoint handles quote generation:
@app.post ( "/tdx_quote" , response_model = QuoteResponse)
async def post_tdx_quote ( request : Request, data : QuoteRequest):
"""
Get TDX quote with report data.
"""
# Extract and validate EKM header (see EKM Channel Binding)
ekm_header = request.headers.get( HEADER_TLS_EKM_CHANNEL_BINDING )
if not ekm_header:
raise HTTPException( status_code = 400 , detail = "Missing EKM header" )
# Validate HMAC signature
try :
ekm_hex = validate_and_extract_ekm(ekm_header, EKM_SHARED_SECRET )
except ValueError as e:
logger.error( f "EKM validation failed: { e } " )
raise HTTPException( status_code = 403 , detail = "Invalid EKM header signature" )
# Compute report_data
report_data = compute_report_data(data.nonce_hex, ekm_hex)
# Get quote and TCB info concurrently
quote, info_response = await asyncio.gather(
dstack_client.get_quote(report_data),
dstack_client.info()
)
tcb_info = info_response.tcb_info
return QuoteResponse(
success = True ,
quote = quote,
tcb_info = tcb_info,
timestamp = str ( int (time.time())),
quote_type = "tdx" ,
)
The service uses asyncio.gather to fetch the quote and TCB info concurrently for better performance.
3. Quote Structure
A TDX quote contains:
TDX Quote (1KB - 4KB):
├── Header
│ ├── Version (2 bytes)
│ ├── Attestation Key Type (2 bytes)
│ └── TEE Type (4 bytes) = TDX (0x00000081)
├── Report Body
│ ├── CPUSVN (16 bytes) - CPU security version
│ ├── MISC_SELECT (4 bytes)
│ ├── ATTRIBUTES (16 bytes)
│ ├── MRENCLAVE (32 bytes) - Enclave measurement (N/A for TDX)
│ ├── MRSIGNER (32 bytes) - Signer measurement (N/A for TDX)
│ ├── MRTD (48 bytes) - Trust Domain measurement
│ ├── RTMR[0-3] (48 bytes each) - Runtime measurements
│ │ ├── RTMR0: Bootloader + kernel measurement
│ │ ├── RTMR1: OS filesystem measurement
│ │ ├── RTMR2: Application measurement (docker-compose hash)
│ │ └── RTMR3: Reserved
│ └── REPORTDATA (64 bytes) - SHA512(nonce + EKM)
├── Signature (ECDSA P-256/P-384)
└── Certification Data
├── PCK Certificate Chain
└── TCB Info
DCAP Verification Process
Umbra performs client-side verification using Intel’s DCAP QVL (Quote Verification Library) compiled to WebAssembly.
Verification Steps
Quote Structure Validation
Parse quote header and body
Verify quote version and TEE type
Validate signature algorithm
Certificate Chain Verification
Extract PCK (Provisioning Certification Key) certificate
Verify certificate chain up to Intel root CA
Check certificate revocation status
Quote Signature Verification
Extract ECDSA signature from quote
Verify signature using PCK public key
Ensure signature covers quote body and report data
TCB Status Evaluation
Fetch latest TCB info from Intel PCS (Provisioning Certification Service)
Compare quote’s TCB level with current TCB info
Determine TCB status (UpToDate, SWHardeningNeeded, OutOfDate, etc.)
Measurement Validation
Verify MRTD matches expected bootchain
Check RTMR values against policy:
RTMR0: Expected boot/kernel measurement
RTMR1: Expected OS image hash
RTMR2: Expected docker-compose application hash
Report Data Verification
Extract report_data from quote
Recompute SHA512(nonce + EKM) client-side
Verify they match (proving session binding)
Critical Security Check : The client MUST verify that the report_data in the quote matches the expected SHA512(nonce + EKM). This proves the quote was generated for THIS specific TLS session and prevents quote replay attacks.
TCB Status Interpretation
The Trusted Computing Base (TCB) status indicates the security level of the platform:
Status Values
Status Meaning Risk Level UpToDateAll platform components are current ✅ Safe SWHardeningNeededVulnerabilities exist but have mitigations ⚠️ Acceptable (with caution) ConfigurationNeededPlatform needs reconfiguration ⚠️ Review required ConfigurationAndSWHardeningNeededBoth configuration and updates needed ⚠️ Review required OutOfDateSecurity updates available but not applied ❌ Risky OutOfDateConfigurationNeededMultiple issues ❌ Risky RevokedPlatform has been compromised ❌ REJECT
Policy Configuration
Umbra’s aTLS client allows configuring acceptable TCB statuses:
// Development policy (relaxed)
export const DEV_POLICY : AtlasPolicy = {
type: "dstack_tdx" ,
disable_runtime_verification: true ,
allowed_tcb_status: [ "UpToDate" , "SWHardeningNeeded" , "OutOfDate" ],
}
// Production policy (strict)
const PROD_POLICY : AtlasPolicy = {
type: "dstack_tdx" ,
expected_bootchain: {
mrtd: "<expected_mrtd_hash>" ,
rtmr0: "<expected_boot_measurement>" ,
rtmr1: "<expected_os_hash>" ,
rtmr2: "<expected_app_hash>" ,
},
allowed_tcb_status: [ "UpToDate" ], // Only accept fully patched systems
}
Production Recommendation : Only accept UpToDate in production environments. SWHardeningNeeded may be acceptable if you understand the specific vulnerabilities and have implemented additional controls.
Real-World Verification Example
Here’s how the browser verifies a quote:
import { createAtlasClient , type AtlasPolicy } from "@/lib/atlas-client"
// 1. Generate client nonce
const nonce = crypto . getRandomValues ( new Uint8Array ( 32 ))
const nonceHex = Array . from ( nonce )
. map ( b => b . toString ( 16 ). padStart ( 2 , '0' ))
. join ( '' )
// 2. Create aTLS client with policy
const policy : AtlasPolicy = {
type: "dstack_tdx" ,
expected_bootchain: {
rtmr2: "abc123..." // Expected docker-compose hash
},
allowed_tcb_status: [ "UpToDate" , "SWHardeningNeeded" ],
}
const atlasFetch = await createAtlasClient (
{
proxyUrl: "wss://proxy.example.com" ,
targetHost: "tee.example.com:443" ,
policy ,
},
async ( attestation ) => {
// This callback fires after verification succeeds
console . log ( "TEE Type:" , attestation . teeType ) // "TDX"
console . log ( "TCB Status:" , attestation . tcbStatus ) // "UpToDate"
console . log ( "Trusted:" , attestation . trusted ) // true
}
)
// 3. Make request - attestation happens automatically
const response = await atlasFetch ( "/api/chat/completions" , {
method: "POST" ,
body: JSON . stringify ({ messages: [ ... ] }),
})
// 4. Verify attestation result
if ( ! response . attestation . trusted ) {
throw new Error ( `Attestation failed: ${ response . attestation . tcbStatus } ` )
}
Dstack Integration
The attestation service uses the dstack SDK to interact with TDX hardware:
from dstack_sdk import AsyncDstackClient
# Initialize client (connects to /var/run/dstack.sock)
dstack_client = AsyncDstackClient()
# Get quote with custom report_data
quote = await dstack_client.get_quote(report_data)
# Get TCB info
info_response = await dstack_client.info()
tcb_info = info_response.tcb_info
The dstack daemon (/var/run/dstack.sock) is a privileged service that communicates with the TDX module in the Linux kernel. Only processes inside the TEE can access this socket.
Development Mode
For local testing without TDX hardware:
# Run attestation service without dstack
export NO_TDX = true
cd cvm/attestation-service
make dev
In development mode:
The service uses EKM_SHARED_SECRET environment variable instead of dstack key derivation
Quotes are still generated but may use simulated values
Client-side verification should use disable_runtime_verification: true
Never use NO_TDX=true or disable_runtime_verification in production. These modes bypass critical security checks.
Troubleshooting
Quote Generation Fails
Error: Failed to obtain TDX quote
Possible causes:
dstack daemon not running (systemctl status dstack)
Socket permission issues (/var/run/dstack.sock)
TDX not enabled in BIOS
Kernel module not loaded (lsmod | grep tdx)
DCAP Verification Fails
Error: Attestation verification failed
Possible causes:
Certificate chain invalid (check Intel PCS connectivity)
TCB status not in allowed list
Measurement mismatch (MRTD/RTMR values don’t match policy)
Clock skew (quote timestamp too far in past/future)
Report Data Mismatch
Error: report_data does not match expected value
This is a critical security error. Possible causes:
Quote replay attack (someone reusing an old quote)
EKM extraction failure (nginx not forwarding correct EKM)
Nonce generation issue (client and server disagree on nonce)
Do NOT ignore report_data mismatches. This indicates a potential security breach or misconfiguration.
Next Steps
EKM Channel Binding Learn how EKM binds attestations to TLS sessions
RA-TLS (aTLS) Explore the complete aTLS implementation
TEE Overview Back to TEE fundamentals
Attestation Service Code View the source code