From: Daniel McCarney Date: Sat, 17 May 2025 15:33:07 +0000 (-0400) Subject: crypto/tls: reject duplicate TLS 1.3 EncryptedExtensions X-Git-Tag: go1.25rc1~100 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=88679da4a396de98e975deb0e007b1d888a55676;p=gostls13.git crypto/tls: reject duplicate TLS 1.3 EncryptedExtensions When a TLS 1.3 client processes the server's encryptedExtensionsMsg it should reject instances that contain duplicate extension types. RFC 8446 ยง4.2 says: There MUST NOT be more than one extension of the same type in a given extension block. This update matches enforcement done in the client hello unmarshalling, but applied to the TLS 1.3 encrypted extensions message unmarshalling. Making this change also allows enabling the DuplicateExtensionClient-TLS-TLS13 BoGo test. Updates #72006 Change-Id: I27a2cd231e4b8762b0d9e2dbd3d8ddd5b87fd5d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/673757 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Auto-Submit: Daniel McCarney Reviewed-by: Filippo Valsorda Reviewed-by: Roland Shoemaker --- diff --git a/src/crypto/tls/bogo_config.json b/src/crypto/tls/bogo_config.json index 8276d08d35..1bc647ce60 100644 --- a/src/crypto/tls/bogo_config.json +++ b/src/crypto/tls/bogo_config.json @@ -72,7 +72,6 @@ "TicketSessionIDLength-33-TLS-TLS11": "TODO: first pass, this should be fixed", "UnsolicitedServerNameAck-TLS-TLS12": "TODO: first pass, this should be fixed", "TicketSessionIDLength-33-TLS-TLS12": "TODO: first pass, this should be fixed", - "DuplicateExtensionClient-TLS-TLS13": "TODO: first pass, this should be fixed", "UnsolicitedServerNameAck-TLS-TLS13": "TODO: first pass, this should be fixed", "RenegotiationInfo-Forbidden-TLS13": "TODO: first pass, this should be fixed", "EMS-Forbidden-TLS13": "TODO: first pass, this should be fixed", diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go index 6c6141c421..ad3e5fa352 100644 --- a/src/crypto/tls/handshake_messages.go +++ b/src/crypto/tls/handshake_messages.go @@ -1056,6 +1056,7 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { return false } + seenExts := make(map[uint16]bool) for !extensions.Empty() { var extension uint16 var extData cryptobyte.String @@ -1064,6 +1065,11 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool { return false } + if seenExts[extension] { + return false + } + seenExts[extension] = true + switch extension { case extensionALPN: var protoList cryptobyte.String