Rustls 0.23.41 plus the Privasys RA-TLS extensions, rebased onto upstream rel-0.23 with green CI. Three commits on top of upstream:
RA-TLS challenge extension 0xFFBB
- CertificateRequest leg:
ServerConfig::ratls_challengesends a challenge nonce to the client;ResolvesClientCert::resolvereceives it (ratls_challenge) so a TEE client binds it into its client cert's attestationreport_data. - ClientHello leg:
ClientConfig::ratls_challengesends the client's nonce; the server cert resolver reads it viaClientHello::ratls_challenge()for bidirectional challenge-response attestation.
Session channel binding (CVE-2026-33697 class relay defence)
- A 32-byte channel binder is derived from the TLS 1.3 key schedule:
HKDF-Expand-Label(client_handshake_traffic_secret, "privasys-ratls-binder-v1", transcript-through-ServerHello, 32)— identical on both peers, no negotiation. - Server leg:
ServerConfig::ratls_bind_certificatere-mints the server leaf at the Certificate-emit seam so its quote'sreport_datacommits to this exact session. - Mutual (client-cert) leg:
ResolvesClientCert::resolvealso receives the binder (ratls_channel_binder) so the client cert's quote commits to the session; the server stores the binder for post-handshake verification. A relayed identity fails closed against a binding-aware verifier (e.g. an Enclave Vault). ConnectionCommon::ratls_channel_binder()exposes the binder on both sides.
Both legs use the same handshake-secret binder, identical across the rustls and Go forks.
Tests
Dedicated rustls/tests/ratls.rs suite (ring + aws-lc-rs): binder equality across the handshake, both challenge legs reaching their resolvers, mutual-leg binder equality, bind-hook cert re-mint on the wire, TLS 1.2 fail-closed.
rustls = { git = "https://github.com/Privasys/rustls", tag = "privasys-v0.8.1" }Supersedes all earlier privasys-v0.x tags (rebased history).