From 32e60edd6dc96e971a455ceec7d84fbc1df8cacd Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 18 Apr 2023 10:24:32 -0700 Subject: [PATCH] crypto/tls: enforce 1.3 record version semantics 1.3 expects the record version is always 1.2 (0x0303), this previously wasn't enforced. Change-Id: I8bc88f588e76f9b862b57601336bb5c5ff08b30e Reviewed-on: https://go-review.googlesource.com/c/go/+/485876 Reviewed-by: Damien Neil Auto-Submit: Roland Shoemaker Run-TryBot: Roland Shoemaker TryBot-Result: Gopher Robot --- conn.go | 10 ++++++++-- conn_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/conn.go b/conn.go index a5e19dc..847d3f8 100644 --- a/conn.go +++ b/conn.go @@ -639,10 +639,16 @@ func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error { } vers := uint16(hdr[1])<<8 | uint16(hdr[2]) + expectedVers := c.vers + if expectedVers == VersionTLS13 { + // All TLS 1.3 records are expected to have 0x0303 (1.2) after + // the initial hello (RFC 8446 Section 5.1). + expectedVers = VersionTLS12 + } n := int(hdr[3])<<8 | int(hdr[4]) - if c.haveVers && c.vers != VersionTLS13 && vers != c.vers { + if c.haveVers && vers != expectedVers { c.sendAlert(alertProtocolVersion) - msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, c.vers) + msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, expectedVers) return c.in.setErrorLocked(c.newRecordHeaderError(nil, msg)) } if !c.haveVers { diff --git a/conn_test.go b/conn_test.go index 78935b1..5e090a0 100644 --- a/conn_test.go +++ b/conn_test.go @@ -285,3 +285,35 @@ func TestHairpinInClose(t *testing.T) { // This call should not deadlock. tlsConn.Close() } + +func TestRecordBadVersionTLS13(t *testing.T) { + client, server := localPipe(t) + defer server.Close() + defer client.Close() + + config := testConfig.Clone() + config.MinVersion, config.MaxVersion = VersionTLS13, VersionTLS13 + + go func() { + tlsConn := Client(client, config) + if err := tlsConn.Handshake(); err != nil { + t.Errorf("Error from client handshake: %v", err) + return + } + tlsConn.vers = 0x1111 + tlsConn.Write([]byte{1}) + }() + + tlsConn := Server(server, config) + if err := tlsConn.Handshake(); err != nil { + t.Errorf("Error from client handshake: %v", err) + return + } + + expectedErr := "tls: received record with version 1111 when expecting version 303" + + _, err := tlsConn.Read(make([]byte, 10)) + if err.Error() != expectedErr { + t.Fatalf("unexpected error: got %q, want %q", err, expectedErr) + } +}