diff --git a/common.go b/common.go index f8243f1..ed987ac 100644 --- a/common.go +++ b/common.go @@ -1394,7 +1394,11 @@ func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error { } // The only signed key exchange we support is ECDHE. - if !supportsECDHE(config, vers, chi.SupportedCurves, chi.SupportedPoints) { + ecdheSupported, err := supportsECDHE(config, vers, chi.SupportedCurves, chi.SupportedPoints) + if err != nil { + return err + } + if !ecdheSupported { return supportsRSAFallback(errors.New("client doesn't support ECDHE, can only use legacy RSA key exchange")) } diff --git a/handshake_client.go b/handshake_client.go index 4ad6aa2..de5c420 100644 --- a/handshake_client.go +++ b/handshake_client.go @@ -886,6 +886,19 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { return false, errors.New("tls: server selected unsupported compression format") } + supportsPointFormat := false + offeredNonCompressedFormat := false + for _, format := range hs.serverHello.supportedPoints { + if format == pointFormatUncompressed { + supportsPointFormat = true + } else { + offeredNonCompressedFormat = true + } + } + if !supportsPointFormat && offeredNonCompressedFormat { + return false, errors.New("tls: server offered only incompatible point formats") + } + if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { c.secureRenegotiation = true if len(hs.serverHello.secureRenegotiation) != 0 { diff --git a/handshake_server.go b/handshake_server.go index 03d0553..3d5ea81 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -268,7 +268,11 @@ func (hs *serverHandshakeState) processClientHello() error { hs.hello.scts = hs.cert.SignedCertificateTimestamps } - hs.ecdheOk = supportsECDHE(c.config, c.vers, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) + hs.ecdheOk, err = supportsECDHE(c.config, c.vers, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) + if err != nil { + c.sendAlert(alertMissingExtension) + return err + } if hs.ecdheOk && len(hs.clientHello.supportedPoints) > 0 { // Although omitting the ec_point_formats extension is permitted, some @@ -339,7 +343,7 @@ func negotiateALPN(serverProtos, clientProtos []string, quic bool) (string, erro // supportsECDHE returns whether ECDHE key exchanges can be used with this // pre-TLS 1.3 client. -func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, supportedPoints []uint8) bool { +func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, supportedPoints []uint8) (bool, error) { supportsCurve := false for _, curve := range supportedCurves { if c.supportsCurve(version, curve) { @@ -349,10 +353,12 @@ func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, support } supportsPointFormat := false + offeredNonCompressedFormat := false for _, pointFormat := range supportedPoints { if pointFormat == pointFormatUncompressed { supportsPointFormat = true - break + } else { + offeredNonCompressedFormat = true } } // Per RFC 8422, Section 5.1.2, if the Supported Point Formats extension is @@ -361,9 +367,11 @@ func supportsECDHE(c *Config, version uint16, supportedCurves []CurveID, support // the parser. See https://go.dev/issue/49126. if len(supportedPoints) == 0 { supportsPointFormat = true + } else if offeredNonCompressedFormat && !supportsPointFormat { + return false, errors.New("tls: client offered only incompatible point formats") } - return supportsCurve && supportsPointFormat + return supportsCurve && supportsPointFormat, nil } func (hs *serverHandshakeState) pickCipherSuite() error {