Skip to content

feat(vault-api): post-quantum transport feature flag (X25519MLKEM768)#30

Merged
UnbreakableMJ merged 1 commit into
mainfrom
pqc-transport
Jun 16, 2026
Merged

feat(vault-api): post-quantum transport feature flag (X25519MLKEM768)#30
UnbreakableMJ merged 1 commit into
mainfrom
pqc-transport

Conversation

@UnbreakableMJ

Copy link
Copy Markdown
Contributor

What

Adds an off-by-default pqc cargo feature that prefers the hybrid X25519MLKEM768 key exchange on the HTTPS/TLS layer — the PRD §12 M7 "PQC transport feature flag" item. With PQC enabled, a TLS 1.3 handshake negotiates a post-quantum-secure shared secret when the server offers it, and silently falls back to a classical group otherwise.

GPL-clean by construction

rustls only ships X25519MLKEM768 via its aws-lc-rs provider, whose bundled AWS-LC carries OpenSSL-licensed code — GPL-incompatible, so off the table for a GPL-3.0-or-later project (Standard §4). Instead the hybrid is built from GPL-compatible parts:

  • classical half — ring's audited X25519 (rustls::crypto::ring::kx_group::X25519), reused as-is;
  • post-quantum half — RustCrypto ml-kem (MlKem768), Apache-2.0/MIT.

cargo deny check passes with the new optional deps in the graph (no allow-list change).

How

  • crates/vault-api/src/pqc.rs — ML-KEM-768 as a rustls::crypto::SupportedKxGroup (client/KEM-initiator role: generate keypair, send the encapsulation key, decapsulate the server's ciphertext), composed with ring's X25519 into the X25519MLKEM768 hybrid. Post-quantum-first wire layout per draft-ietf-tls-ecdhe-mlkem (client share ek(1184)‖x25519(32), server share ct(1088)‖x25519(32), secret ss_mlkem(32)‖ss_x25519(32)), mirroring rustls's own crate-private layout. client_config() builds a rustls ClientConfig listing the hybrid first (classical fallback), injected into reqwest via use_preconfigured_tls. No unsafe (stays under #![forbid(unsafe_code)]).
  • client.rsBitwardenClient::new wires it behind #[cfg(feature = "pqc")]; a gated Error::PqcTls carries config errors. vault-agent gains a pqc passthrough feature.

Off by default → existing gates unchanged

The default dep tree, cargo test --workspace, cargo deny, and both headless builds are untouched (PQC off). Clippy is --all-features so it builds + lints the module. The feature's own tests run with cargo test -p vault-api --features pqc (CI's test job doesn't pass --all-features) and cover: the ML-KEM client kx round-trip (encapsulate→decapsulate secrets match), the hybrid pub-key layout, wrong-length rejection, and that the config prefers PQC.

Verification

fmt --check, fresh-isolated clippy --all-features -D warnings, cargo test --workspace --all-targets, cargo test -p vault-api --features pqc (4/4), cargo deny check, both headless builds — all green.

Out of scope (still pending for the v0.1 tag)

A live PQC-handshake test against a real server; making PQC the default. The ≥24h fuzz soak, the broader hardening pass, and the §11.2 two-week daily-driver attestation remain; then a slice cuts v0.1.0.

🤖 Generated with Claude Code

Adds an off-by-default `pqc` cargo feature that prefers the hybrid
X25519MLKEM768 key exchange on the HTTPS/TLS layer — the PRD §12 M7 PQC
transport item. Built from GPL-compatible parts only: the classical half
reuses ring's audited X25519, the post-quantum half is RustCrypto `ml-kem`
(Apache-2.0/MIT). We deliberately avoid aws-lc-rs (the only rustls provider
shipping X25519MLKEM768) because its bundled AWS-LC carries OpenSSL-licensed
code, which is GPL-incompatible.

- crates/vault-api/src/pqc.rs: ML-KEM-768 as a rustls SupportedKxGroup
  (client/KEM-initiator role), composed with ring's X25519 into the
  X25519MLKEM768 hybrid (post-quantum-first wire layout per
  draft-ietf-tls-ecdhe-mlkem); `client_config()` builds a rustls ClientConfig
  that lists the hybrid first with classical fallback, injected into reqwest
  via `use_preconfigured_tls`. No unsafe (stays under forbid(unsafe_code)).
- BitwardenClient::new wires it behind `#[cfg(feature = "pqc")]`; a gated
  Error::PqcTls variant carries config errors. vault-agent gains a `pqc`
  passthrough feature.
- Off by default: the default dep tree, tests, deny, and headless builds are
  unchanged. Tests (run with `--features pqc`) cover the ML-KEM client kx
  round-trip + hybrid layout + that the config prefers PQC.
- docs/pqc.md (construction + licensing rationale), README pointer, CHANGELOG.

TLS 1.3 only; silent classical fallback when the server lacks PQC.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@UnbreakableMJ
UnbreakableMJ merged commit 7eb5a7c into main Jun 16, 2026
8 checks passed
@UnbreakableMJ
UnbreakableMJ deleted the pqc-transport branch June 16, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant