From e4e8bff27dbe24575528b9a620df9b86f32fcdec Mon Sep 17 00:00:00 2001 From: peg Date: Mon, 27 Apr 2026 10:25:00 +0200 Subject: [PATCH 1/5] Document protocol details in README --- crates/attestation/README.md | 12 +++++ crates/attested-tls/readme.md | 84 ++++++++++++++++++++++++++++++++++- crates/pccs/README.md | 27 +++++++++++ readme.md | 22 ++++++--- 4 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 crates/pccs/README.md diff --git a/crates/attestation/README.md b/crates/attestation/README.md index 6e0320c..e1edfdc 100644 --- a/crates/attestation/README.md +++ b/crates/attestation/README.md @@ -10,6 +10,18 @@ This crate provides: - Attestation generation and verification for DCAP and (optionally) Azure - Parsing and evaluation of measurement policies +## Runtime Requirements + +Verification uses the [`pccs`](../pccs) crate for collateral caching and +background refresh. As a result, constructing an `AttestationVerifier` with +PCCS enabled and calling verification APIs, including +`verify_attestation_sync()`, is expected to happen from within a Tokio runtime, +and will panic if called outside of one. + +Note that the synchronous verification API is synchronous in its return type, +but it still relies on Tokio-backed background tasks for PCCS pre-warm +and cache refresh. + ## Feature flags ### `azure` diff --git a/crates/attested-tls/readme.md b/crates/attested-tls/readme.md index 5a0a745..d8dc837 100644 --- a/crates/attested-tls/readme.md +++ b/crates/attested-tls/readme.md @@ -1,3 +1,85 @@ # attested-tls -Attested TLS primitives. +Attested TLS primitives built on `rustls`. + +This crate provides two components: + +- `AttestedCertificateResolver`: issues TLS certificates which contain an + embedded attestation and handles renewal. It implements + [`rustls::server::ResolvesServerCert`](https://docs.rs/rustls/latest/rustls/server/trait.ResolvesServerCert.html) + and [`rustls::client::ResolvesClientCert`](https://docs.rs/rustls/latest/rustls/client/trait.ResolvesClientCert.html). +- `AttestedCertificateVerifier`: verifies the TLS certificate and the embedded + attestation during TLS handshake. It implements [`rustls::client::danger::ServerCertVerifier`](https://docs.rs/rustls/latest/rustls/client/danger/trait.ServerCertVerifier.html) + and [`rustls::server::danger::ClientCertVerifier`](https://docs.rs/rustls/latest/rustls/server/danger/trait.ClientCertVerifier.html). + +It supports both server and client TLS authentication, and can be used as the +inner attested session inside [`nested-tls`](../nested-tls). + +## Protocol details + +The resolver issues a short-lived X.509 leaf certificate whose attestation is +bound to: + +- The certificate public key +- The certificate validity window (`not_before`, `not_after`) +- The certificate primary hostname (common name) + +The binding is encoded as: + +`SHA-512(public_key_der || not_before_unix_secs || not_after_unix_secs || common_name)` + +That 64-byte hash is used as the attestation report data. The embedded +attestation is verified against the same recomputed value during certificate +verification. + +The certificate resolver: + +- Takes a single ECDSA P-256 keypair when constructed +- Issues either a self-signed leaf certificate or a leaf signed by a provided + private CA +- Embeds attestation evidence into the certificate using the + [`ra-tls`](https://github.com/Dstack-TEE/dstack/tree/master/ra-tls) crate +- Renews the certificate after two-thirds of its validity period has passed +- Reuses the same keypair for renewed certificates created by the same + resolver instance + +The certificate verifier: + +- Optionally verifies the certificate chain against a provided `RootCertStore` +- For self-signed server certificates, verifies server name and certificate + validity +- For self-signed client certificates, verifies certificate validity +- Extracts the embedded attestation from the certificate +- Recomputes the expected report data from the certificate contents +- Verifies the attestation through [`attestation`](../attestation) +- Caches successful attestation verifications until the certificate expires + so repeated handshakes with the same certificate avoid repeating quote + verification. + +Both server-side and client-side attested certificates are supported. + +## Certificate format + +Certificates are issued with: + +- Subject common name set to the configured primary hostname +- Subject alternative names containing the primary hostname plus any extra SANs +- Usable for both server and client auth + +The attestation is embedded using the `ra-tls` certificate extension format. +When verifying a certificate, this crate first tries to parse the `ra-tls` +attestation payload directly. If that fails, it falls back to reading the +custom attestation extension OID and parsing the JSON payload stored there. + +## Relationship to `nested-tls` + +This crate does not implement an outer TLS session or any stream nesting by +itself. + +If you want a standard CA-signed outer TLS session plus an inner attested +TLS session, use this crate together with [`nested-tls`](../nested-tls). +This is demonstrated in [tests/nested_tls.rs](./tests/nested_tls.rs). + +## Runtime requirements + +This crate expects to run in a Tokio runtime. diff --git a/crates/pccs/README.md b/crates/pccs/README.md new file mode 100644 index 0000000..d76b47e --- /dev/null +++ b/crates/pccs/README.md @@ -0,0 +1,27 @@ +# pccs + +An internal Provisioning Certificate Caching Service implementation for DCAP +collateral fetching and caching. + +This crate is used by attestation verification code that needs Intel TDX/SGX +collateral such as TCB info, QE identity, and certificate revocation lists. +It can: + +- Fetch collateral from Intel PCS or a configured PCCS endpoint +- Cache collateral in-process +- Pre-warm the cache at startup +- Refresh cached collateral in the background before expiry + +This is an alternative to Intel's reference PCCS server implementation which +can be embedded in Rust services that verify quotes. + +For Intel's terminology and architecture, see the Intel documentation for the +[Provisioning Certificate Caching Service (PCCS)](https://cc-enabling.trustedservices.intel.com/intel-sgx-tdx-pccs/01/introduction/). + +## Runtime Requirements + +This crate expects to be used from within a Tokio runtime. + +That applies even when calling synchronous-looking APIs such as +`get_collateral_sync()`: cache miss repair, proactive refresh, and startup +pre-warm are all driven by Tokio background tasks. diff --git a/readme.md b/readme.md index 209642c..322fe2f 100644 --- a/readme.md +++ b/readme.md @@ -1,18 +1,30 @@ # attested-tls -Primitives for attested tls channels. +Primitives for attested TLS channels. -Provided crates: +This workspace contains components for a protocol which binds confidential +computing attestation evidence to TLS certificates. -- [`attested-tls`](./crates/attested-tls) - WIP - provides attested TLS via X509 +- A outer TLS session authenticates the service using a standard CA-signed + certificate. This is optional. +- An inner TLS session which uses a certificate with attestation + evidence embedded in an extension. +- The attestation is verified during the inner TLS handshake and is bound to + the details of the certificate. + +More details in the individual READMEs of the provided crates: + +- [`attested-tls`](./crates/attested-tls) - provides attested TLS via X509 Certificate extensions and a custom certificate verifier. - [`nested-tls`](./crates/nested-tls) - provides two TLS sessions, such that that outer session can be used for a CA signed certificate and the inner - session for attestation. + session for attestation. - [`attestation`](./crates/attestation) - provides attestation generation, verification and measurement handling. +- [`pccs`](./crates/pccs) provides collateral fetching and caching for DCAP + verification. The included `shell.nix` file can be used with `nix-shell`, `direnv`, or `nix develop` to add the dependencies needed by the optional `azure` feature of the -`attestation` crate on Linux. See the +`attestation` crate on Linux. See the [`attestation` crate readme](./crates/attestation) for details. From 34a3e107c3240506ee6eb2705f8d9f3593208a1c Mon Sep 17 00:00:00 2001 From: peg Date: Mon, 27 Apr 2026 10:59:56 +0200 Subject: [PATCH 2/5] Add more explanation to top-level readme --- readme.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/readme.md b/readme.md index 322fe2f..2e4dd0a 100644 --- a/readme.md +++ b/readme.md @@ -5,6 +5,19 @@ Primitives for attested TLS channels. This workspace contains components for a protocol which binds confidential computing attestation evidence to TLS certificates. +```mermaid +sequenceDiagram + participant C as Client + participant S as Server + + opt Outer TLS + Note over C,S: TLS handshake with CA-signed cert + end + + Note over C,S: TLS handshake with attestation + C<<->>S: Application traffic +``` + - A outer TLS session authenticates the service using a standard CA-signed certificate. This is optional. - An inner TLS session which uses a certificate with attestation @@ -12,6 +25,12 @@ computing attestation evidence to TLS certificates. - The attestation is verified during the inner TLS handshake and is bound to the details of the certificate. +The idea is that the outer identity proves ownership of the domain and can +potentially persist across CVM re-starts to avoid relying on the CA at boot. + +The inner identity should not be persistent and represents a particular CVM +instance and particular OS image build. + More details in the individual READMEs of the provided crates: - [`attested-tls`](./crates/attested-tls) - provides attested TLS via X509 From 72114e28da03b88b71e0a00b32bf3e5d809bb997 Mon Sep 17 00:00:00 2001 From: peg Date: Mon, 27 Apr 2026 11:28:56 +0200 Subject: [PATCH 3/5] Add more explanation to nested-tls readme --- crates/attested-tls/readme.md | 2 +- crates/nested-tls/readme.md | 30 ++++++++++++++++++++++++++++++ readme.md | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/crates/attested-tls/readme.md b/crates/attested-tls/readme.md index d8dc837..540b251 100644 --- a/crates/attested-tls/readme.md +++ b/crates/attested-tls/readme.md @@ -12,7 +12,7 @@ This crate provides two components: attestation during TLS handshake. It implements [`rustls::client::danger::ServerCertVerifier`](https://docs.rs/rustls/latest/rustls/client/danger/trait.ServerCertVerifier.html) and [`rustls::server::danger::ClientCertVerifier`](https://docs.rs/rustls/latest/rustls/server/danger/trait.ClientCertVerifier.html). -It supports both server and client TLS authentication, and can be used as the +The crate supports both server and client TLS authentication, and can be used as the inner attested session inside [`nested-tls`](../nested-tls). ## Protocol details diff --git a/crates/nested-tls/readme.md b/crates/nested-tls/readme.md index aaa02c8..3a44d84 100644 --- a/crates/nested-tls/readme.md +++ b/crates/nested-tls/readme.md @@ -1,3 +1,33 @@ # nested-tls Nested TLS primitives. + +This crate provides wrappers around `rustls'` `Acceptor` and `Connector` for +running one TLS session inside another. + +At a high level: + +1. The client and server complete an outer TLS handshake over the underlying + transport. +2. A second TLS handshake is then performed over the encrypted outer TLS + stream. +3. The resulting stream can be used like a normal TLS stream. + +The main types are: + +- `client::NestingTlsConnector`, which performs the outer handshake and then + the inner handshake on the client side +- `server::NestingTlsAcceptor`, which accepts the outer handshake and then the + inner handshake on the server side + +The crate also includes [Actix](https://actix.rs/) integration for both client +and server. + +This crate does not define the authentication policy of either layer. It only +composes two `rustls` sessions. In this workspace, the proposed pattern is: + +- outer TLS for conventional CA-signed certificates +- inner TLS for attested certificates via [`attested-tls`](../attested-tls) + +After both handshakes complete, callers interact with the returned stream as a +single nested TLS connection. diff --git a/readme.md b/readme.md index 2e4dd0a..501bd4c 100644 --- a/readme.md +++ b/readme.md @@ -14,7 +14,7 @@ sequenceDiagram Note over C,S: TLS handshake with CA-signed cert end - Note over C,S: TLS handshake with attestation + Note over C,S: TLS handshake with attestation verification C<<->>S: Application traffic ``` From fc24c8ace0d44cd28ae7f9e3262605e71a3513d2 Mon Sep 17 00:00:00 2001 From: peg Date: Fri, 8 May 2026 08:58:50 +0200 Subject: [PATCH 4/5] Update documentation to match implementation following latest changes --- crates/attested-tls/readme.md | 3 ++- readme.md | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/attested-tls/readme.md b/crates/attested-tls/readme.md index 540b251..4127446 100644 --- a/crates/attested-tls/readme.md +++ b/crates/attested-tls/readme.md @@ -34,7 +34,8 @@ verification. The certificate resolver: -- Takes a single ECDSA P-256 keypair when constructed +- Uses one keypair per resolver instance; by default it generates an + ECDSA P-256 keypair, but callers can provide a compatible keypair - Issues either a self-signed leaf certificate or a leaf signed by a provided private CA - Embeds attestation evidence into the certificate using the diff --git a/readme.md b/readme.md index 501bd4c..367037e 100644 --- a/readme.md +++ b/readme.md @@ -18,7 +18,7 @@ sequenceDiagram C<<->>S: Application traffic ``` -- A outer TLS session authenticates the service using a standard CA-signed +- An outer TLS session authenticates the service using a standard CA-signed certificate. This is optional. - An inner TLS session which uses a certificate with attestation evidence embedded in an extension. @@ -36,7 +36,7 @@ More details in the individual READMEs of the provided crates: - [`attested-tls`](./crates/attested-tls) - provides attested TLS via X509 Certificate extensions and a custom certificate verifier. - [`nested-tls`](./crates/nested-tls) - provides two TLS sessions, such that - that outer session can be used for a CA signed certificate and the inner + the outer session can be used for a CA signed certificate and the inner session for attestation. - [`attestation`](./crates/attestation) - provides attestation generation, verification and measurement handling. From 94158edcf2ac8ce19a54b6446ee716ed9a2c8d5f Mon Sep 17 00:00:00 2001 From: peg Date: Tue, 19 May 2026 09:16:58 +0200 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: Anton --- crates/attestation/README.md | 11 +++++------ crates/attested-tls/readme.md | 29 +++++++++++++++++------------ crates/nested-tls/readme.md | 2 +- crates/pccs/README.md | 7 ++++--- readme.md | 11 ++++++----- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/crates/attestation/README.md b/crates/attestation/README.md index e1edfdc..e57b3b5 100644 --- a/crates/attestation/README.md +++ b/crates/attestation/README.md @@ -14,13 +14,12 @@ This crate provides: Verification uses the [`pccs`](../pccs) crate for collateral caching and background refresh. As a result, constructing an `AttestationVerifier` with -PCCS enabled and calling verification APIs, including -`verify_attestation_sync()`, is expected to happen from within a Tokio runtime, -and will panic if called outside of one. +PCCS enabled and calling verification APIs is expected to happen from within a +Tokio runtime and might panic if called outside of one. -Note that the synchronous verification API is synchronous in its return type, -but it still relies on Tokio-backed background tasks for PCCS pre-warm -and cache refresh. +Note that although some of the verification API methods are synchronous (for +example `verify_attestation_sync`), still their functionality depends on +Tokio-backed background tasks such as PCCS pre-warm and cache refresh. ## Feature flags diff --git a/crates/attested-tls/readme.md b/crates/attested-tls/readme.md index 4127446..538a4f2 100644 --- a/crates/attested-tls/readme.md +++ b/crates/attested-tls/readme.md @@ -4,20 +4,24 @@ Attested TLS primitives built on `rustls`. This crate provides two components: -- `AttestedCertificateResolver`: issues TLS certificates which contain an - embedded attestation and handles renewal. It implements - [`rustls::server::ResolvesServerCert`](https://docs.rs/rustls/latest/rustls/server/trait.ResolvesServerCert.html) +- `AttestedCertificateResolver`: issues and renews TLS certificates with + attestations embedded in their extensions. + + It implements [`rustls::server::ResolvesServerCert`](https://docs.rs/rustls/latest/rustls/server/trait.ResolvesServerCert.html) and [`rustls::client::ResolvesClientCert`](https://docs.rs/rustls/latest/rustls/client/trait.ResolvesClientCert.html). -- `AttestedCertificateVerifier`: verifies the TLS certificate and the embedded - attestation during TLS handshake. It implements [`rustls::client::danger::ServerCertVerifier`](https://docs.rs/rustls/latest/rustls/client/danger/trait.ServerCertVerifier.html) + +- `AttestedCertificateVerifier`: verifies the TLS certificates and their + embedded attestations during TLS handshake. + + It implements [`rustls::client::danger::ServerCertVerifier`](https://docs.rs/rustls/latest/rustls/client/danger/trait.ServerCertVerifier.html) and [`rustls::server::danger::ClientCertVerifier`](https://docs.rs/rustls/latest/rustls/server/danger/trait.ClientCertVerifier.html). -The crate supports both server and client TLS authentication, and can be used as the -inner attested session inside [`nested-tls`](../nested-tls). +The crate supports both server and client TLS authentication, and can be used as +the inner attested session inside [`nested-tls`](../nested-tls). ## Protocol details -The resolver issues a short-lived X.509 leaf certificate whose attestation is +The resolver issues a short-lived X.509 leaf certificate which attestation is bound to: - The certificate public key @@ -36,8 +40,8 @@ The certificate resolver: - Uses one keypair per resolver instance; by default it generates an ECDSA P-256 keypair, but callers can provide a compatible keypair -- Issues either a self-signed leaf certificate or a leaf signed by a provided - private CA +- Issues either a self-signed certificate or a leaf certificate signed by a + provided (private) CA - Embeds attestation evidence into the certificate using the [`ra-tls`](https://github.com/Dstack-TEE/dstack/tree/master/ra-tls) crate - Renews the certificate after two-thirds of its validity period has passed @@ -67,8 +71,9 @@ Certificates are issued with: - Subject alternative names containing the primary hostname plus any extra SANs - Usable for both server and client auth -The attestation is embedded using the `ra-tls` certificate extension format. -When verifying a certificate, this crate first tries to parse the `ra-tls` +The attestation is embedded using the [`ra-tls`](https://github.com/Dstack-TEE/dstack/tree/master/ra-tls) +certificate extension format. When verifying a certificate, this crate first +tries to parse the [`ra-tls`](https://github.com/Dstack-TEE/dstack/tree/master/ra-tls) attestation payload directly. If that fails, it falls back to reading the custom attestation extension OID and parsing the JSON payload stored there. diff --git a/crates/nested-tls/readme.md b/crates/nested-tls/readme.md index 3a44d84..60829a0 100644 --- a/crates/nested-tls/readme.md +++ b/crates/nested-tls/readme.md @@ -2,7 +2,7 @@ Nested TLS primitives. -This crate provides wrappers around `rustls'` `Acceptor` and `Connector` for +This crate provides wrappers around `rustls`'s `Acceptor` and `Connector` for running one TLS session inside another. At a high level: diff --git a/crates/pccs/README.md b/crates/pccs/README.md index d76b47e..e1a3cfd 100644 --- a/crates/pccs/README.md +++ b/crates/pccs/README.md @@ -5,6 +5,7 @@ collateral fetching and caching. This crate is used by attestation verification code that needs Intel TDX/SGX collateral such as TCB info, QE identity, and certificate revocation lists. + It can: - Fetch collateral from Intel PCS or a configured PCCS endpoint @@ -22,6 +23,6 @@ For Intel's terminology and architecture, see the Intel documentation for the This crate expects to be used from within a Tokio runtime. -That applies even when calling synchronous-looking APIs such as -`get_collateral_sync()`: cache miss repair, proactive refresh, and startup -pre-warm are all driven by Tokio background tasks. +The above applies even when calling synchronous-looking APIs such as +`get_collateral_sync()` because cache miss repair, proactive refresh, and +startup pre-warm are all driven by Tokio background tasks. diff --git a/readme.md b/readme.md index 367037e..8cf9c74 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ Primitives for attested TLS channels. -This workspace contains components for a protocol which binds confidential +This workspace contains components for a protocol that binds confidential computing attestation evidence to TLS certificates. ```mermaid @@ -20,16 +20,17 @@ sequenceDiagram - An outer TLS session authenticates the service using a standard CA-signed certificate. This is optional. -- An inner TLS session which uses a certificate with attestation - evidence embedded in an extension. +- An inner TLS session uses a certificate with attestation evidence embedded in + an extension. - The attestation is verified during the inner TLS handshake and is bound to the details of the certificate. The idea is that the outer identity proves ownership of the domain and can potentially persist across CVM re-starts to avoid relying on the CA at boot. -The inner identity should not be persistent and represents a particular CVM -instance and particular OS image build. +The inner identity represents particular CVM lifetime (for example, it can +persist across service restarts, but must not persist across CVM reboots, let +alone CVM image updates). More details in the individual READMEs of the provided crates: