From 0eb1df22cf7e6fecaadc27d58075aaf7a4b9572d Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Sun, 18 Aug 2024 23:25:25 -0400 Subject: [PATCH] crypto/tls: allow 256KiB certificate messages During handshake, lift the message length limit, but only for certificate messages. Fixes #50773 Change-Id: Ida9d83f4219c4386ca71ed3ef72b22259665a187 Reviewed-on: https://go-review.googlesource.com/c/go/+/585402 LUCI-TryBot-Result: Go LUCI Reviewed-by: Filippo Valsorda Auto-Submit: Roland Shoemaker Reviewed-by: Damien Neil --- common.go | 13 +++++++------ conn.go | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/common.go b/common.go index 4b49185..70695c1 100644 --- a/common.go +++ b/common.go @@ -58,12 +58,13 @@ func VersionName(version uint16) string { } const ( - maxPlaintext = 16384 // maximum plaintext payload length - maxCiphertext = 16384 + 2048 // maximum ciphertext payload length - maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3 - recordHeaderLen = 5 // record header length - maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) - maxUselessRecords = 32 // maximum number of consecutive non-advancing records + maxPlaintext = 16384 // maximum plaintext payload length + maxCiphertext = 16384 + 2048 // maximum ciphertext payload length + maxCiphertextTLS13 = 16384 + 256 // maximum ciphertext length in TLS 1.3 + recordHeaderLen = 5 // record header length + maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) + maxHandshakeCertificateMsg = 262144 // maximum certificate message size (256 KiB) + maxUselessRecords = 16 // maximum number of consecutive non-advancing records ) // TLS record types. diff --git a/conn.go b/conn.go index 7ded21c..868792f 100644 --- a/conn.go +++ b/conn.go @@ -1152,10 +1152,22 @@ func (c *Conn) readHandshake(transcript transcriptHash) (any, error) { } data := c.hand.Bytes() + + maxHandshakeSize := maxHandshake + // hasVers indicates we're past the first message, forcing someone trying to + // make us just allocate a large buffer to at least do the initial part of + // the handshake first. + if c.haveVers && data[0] == typeCertificate { + // Since certificate messages are likely to be the only messages that + // can be larger than maxHandshake, we use a special limit for just + // those messages. + maxHandshakeSize = maxHandshakeCertificateMsg + } + n := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) - if n > maxHandshake { + if n > maxHandshakeSize { c.sendAlertLocked(alertInternalError) - return nil, c.in.setErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake)) + return nil, c.in.setErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshakeSize)) } if err := c.readHandshakeBytes(4 + n); err != nil { return nil, err