mirror of
https://github.com/refraction-networking/utls.git
synced 2025-04-03 20:17:36 +03:00
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 <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> Auto-Submit: Roland Shoemaker <roland@golang.org> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
5bf846b35c
commit
c96cbeb1bf
3 changed files with 77 additions and 8 deletions
13
common.go
13
common.go
|
@ -59,12 +59,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 = 16 // 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.
|
||||
|
|
16
conn.go
16
conn.go
|
@ -1089,10 +1089,22 @@ func (c *Conn) readHandshake(transcript transcriptHash) (any, error) {
|
|||
return nil, err
|
||||
}
|
||||
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
|
||||
|
|
56
tls_test.go
56
tls_test.go
|
@ -13,6 +13,7 @@ import (
|
|||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
|
@ -2002,3 +2003,58 @@ func TestX509KeyPairPopulateCertificate(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestEarlyLargeCertMsg(t *testing.T) {
|
||||
client, server := localPipe(t)
|
||||
|
||||
go func() {
|
||||
if _, err := client.Write([]byte{byte(recordTypeHandshake), 3, 4, 0, 4, typeCertificate, 1, 255, 255}); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}()
|
||||
|
||||
expectedErr := "tls: handshake message of length 131071 bytes exceeds maximum of 65536 bytes"
|
||||
servConn := Server(server, testConfig)
|
||||
err := servConn.Handshake()
|
||||
if err == nil {
|
||||
t.Fatal("unexpected success")
|
||||
}
|
||||
if err.Error() != expectedErr {
|
||||
t.Fatalf("unexpected error: got %q, want %q", err, expectedErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLargeCertMsg(t *testing.T) {
|
||||
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpl := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{CommonName: "test"},
|
||||
ExtraExtensions: []pkix.Extension{
|
||||
{
|
||||
Id: asn1.ObjectIdentifier{1, 2, 3},
|
||||
// Ballast to inflate the certificate beyond the
|
||||
// regular handshake record size.
|
||||
Value: make([]byte, 65536),
|
||||
},
|
||||
},
|
||||
}
|
||||
cert, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
clientConfig, serverConfig := testConfig.Clone(), testConfig.Clone()
|
||||
clientConfig.InsecureSkipVerify = true
|
||||
serverConfig.Certificates = []Certificate{
|
||||
{
|
||||
Certificate: [][]byte{cert},
|
||||
PrivateKey: k,
|
||||
},
|
||||
}
|
||||
if _, _, err := testHandshake(t, clientConfig, serverConfig); err != nil {
|
||||
t.Fatalf("unexpected failure :%s", err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue