Skip to main content
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:
  1. DCAP quote - Cryptographic proof from Intel
  2. Report data binding - Links nonce and session EKM
  3. RTMR replay - Validates event log integrity
  4. Bootchain measurements - Verifies firmware and OS
  5. 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:
  1. Parse quote - Extract TD report, signature, and certificates
  2. Verify PCK cert chain - Check signatures up to Intel root CA
  3. Check revocation - Ensure PCK cert is not revoked
  4. Verify QE identity - Ensure Quoting Enclave is genuine Intel QE
  5. Verify quote signature - Check ECDSA signature using PCK public key
  6. 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:
StatusMeaningProduction Use
UpToDateAll components current✅ Recommended
SWHardeningNeededMicrocode update available⚠️ Acceptable
ConfigurationNeededBIOS config issue⚠️ Review required
OutOfDateUpdates available⚠️ Use with grace period
TDRelaunchAdvisedTD should be restarted❌ Not recommended
RevokedPlatform 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();

Extract actual report_data

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

MeasurementComponentWhat It Measures
MRTDTDVF (firmware)Initial TD memory layout, firmware code
RTMR0Virtual hardwareVM configuration, CPU/memory layout
RTMR1Linux kernelKernel code loaded into the TD
RTMR2Kernel cmdline + initramfsBoot 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:
  1. Serializes the app_compose JSON deterministically
  2. Computes SHA256 hash
  3. 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

Build docs developers (and LLMs) love