Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/spec/attestation.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ An `AttestationReport` carries `platform`, `measurement`, the bound `public_key`
2. Report signature: the ECDSA-P384 signature (stored as little-endian `r` and `s`) is verified against the VCEK public key over the report body (`report[:0x2A0]`).
3. Binding: the launch `measurement` and the `report_data` (which carries the runtime key and nonce) are checked against expected values.

What is validated. The chain-verification path is exercised against the genuine AMD Milan ARK/ASK root chain fetched from AMD KDS (`tests/fixtures/sev_snp/`). The report-signature path is exercised end to end with a synthetic VCEK and report, because a genuine report plus VCEK pair requires real SEV-SNP hardware. Producing a report (`SevSnpProvider.attest`) fails closed off hardware (`AttestationUnsupported`).
What is validated. The chain-verification path is exercised against the genuine AMD Milan ARK/ASK root chain fetched from AMD KDS (`tests/fixtures/sev_snp/`), and the full path (VCEK chain to the ARK, ECDSA-P384 report signature, measurement binding, and rejection of a flipped bit) is exercised against a genuine SEV-SNP report captured from an Azure confidential VM, alongside the synthetic vectors. Producing a report (`SevSnpProvider.attest`) still fails closed off hardware (`AttestationUnsupported`). See [hardware validation](../hardware-validation.md).

Cross-operator use. Two operators in separate trust domains each bind their sealed-channel public key into a report and verify the counterparty's report against a pinned golden measurement. This composes into mutual attestation, confidential cross-operator delegation (seal to the attested key), and binary-swap detection (a changed measurement is rejected), validated in software as claim C6. See the [call graph](call-graph.md) and the `claim6-cross-operator-attestation` experiment.

## TDX verification

`ca2a_verify.tdx.verify_tdx_quote` appraises an Intel TDX quote (DCAP, ECDSA-256) offline in four fail-closed steps: the PCK certificate chain is verified up to a trusted Intel root; the Quoting Enclave report is verified against the PCK; the attestation key is confirmed to be the one the QE report data commits to (SHA-256 of the key and the QE auth data); and the attestation key's signature over the quote body is verified, along with the launch measurement (MRTD) and report data.

What is validated. The chain-verification path accepts the genuine self-signed Intel SGX Root CA fetched from Intel (`tests/fixtures/tdx/`) and rejects an untrusted root. The multi-level signature path (PCK to QE report to attestation key to quote) is exercised end to end with a synthetic self-consistent quote, because a genuine quote requires a TDX guest. Byte offsets follow the Intel DCAP Quote v4 layout; end-to-end validation against a real hardware quote requires a TDX guest and remains open.
What is validated. The chain-verification path accepts the genuine self-signed Intel SGX Root CA fetched from Intel (`tests/fixtures/tdx/`) and rejects an untrusted root, and the multi-level signature path (PCK to QE report to attestation key to quote) is exercised both with a synthetic self-consistent quote and against a genuine DCAP v4 quote captured from a GCP C3 confidential VM. Byte offsets follow the Intel DCAP Quote v4 layout, including the nested type-6 `QE_REPORT_CERTIFICATION_DATA` header that wraps the QE report and the type-5 PCK chain; reading the QE report directly after the attestation key is six bytes early and rejects every genuine quote. Quote *generation* still requires a TDX guest. See [hardware validation](../hardware-validation.md).

## TPM verification

`ca2a_verify.tpm.verify_tpm_quote` appraises a TPM 2.0 quote (`TPMS_ATTEST`) offline: the AK certificate chain is verified to a trusted root, the AK signature over the attest blob is verified (ECDSA-SHA256 or RSA PKCS#1 v1.5), the structure is confirmed to be a TPM-generated quote (magic and type), and the qualifying data (the verifier's nonce) and the PCR digest (the platform measurement) are checked against expected values.

What is validated. Unlike SEV-SNP and TDX, TPM attestation keys chain to per-vendor EK roots, so there is no single published root to validate against; the caller supplies the vendor roots it trusts, and the verifier is exercised against synthetic self-consistent vectors. Producing a quote (`TpmProvider.attest`) fails closed off a real TPM.
What is validated. Unlike SEV-SNP and TDX, TPM attestation keys chain to per-vendor EK roots, so there is no single published root to validate against; the caller supplies the vendor roots it trusts, and the verifier is exercised against synthetic self-consistent vectors only. No real AK-signed quote has been run through it, so unlike the other two backends the TPM path is not hardware-validated. See [hardware validation](../hardware-validation.md).

## Fail closed

Expand Down
10 changes: 6 additions & 4 deletions docs/spec/call-graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ If any step raises, the call is denied. Absence of evidence is denial, not a war
| Step | What it enforces | Function / type | Status |
|---|---|---|---|
| 1. Chain verification | Signature, continuity, attenuation, depth bound, anti-replay | `verify_chain` | Implemented |
| 2. Peer attestation | Peer measurement matches an expected value | `ca2a_verify.sev_snp.verify_sev_snp_report` | SEV-SNP verifier implemented; not yet wired into the call path; report needs hardware |
| 3. Scope intersection | Delegated scope intersected with local policy | `ca2a_runtime.peer.effective_scope`, `enforce_peer_call` | Implemented (decision core); Cedar engine binding pending (#10) |
| 2. Peer attestation | Peer measurement matches an expected value | `ca2a_verify.sev_snp`, `.tdx`, `.tpm`; `ca2a_runtime.attestation` | Verifiers implemented and wired into the handshake. SEV-SNP and TDX appraise real hardware evidence; on a live call off hardware the appraisal is `assurance="none"` |
| 3. Scope intersection | Delegated scope intersected with local policy | `ca2a_runtime.peer.effective_scope`, `enforce_peer_call` | Implemented, with `LocalPolicy` or the Cedar engine (`CedarPolicy`) |
| 4. Payload sealing | Payload sealed to the peer's attested key | `SealedChannel.seal`, `open_sealed` | Implemented (crypto); binding to a verified report on the live path pending |
| 5. Provenance record | A `DelegationRecord` emitted and linked to its parent | `enforce_peer_call`, `record_for`, `verify_dag` | Implemented (emitted by the decision core) |
| Inbound pipeline handler | Verify, enforce, open sealed payload, emit record off a parsed request | `handle_peer_request`, `PeerRequest` | Implemented (transport-agnostic) |
Expand All @@ -57,9 +57,11 @@ delegated_scope = leaf.scope # frozenset[str], the authority to enforce below

`max_depth` comes from `Ca2aConfig.max_delegation_depth` (default 8). This step is deterministic and offline: it contacts no operator and depends only on the signed bytes. It is the only step that gates an inbound call in this release.

## Step 2: verify peer attestation (pending, Tier 3)
## Step 2: verify peer attestation (implemented; software mode on a live call)

The runtime confirms the peer is running attested, measured code before it is trusted with the task, by checking the peer's report measurement against an expected value under a fresh nonce. A SEV-SNP verifier exists (`ca2a_verify.sev_snp.verify_sev_snp_report`: VCEK chain, report-signature, measurement binding), but it is not yet wired into this call path, producing a report requires real SEV-SNP hardware, and TDX/TPM backends are not implemented. Verification fails closed when evidence is absent. Do not treat this step as active on the live path yet. See [attestation.md](attestation.md).
The runtime confirms the peer is running attested, measured code before it is trusted with the task, by checking the peer's report measurement against an expected value under a fresh nonce. Verifiers exist and are fail-closed for all three platforms: `ca2a_verify.sev_snp` (VCEK chain, ECDSA-P384 report signature, measurement binding), `ca2a_verify.tdx` (DCAP v4 including the nested type-6 QE certification data, PCK chain to the Intel SGX Root CA, QE binding, MRTD) and `ca2a_verify.tpm` (AK chain, AK signature, qualifying-data and PCR-digest binding). The SEV-SNP and TDX verifiers appraise genuine hardware evidence; TPM is synthetic-vector validated only. See [hardware validation](../hardware-validation.md).

The handshake in `ca2a_runtime.attestation` gates the seal on an appraised channel key, so this step is wired into the call path. What is still missing is hardware on the live path: producing a report requires the platform, so off hardware the appraisal records `assurance="none"` and the `verifier` seam is not driven off a real quote. Do not read a completed software-mode call as an attested one. See [attestation.md](attestation.md).

## Step 3: intersect scope with local policy (implemented as a decision core)

Expand Down
Loading