Add configurable TLS curve preferences for hybrid ML-KEM policy
- Dominant language
- Go
- Stars
- 36.3k
- Forks
- 4.8k
- PR merge metrics
- PR metrics pending
Description
**Is your feature request related to a problem? Please describe.**
Vault's current Go baseline supports the standardized `X25519MLKEM768` TLS 1.3 hybrid key-exchange group and Go can prefer it automatically. However, an older or deliberately constrained client can still negotiate classical key exchange. Vault operators do not currently have a listener-level control to distinguish a compatibility rollout from a policy that requires hybrid ML-KEM.
For secrets-management traffic with a long confidentiality lifetime, this prevents operators from enforcing a chosen harvest-now-decrypt-later posture after they have upgraded and validated their client estate. It also makes it difficult to prove whether classical fallback is intentionally allowed or merely an uncontrolled default.
This request is limited to TLS group configuration. It does not propose new cryptographic implementations, PQ certificates, Transit KEM operations, or changes to TLS 1.3 cipher suites.
**Describe the solution you'd like**
Add an optional TCP-listener setting such as `tls_curve_preferences` that maps an explicit allowlist/order of supported names to Go `tls.CurveID` values.
Example compatibility rollout:
```hcl
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/vault/tls/server.pem"
tls_key_file = "/vault/tls/server-key.pem"
tls_min_version = "tls13"
tls_curve_preferences = ["X25519MLKEM768", "X25519"]
}
```
Example enforcement rollout:
```hcl
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/vault/tls/server.pem"
tls_key_file = "/vault/tls/server-key.pem"
tls_min_version = "tls13"
tls_curve_preferences = ["X25519MLKEM768"]
}
```
Proposed behavior:
- an absent setting preserves Go's existing defaults exactly;
- names are mapped through an explicit, documented allowlist rather than numeric IDs;
- unknown, empty, or duplicate entries fail listener configuration with an actionable error;
- hybrid-only configuration requires `tls_min_version = "tls13"` because PQC for TLS 1.2 is not being standardized;
- enforcement mode does not silently append a classical fallback;
- configuration output/logging may report the selected names but must not log connection secrets or session material;
- TLS 1.3 cipher-suite configuration remains separate because those suites do not select the KEX group.
I would expect a focused implementation to add listener configuration parsing, validation, the `tls.Config.CurvePreferences` assignment, documentation, and tests covering:
- unchanged defaults when omitted;
- hybrid negotiation with a capable client;
- classical fallback in compatibility mode;
- rejection of a classical-only client in hybrid-only mode;
- TLS 1.2/min-version conflicts;
- unknown and duplicate group names;
- multiple listener configurations;
- FIPS build behavior where applicable;
- configuration redaction and diagnostic output.
I would first scope this to the TCP API listener. If the cluster listener shares the same configuration seam, applying the setting consistently may be reasonable; otherwise cluster and plugin transport policy should be separate follow-up work.
**Describe alternatives you've considered**
1. Rely only on Go defaults. This provides opportunistic hybrid KEX but no way to require it after client migration.
2. Disable classical groups through undocumented environment/runtime controls. This is fragile, difficult to audit, and not a supported Vault configuration contract.
3. Place a PQC-capable reverse proxy in front of Vault. This adds another privileged component, certificate boundary, failure mode, and operational cost while leaving other Vault transport paths potentially classical.
4. Replace Vault or wait for pure-PQC TLS. Hybrid `X25519MLKEM768` is already standardized and implemented, and a staged compatibility-to-enforcement path can be useful now.
**Explain any additional use-cases**
- regulated organizations protecting secrets and credentials with multi-year confidentiality requirements;
- operators inventorying which Vault agents, CLIs, SDKs, proxies, and automation clients are not yet hybrid-capable;
- staged rollout where compatibility mode is monitored before hybrid-only enforcement;
- evidence that listener policy matches an organization's cryptographic migration standard;
- regression testing so client or runtime changes do not silently restore classical fallback.
The operational cost benefit is that organizations can use their existing Vault listeners and Go TLS implementation rather than deploying a separate TLS proxy solely to control hybrid key exchange.
**Additional context**
- Related broader request: #29673
- The implementation should use Go's standard-library group and contain no third-party PQ cryptographic dependency.
- Any contribution would be original work against Vault's current interfaces and accompanied by unit/integration tests and a changelog entry.
Disclosure: I maintain related open-source PQC migration work and work through [A2Z SOC](https://a2zsoc.com/), which provides scoped cryptographic-discovery and PQC rollout assessments. Any Vault implementation, tests, and documentation would remain vendor-neutral and contain no service promotion.
Contributor guide
Research direction
Start at the TCP API listener configuration parser and trace how listener settings reach the Go tls.Config. Read the existing listener validation, TLS tests, and diagnostic or redaction paths mentioned by the issue. Done means omitted settings preserve defaults, named groups validate and apply correctly, rollout and enforcement cases are tested, and documentation covers the supported configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100