mirror of
https://github.com/cloudflare/cloudflared.git
synced 2026-06-23 04:10:20 +00:00
f674b82e2a
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.
80 lines
3.2 KiB
Go
80 lines
3.2 KiB
Go
package crypto
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"errors"
|
|
"fmt"
|
|
"slices"
|
|
|
|
"github.com/cloudflare/cloudflared/features"
|
|
)
|
|
|
|
// errUnknownPostQuantumMode is returned by GetCurvePreferences when the
|
|
// caller passes a features.PostQuantumMode value that is not one of the
|
|
// documented constants. It is intentionally unexported: callers should treat
|
|
// any non-nil error as a programming mistake rather than inspecting it.
|
|
var errUnknownPostQuantumMode = errors.New("the provided post quantum mode is unknown")
|
|
|
|
// P256Kyber768Draft00 is a post-quantum KEM based on Kyber768.
|
|
const P256Kyber768Draft00 = tls.CurveID(0xfe32) // ID 65074
|
|
|
|
// Canonical curve lists returned by GetCurvePreferences. They are kept
|
|
// package-private so that callers cannot accidentally mutate the shared
|
|
// slice; GetCurvePreferences always returns a clone.
|
|
var (
|
|
// postQuantumStrictCurves is used when the caller requires a
|
|
// post-quantum handshake. Only PQ curves (X25519MLKEM768 and the
|
|
// deprecated P256Kyber768Draft00 for backward compatibility) are
|
|
// advertised; no classical-only curve is included.
|
|
postQuantumStrictCurves = []tls.CurveID{tls.X25519MLKEM768, P256Kyber768Draft00}
|
|
// postQuantumPreferCurves is used for the default "prefer" mode: the PQ
|
|
// curve is advertised first and the classical CurveP256 is listed as a
|
|
// fallback so peers without PQ support can still negotiate.
|
|
postQuantumPreferCurves = []tls.CurveID{tls.X25519MLKEM768, P256Kyber768Draft00, tls.CurveP256}
|
|
)
|
|
|
|
// getCurvePreferences returns the TLS curve preferences that should be
|
|
// applied to edge-facing connections for the given post-quantum mode.
|
|
//
|
|
// The returned slice is the canonical, protocol-agnostic curve list and is
|
|
// suitable for direct assignment to tls.Config.CurvePreferences. A fresh
|
|
// slice is returned on every call, so callers may mutate it freely without
|
|
// affecting other callers.
|
|
//
|
|
// An error is returned only when profile is not a recognised
|
|
// features.PostQuantumMode value, which indicates a programming bug in the
|
|
// caller.
|
|
func getCurvePreferences(profile features.PostQuantumMode) ([]tls.CurveID, error) {
|
|
switch profile {
|
|
case features.PostQuantumPrefer:
|
|
return slices.Clone(postQuantumPreferCurves), nil
|
|
case features.PostQuantumStrict:
|
|
return slices.Clone(postQuantumStrictCurves), nil
|
|
}
|
|
|
|
return nil, errUnknownPostQuantumMode
|
|
}
|
|
|
|
// TLSConfigWithCurvePreferences clones the provided tls.Config and applies
|
|
// curve preferences based on the given post-quantum mode.
|
|
//
|
|
// The original tls.Config is never modified; a clone is returned so that
|
|
// callers can safely use the same base configuration across multiple
|
|
// goroutines without racing on CurvePreferences.
|
|
//
|
|
// Returns an error only when pqMode is not a recognised
|
|
// features.PostQuantumMode value.
|
|
func TLSConfigWithCurvePreferences(tlsConfig *tls.Config, pqMode features.PostQuantumMode) (*tls.Config, error) {
|
|
// Clone the TLS config before applying per-connection curve
|
|
// preferences. The TlsConfig may be shared across goroutines;
|
|
// mutating it directly would race with concurrent connection attempts.
|
|
config := tlsConfig.Clone()
|
|
curvePref, err := getCurvePreferences(pqMode)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("get curve preferences: %w", err)
|
|
}
|
|
|
|
config.CurvePreferences = curvePref
|
|
return config, nil
|
|
}
|