Module pq

Module pq 

Source
Expand description

Post-quantum TLS (DW-105): X25519+ML-KEM hybrid key exchange.

This module wires the X25519+ML-KEM hybrid key-exchange group into rustls. The hybrid group combines a classical ECDH secret (X25519) with a post-quantum KEM secret (ML-KEM, formerly Kyber) so that the negotiated session key remains confidential even if a future quantum adversary can break ECDH. The classical X25519 share is kept as a fallback, so a client that does not support the hybrid group still completes a classical handshake (rustls’s kx group list is a preference order: the first group the client supports wins, so prepending the hybrid group PREFERS it without removing the classical fallback).

§Experimental

The rustls API for post-quantum key exchange is EXPERIMENTAL and not yet stable: the specific kx group type, its registration path, and the provider integration may change between rustls releases. This module is therefore structured so the config schema EXISTS and COMPILES regardless of whether the experimental PQ API is available in the pinned rustls version. When the experimental API is not reachable, install_pq_kx_group is a documented no-op (it logs and returns PqMode::Disabled); when the API stabilizes, the real wiring lands here without touching config, validation, or metrics.

§FIPS incompatibility

ML-KEM is NOT on the FIPS-validated list for aws-lc-rs. Combining PQ hybrid key exchange with FIPS mode (Enterprise ent cargo feature) is REJECTED at config validation: a listener or upstream with pq: true while FIPS mode is active fails validation naming the field. The two features must not combine unless both algorithms are on a validated list (a future NIST FIPS 203 module path would lift this).

§Opt-in

PQ hybrid key exchange is opt-in per listener and per upstream via the additive pq: true config field. When the pq cargo feature is OFF, pq: true is accepted by the parser (additive-only, strict serde preserved) but is INERT: no kx group is prepended, and validation emits a warning issue so the operator knows the build does not include the PQ feature.

Structs§

PqHandshakeResult
The outcome of a PQ hybrid handshake attempt, captured for the dwara_tls_pq_handshakes_total{result} metric. The kx_group field carries the negotiated group name when the hybrid group was used, or the classical fallback group name when the client did not support the hybrid group (a fallback result).

Enums§

PqMode
The post-quantum TLS mode of the gateway.

Constants§

PQ_KX_GROUP_NAME
The canonical name of the X25519+ML-KEM hybrid key-exchange group as rustls would register it. Used as the kx_group label on PqHandshakeResult and in logs. The exact rustls type name may differ when the experimental API stabilizes; this constant is the operator-facing label.

Functions§

install_pq_kx_group
Prepend the X25519+ML-KEM hybrid key-exchange group to the rustls provider’s kx group list, so the hybrid group is PREFERRED while the classical X25519 group remains as a fallback for non-PQ clients.
pq_api_available
True when the pq cargo feature is compiled in AND the experimental rustls PQ API is reachable. Used by validation to distinguish “feature on but API inert” (warn) from “feature off” (warn) — both warn, but the message differs. The rustls 0.23.43 crate exposes the X25519MLKEM768 hybrid kx group via the aws-lc-rs provider, so this returns true.
pq_handshake_metric
The metric label for a PqHandshakeResult: success when the hybrid group was negotiated, fallback when the client fell back to a classical group, disabled when PQ is off. This is the closed three-value label set for dwara_tls_pq_handshakes_total{result}.
pq_provider
Build a CryptoProvider from the aws-lc-rs default provider with the X25519MLKEM768 hybrid kx group prepended to the kx group list. This is the per-config PQ support path (matching the FIPS pattern: fips_provider() returns a per-config provider). The server and client config builders use this when pq: true is set, passing the returned provider to ServerConfig::builder_with_provider or ClientConfig::builder_with_provider.