TUN-10413: Centralize TLS curve configuration in crypto/ and adopt X25519MLKEM768 for QUIC/H2

Introduce a new crypto/ package as the single source of truth for TLS
curve preferences used on every edge-facing connection, and adopt
X25519MLKEM768 as the primary post-quantum key exchange for both QUIC
and HTTP/2:

  PQ Prefer (default):     X25519MLKEM768, P256Kyber768Draft00, CurveP256
  PQ Strict (--post-quantum): X25519MLKEM768, P256Kyber768Draft00

The curve list is identical under FIPS and non-FIPS builds, so
crypto.GetCurvePreferences takes only a features.PostQuantumMode and
returns a fresh slice on every call.

HTTP/2 now applies these curve preferences the same way QUIC does. The
previous PostQuantumStrict rejection in serveHTTP2 and the forced
QUIC-only selection in NewProtocolSelector are removed since both
transports support the same post-quantum curves; the needPQ parameter
is dropped from NewProtocolSelector accordingly.

Also fix a shared tls.Config race: both the QUIC and HTTP/2 paths now
Clone() the per-protocol entry from TunnelConfig.EdgeTLSConfigs before
mutating CurvePreferences instead of writing through the shared map
entry.

Legacy Kyber draft curve X25519Kyber768Draft00
and the unused removeDuplicates helper are removed along with the old
supervisor/pqtunnels.go / _test.go files.

AGENTS.md is updated with guidance on the new crypto/ package, the
cfdcrypto import alias, the tls.Config cloning rule, and the lint
workflow implications of .golangci.yaml's whole-files: true setting.
This commit is contained in:
lneto
2026-05-12 07:47:38 +01:00
committed by Luis Neto
parent ae3799a098
commit f674b82e2a
12 changed files with 326 additions and 235 deletions
+52
View File
@@ -60,6 +60,16 @@ make vet
cd component-tests && python -m pytest test_file.py::test_function_name
```
Notes on linting:
- `.golangci.yaml` is configured with `new-from-rev` and `whole-files: true`.
Touching a file triggers linting of the ENTIRE file, not just the changed
hunks. Expect to fix pre-existing issues in files you modify, or add
targeted `// nolint: <linter>` comments with a short justification.
- Prefer `defer func() { _ = resource.Close() }()` over `defer resource.Close()`
for `io.Closer` values whose error truly does not matter — this satisfies
`errcheck` without hiding real failures elsewhere.
## Project Knowledge
### Package Structure
@@ -68,6 +78,24 @@ cd component-tests && python -m pytest test_file.py::test_function_name
- Package names should be lowercase, single words when possible
- Avoid generic names like `util`, `common`, `helper`
#### Well-known shared packages
- `crypto/`: Single source of truth for TLS curve preferences and other
cryptographic primitives shared by every edge-facing transport. Import as
`cfdcrypto "github.com/cloudflare/cloudflared/crypto"` to avoid colliding
with the standard library's `crypto` package. Do NOT duplicate TLS curve
or cipher selection logic in other packages.
- `tlsconfig/`: Builds the base `*tls.Config` used for edge connections
(`CreateTunnelConfig`) and loads origin/CA pools. Curve selection is
intentionally NOT set here; it is applied per-connection from the
`crypto/` package so the same config can be cloned and reused across
protocols.
- `features/`: Runtime feature flags including `PostQuantumMode`
(`PostQuantumPrefer` = default, `PostQuantumStrict` = `--post-quantum`).
- `fips/`: Build-tag driven FIPS detection. Only `fips.IsFipsEnabled()` is
exposed; never branch on `fipsEnabled` inside a function if the two
branches return the same value.
### Function and Method Guidelines
```go
@@ -171,6 +199,30 @@ type TunnelProperties struct {
- Use channels for goroutine communication
- Protect shared state with mutexes
- Prefer `sync.RWMutex` for read-heavy workloads
- `*tls.Config` values stored in shared maps (e.g.
`TunnelConfig.EdgeTLSConfigs`) must be `Clone()`d before mutating
per-connection fields like `CurvePreferences` or `NextProtos`. Writing
through the shared pointer races with concurrent connection attempts.
### TLS & Post-Quantum key exchange
- Per-connection TLS configuration for edge connections is built via
`cfdcrypto.TLSConfigWithCurvePreferences(tlsConfig, pqMode)`. It clones
the provided `*tls.Config` and sets `CurvePreferences` based on `pqMode`,
so callers never need to clone or mutate `CurvePreferences` themselves.
Do NOT reach for the package-private `getCurvePreferences` helper; the
exported `TLSConfigWithCurvePreferences` is the only supported entry
point.
- Two PQ modes are supported and apply identically to QUIC and HTTP/2:
- `PostQuantumPrefer` (default): `[X25519MLKEM768, P256Kyber768Draft00, CurveP256]`
- `PostQuantumStrict` (`--post-quantum`): `[X25519MLKEM768, P256Kyber768Draft00]`
- FIPS and non-FIPS builds use the same curve list. Do NOT reintroduce a
`fipsEnabled` branch in curve-selection code; if the two modes ever
diverge, express the divergence inside `crypto/` so call sites remain
untouched.
- HTTP/2 supports post-quantum handshakes. Never re-add a
`PostQuantumStrict`-based rejection to H2 code paths, and never force
`--post-quantum` to select QUIC-only in protocol selection.
### Configuration