Skip to content
Snippets Groups Projects
Commit e282cbb1 authored by Daniel McCarney's avatar Daniel McCarney
Browse files

crypto/tls: handle client hello version too high

If the client hello legacy version is >= TLS 1.3, and no
supported_versions extension is sent, negotiate TLS 1.2 or lower when
supported.

On the topic of supported version negotiation RFC 8446 4.2.1 indicates
TLS 1.3 implementations MUST send a supported_versions extension with
a list of their supported protocol versions. The crypto/tls package
enforces this when the client hello legacy version indicates TLS 1.3
(0x0304), aborting the handshake with an alertMissingExtension alert if
no supported_versions were received.

However, section 4.2.1 indicates different behaviour should be used when
the extension is not present and TLS 1.2 or prior are supported:

  If this extension is not present, servers which are compliant with
  this specification and which also support TLS 1.2 MUST negotiate
  TLS 1.2 or prior as specified in [RFC5246], even if
  ClientHello.legacy_version is 0x0304 or later.

This commit updates the client hello processing logic to allow this
behaviour. If no supported_versions extension was received we ignore the
legacy version being >= TLS 1.3 and instead negotiate a lower supported
version if the server configuration allows.

This fix in turn allows enabling the BoGo ClientHelloVersionTooHigh,
MinorVersionTolerance, and MajorVersionTolerance tests.

Updates #72006
Change-Id: I27a2cd231e4b8762b0d9e2dbd3d8ddd5b87fd5c9
Reviewed-on: https://go-review.googlesource.com/c/go/+/671235


Reviewed-by: default avatarCherry Mui <cherryyz@google.com>
Reviewed-by: default avatarRoland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
parent fd605450
No related branches found
No related tags found
No related merge requests found
...@@ -66,11 +66,8 @@ ...@@ -66,11 +66,8 @@
"SupportTicketsWithSessionID": "TODO: first pass, this should be fixed", "SupportTicketsWithSessionID": "TODO: first pass, this should be fixed",
"NoNullCompression-TLS12": "TODO: first pass, this should be fixed", "NoNullCompression-TLS12": "TODO: first pass, this should be fixed",
"KeyUpdate-RequestACK": "TODO: first pass, this should be fixed", "KeyUpdate-RequestACK": "TODO: first pass, this should be fixed",
"ClientHelloVersionTooHigh": "TODO: first pass, this should be fixed",
"MinorVersionTolerance": "TODO: first pass, this should be fixed",
"IgnoreClientVersionOrder": "TODO: first pass, this should be fixed", "IgnoreClientVersionOrder": "TODO: first pass, this should be fixed",
"SupportedVersionSelection-TLS12": "TODO: first pass, this should be fixed", "SupportedVersionSelection-TLS12": "TODO: first pass, this should be fixed",
"MajorVersionTolerance": "TODO: first pass, this should be fixed",
"DuplicateExtensionServer-TLS-TLS1": "TODO: first pass, this should be fixed", "DuplicateExtensionServer-TLS-TLS1": "TODO: first pass, this should be fixed",
"DuplicateExtensionClient-TLS-TLS1": "TODO: first pass, this should be fixed", "DuplicateExtensionClient-TLS-TLS1": "TODO: first pass, this should be fixed",
"UnsolicitedServerNameAck-TLS-TLS1": "TODO: first pass, this should be fixed", "UnsolicitedServerNameAck-TLS-TLS1": "TODO: first pass, this should be fixed",
......
...@@ -169,7 +169,15 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, *echServer ...@@ -169,7 +169,15 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, *echServer
c.ticketKeys = originalConfig.ticketKeys(configForClient) c.ticketKeys = originalConfig.ticketKeys(configForClient)
clientVersions := clientHello.supportedVersions clientVersions := clientHello.supportedVersions
if len(clientHello.supportedVersions) == 0 { if clientHello.vers >= VersionTLS13 && len(clientVersions) == 0 {
// RFC 8446 4.2.1 indicates when the supported_versions extension is not sent,
// compatible servers MUST negotiate TLS 1.2 or earlier if supported, even
// if the client legacy version is TLS 1.3 or later.
//
// Since we reject empty extensionSupportedVersions in the client hello unmarshal
// finding the supportedVersions empty indicates the extension was not present.
clientVersions = supportedVersionsFromMax(VersionTLS12)
} else if len(clientVersions) == 0 {
clientVersions = supportedVersionsFromMax(clientHello.vers) clientVersions = supportedVersionsFromMax(clientHello.vers)
} }
c.vers, ok = c.config.mutualVersion(roleServer, clientVersions) c.vers, ok = c.config.mutualVersion(roleServer, clientVersions)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment