After retrieving the attestation quote and event log, Atlas performs a series of cryptographic verification steps to establish trust in the remote TEE.
Verification overview
The verification process validates:
- DCAP quote - Cryptographic proof from Intel
- Report data binding - Links nonce and session EKM
- RTMR replay - Validates event log integrity
- Bootchain measurements - Verifies firmware and OS
- Runtime measurements - Validates app config and OS image
Each step builds on the previous, creating an unbroken chain of trust.
Step 1: DCAP quote verification
DCAP (Data Center Attestation Primitives) verification proves the quote was generated by a genuine Intel TDX CPU.
Fetch collateral
Collateral contains the certificates and CRLs needed to verify the quote signature:
let pccs_url = "https://api.trustedservices.intel.com";
let collateral = get_collateral(pccs_url, quote).await?;
Collateral includes:
- PCK Certificate Chain - Proves the Platform Certification Key (PCK) is Intel-issued
- TCB Info - Trusted Computing Base version information
- QE Identity - Expected Quoting Enclave measurements
- CRL - Certificate Revocation List
Atlas caches collateral by (PCCS URL, FMSPC, CA) for 8 hours to reduce network requests. The cache uses TTL expiration to ensure fresh collateral.
Verify quote signature
let verified_report = verify(quote, &collateral, now_secs)?;
The verify() function (from dcap-qvl crate) performs:
- Parse quote - Extract TD report, signature, and certificates
- Verify PCK cert chain - Check signatures up to Intel root CA
- Check revocation - Ensure PCK cert is not revoked
- Verify QE identity - Ensure Quoting Enclave is genuine Intel QE
- Verify quote signature - Check ECDSA signature using PCK public key
- Extract TD report - Parse the cryptographically verified TD report
If verification succeeds, the verified_report contains trusted measurements:
pub struct VerifiedReport {
pub status: String, // TCB status ("UpToDate", "OutOfDate", etc.)
pub report: Report, // Contains TDReport with measurements
}
Check TCB status
The TCB (Trusted Computing Base) status indicates the platform’s security level:
let tcb_allowed = config
.allowed_tcb_status
.iter()
.any(|s| s == &verified_report.status);
if !tcb_allowed {
return Err(AtlsVerificationError::TcbStatusNotAllowed {
status: verified_report.status,
allowed: config.allowed_tcb_status,
});
}
Common TCB statuses:
| Status | Meaning | Production Use |
|---|
UpToDate | All components current | ✅ Recommended |
SWHardeningNeeded | Microcode update available | ⚠️ Acceptable |
ConfigurationNeeded | BIOS config issue | ⚠️ Review required |
OutOfDate | Updates available | ⚠️ Use with grace period |
TDRelaunchAdvised | TD should be restarted | ❌ Not recommended |
Revoked | Platform compromised | ❌ Reject |
Grace period for OutOfDate
If configured, allow OutOfDate platforms within a grace period:
enforce_grace_period(
&verified_report,
&parsed_quote,
&collateral,
config.grace_period,
now_secs
)?;
The grace period allows platforms with OutOfDate TCB status if:
grace_period is configured in seconds
tcb_date + grace_period >= current_time
Example: With a 30-day grace period, platforms remain trusted for 30 days after a TCB update is released.
After DCAP verification, all data in verified_report is cryptographically trusted. Subsequent checks compare against this trusted baseline.
Step 2: Report data binding
Verify the quote was generated for this specific verification request and TLS session.
Compute expected report_data
let mut hasher = Sha512::new();
hasher.update(nonce); // 32 bytes from client
hasher.update(session_ekm); // 32 bytes from TLS session
let expected: [u8; 64] = hasher.finalize().into();
let td_report = verified_report.report.as_td10()
.ok_or(AtlsVerificationError::TeeTypeMismatch)?;
let actual = td_report.report_data;
Compare
if expected != actual {
return Err(AtlsVerificationError::ReportDataMismatch {
expected: hex::encode(expected),
actual: hex::encode(actual),
});
}
This binding proves:
- Freshness - Quote contains the nonce from this request
- Session binding - Quote contains the EKM from this TLS session
- No relay - Attacker cannot relay quotes from different sessions
Step 3: RTMR replay
Verify the event log integrity by replaying it to recompute RTMRs.
What are RTMRs?
Runtime Measurement Registers (RTMRs) are cryptographic accumulators:
RTMR_new = SHA384(RTMR_old || event_hash)
Each event extends an RTMR:
RTMR[pcr] = SHA384(RTMR[pcr] || SHA384(event_data))
RTMRs start at all-zeros and accumulate measurements throughout the boot process.
Replay event log
let replayed_rtmrs = quote_response.replay_rtmrs()?;
This recomputes RTMRs by processing each event in order:
for event in events {
let event_hash = SHA384(event.event_payload);
rtmrs[event.pcr] = SHA384(rtmrs[event.pcr] || event_hash);
}
Compare against trusted report
let trusted_rtmrs = [
hex::encode(td_report.rt_mr0),
hex::encode(td_report.rt_mr1),
hex::encode(td_report.rt_mr2),
hex::encode(td_report.rt_mr3),
];
for i in 0..4u8 {
let replayed = replayed_rtmrs.get(&i)
.ok_or(AtlsVerificationError::Quote(
format!("RTMR{} missing from replay", i)
))?;
if replayed != &trusted_rtmrs[i as usize] {
return Err(AtlsVerificationError::RtmrMismatch {
index: i,
expected: trusted_rtmrs[i as usize].clone(),
actual: replayed.clone(),
});
}
}
After RTMR replay succeeds, the event log is trusted. All measurements in the event log (certificate hash, app config, OS image) can now be validated.
Step 4: Bootchain verification
Verify the TEE firmware and OS kernel match expected values.
Get trusted measurements
let td_report = verified_report.report.as_td10()?;
let actual_mrtd = hex::encode(td_report.mr_td);
let actual_rtmrs = [
hex::encode(td_report.rt_mr0),
hex::encode(td_report.rt_mr1),
hex::encode(td_report.rt_mr2),
];
Compare against expected bootchain
let bootchain = config.expected_bootchain
.as_ref()
.ok_or(AtlsVerificationError::Configuration(
"expected_bootchain is required".into()
))?;
if actual_mrtd != bootchain.mrtd {
return Err(AtlsVerificationError::BootchainMismatch {
field: "mrtd".into(),
expected: bootchain.mrtd.clone(),
actual: actual_mrtd,
});
}
for i in 0..3 {
if actual_rtmrs[i] != bootchain[i] {
return Err(AtlsVerificationError::BootchainMismatch {
field: format!("rtmr{}", i),
expected: bootchain[i].clone(),
actual: actual_rtmrs[i].clone(),
});
}
}
Bootchain measurement meanings
| Measurement | Component | What It Measures |
|---|
| MRTD | TDVF (firmware) | Initial TD memory layout, firmware code |
| RTMR0 | Virtual hardware | VM configuration, CPU/memory layout |
| RTMR1 | Linux kernel | Kernel code loaded into the TD |
| RTMR2 | Kernel cmdline + initramfs | Boot parameters, initial ramdisk |
Step 5: Certificate binding verification
Verify the TLS certificate was generated inside the TEE.
Compute certificate hash
let cert_hash = hex::encode(Sha256::digest(peer_cert));
Find certificate event
let cert_event = events
.iter()
.rfind(|e| e.event == "New TLS Certificate")
.ok_or(AtlsVerificationError::CertificateNotInEventLog)?;
Decode and compare
The event payload is double-encoded (hex-of-hex):
let decoded = hex::decode(&cert_event.event_payload)?;
let eventlog_cert_hash = String::from_utf8(decoded)?;
if eventlog_cert_hash != cert_hash {
return Err(AtlsVerificationError::CertificateNotInEventLog);
}
Because the event log passed RTMR replay, and the certificate hash is in the event log, we’ve proven the TLS certificate was generated inside the TEE before the quote was created.
Step 6: App compose verification
Verify the application configuration matches expectations.
Compute expected hash
let expected = get_compose_hash(config.app_compose
.as_ref()
.ok_or(AtlsVerificationError::Configuration(
"app_compose is required".into()
))?
)?;
The get_compose_hash() function:
- Serializes the app_compose JSON deterministically
- Computes SHA256 hash
- Returns lowercase hex string
Find compose-hash event
let event = events
.iter()
.find(|e| e.event == "compose-hash")
.ok_or(AtlsVerificationError::AppComposeHashMismatch {
expected: expected.clone(),
actual: "<not found in event log>".to_string(),
})?;
Compare
if event.event_payload != expected {
return Err(AtlsVerificationError::AppComposeHashMismatch {
expected,
actual: event.event_payload.clone(),
});
}
This proves the application running in the TEE matches the expected configuration (environment variables, volumes, ports, etc.).
Step 7: OS image verification
Verify the OS image (initramfs) matches the expected version.
Find os-image-hash event
let expected = config.os_image_hash
.as_ref()
.ok_or(AtlsVerificationError::Configuration(
"os_image_hash is required".into()
))?;
let event = events
.iter()
.find(|e| e.event == "os-image-hash")
.ok_or(AtlsVerificationError::OsImageHashMismatch {
expected: expected.clone(),
actual: Some("<not found in event log>".to_string()),
})?;
Compare
if &event.event_payload != expected {
return Err(AtlsVerificationError::OsImageHashMismatch {
expected: expected.clone(),
actual: Some(event.event_payload.clone()),
});
}
This ensures the OS running in the TEE is the expected, trusted version.
Complete trust chain
After all verification steps succeed, we have established:
Intel Root CA (trusted)
↓ signs
PCK Certificate
↓ signs
TDX Quote
↓ contains
TD Report (MRTD, RTMRs, report_data)
↓ verifies
Event Log (via RTMR replay)
↓ contains
Runtime Measurements
• TLS certificate hash
• App compose hash
• OS image hash
↓ and
Session Binding (via report_data)
• Nonce (freshness)
• Session EKM (prevents relay)
Every link in this chain has been cryptographically verified, providing end-to-end trust from Intel’s root keys to the application running in the TEE.
See also