mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
[release-branch.go1.19] crypto/tls: add GODEBUG to control max RSA key size
Add a new GODEBUG setting, tlsmaxrsasize, which allows controlling the maximum RSA key size we will accept during TLS handshakes. Fixes #61968 Change-Id: I52f060be132014d219f4cd438f59990011a35c96 Reviewed-on: https://go-review.googlesource.com/c/go/+/517495 Auto-Submit: Roland Shoemaker <roland@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Roland Shoemaker <roland@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-on: https://go-review.googlesource.com/c/go/+/518536 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
parent
c08a5fa413
commit
caca5f126b
@ -1413,6 +1413,11 @@ func (c *Conn) closeNotify() error {
|
|||||||
//
|
//
|
||||||
// For control over canceling or setting a timeout on a handshake, use
|
// For control over canceling or setting a timeout on a handshake, use
|
||||||
// HandshakeContext or the Dialer's DialContext method instead.
|
// HandshakeContext or the Dialer's DialContext method instead.
|
||||||
|
//
|
||||||
|
// In order to avoid denial of service attacks, the maximum RSA key size allowed
|
||||||
|
// in certificates sent by either the TLS server or client is limited to 8192
|
||||||
|
// bits. This limit can be overridden by setting tlsmaxrsasize in the GODEBUG
|
||||||
|
// environment variable (e.g. GODEBUG=tlsmaxrsasize=4096).
|
||||||
func (c *Conn) Handshake() error {
|
func (c *Conn) Handshake() error {
|
||||||
return c.HandshakeContext(context.Background())
|
return c.HandshakeContext(context.Background())
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
|
"internal/godebug"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -857,9 +859,18 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxRSAKeySize is the maximum RSA key size in bits that we are willing
|
// defaultMaxRSAKeySize is the maximum RSA key size in bits that we are willing
|
||||||
// to verify the signatures of during a TLS handshake.
|
// to verify the signatures of during a TLS handshake.
|
||||||
const maxRSAKeySize = 8192
|
const defaultMaxRSAKeySize = 8192
|
||||||
|
|
||||||
|
func checkKeySize(n int) (max int, ok bool) {
|
||||||
|
if v := godebug.Get("tlsmaxrsasize"); v != "" {
|
||||||
|
if max, err := strconv.Atoi(v); err == nil {
|
||||||
|
return max, n <= max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultMaxRSAKeySize, n <= defaultMaxRSAKeySize
|
||||||
|
}
|
||||||
|
|
||||||
// verifyServerCertificate parses and verifies the provided chain, setting
|
// verifyServerCertificate parses and verifies the provided chain, setting
|
||||||
// c.verifiedChains and c.peerCertificates or sending the appropriate alert.
|
// c.verifiedChains and c.peerCertificates or sending the appropriate alert.
|
||||||
@ -871,9 +882,12 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
|
|||||||
c.sendAlert(alertBadCertificate)
|
c.sendAlert(alertBadCertificate)
|
||||||
return errors.New("tls: failed to parse certificate from server: " + err.Error())
|
return errors.New("tls: failed to parse certificate from server: " + err.Error())
|
||||||
}
|
}
|
||||||
if cert.PublicKeyAlgorithm == x509.RSA && cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
|
if cert.PublicKeyAlgorithm == x509.RSA {
|
||||||
c.sendAlert(alertBadCertificate)
|
n := cert.PublicKey.(*rsa.PublicKey).N.BitLen()
|
||||||
return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
|
if max, ok := checkKeySize(n); !ok {
|
||||||
|
c.sendAlert(alertBadCertificate)
|
||||||
|
return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", max)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
certs[i] = cert
|
certs[i] = cert
|
||||||
}
|
}
|
||||||
|
@ -2678,19 +2678,44 @@ u58=
|
|||||||
-----END CERTIFICATE-----`
|
-----END CERTIFICATE-----`
|
||||||
|
|
||||||
func TestHandshakeRSATooBig(t *testing.T) {
|
func TestHandshakeRSATooBig(t *testing.T) {
|
||||||
testCert, _ := pem.Decode([]byte(largeRSAKeyCertPEM))
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
godebug string
|
||||||
|
expectedServerErr string
|
||||||
|
expectedClientErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "key too large",
|
||||||
|
expectedServerErr: "tls: server sent certificate containing RSA key larger than 8192 bits",
|
||||||
|
expectedClientErr: "tls: client sent certificate containing RSA key larger than 8192 bits",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "acceptable key (GODEBUG=tlsmaxrsasize=8193)",
|
||||||
|
godebug: "tlsmaxrsasize=8193",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
if tc.godebug != "" {
|
||||||
|
t.Setenv("GODEBUG", tc.godebug)
|
||||||
|
}
|
||||||
|
|
||||||
c := &Conn{conn: &discardConn{}, config: testConfig.Clone()}
|
testCert, _ := pem.Decode([]byte(largeRSAKeyCertPEM))
|
||||||
|
|
||||||
expectedErr := "tls: server sent certificate containing RSA key larger than 8192 bits"
|
c := &Conn{conn: &discardConn{}, config: testConfig.Clone()}
|
||||||
err := c.verifyServerCertificate([][]byte{testCert.Bytes})
|
|
||||||
if err == nil || err.Error() != expectedErr {
|
|
||||||
t.Errorf("Conn.verifyServerCertificate unexpected error: want %q, got %q", expectedErr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedErr = "tls: client sent certificate containing RSA key larger than 8192 bits"
|
err := c.verifyServerCertificate([][]byte{testCert.Bytes})
|
||||||
err = c.processCertsFromClient(Certificate{Certificate: [][]byte{testCert.Bytes}})
|
if tc.expectedServerErr == "" && err != nil {
|
||||||
if err == nil || err.Error() != expectedErr {
|
t.Errorf("Conn.verifyServerCertificate unexpected error: %s", err)
|
||||||
t.Errorf("Conn.processCertsFromClient unexpected error: want %q, got %q", expectedErr, err)
|
} else if tc.expectedServerErr != "" && (err == nil || err.Error() != tc.expectedServerErr) {
|
||||||
|
t.Errorf("Conn.verifyServerCertificate unexpected error: want %q, got %q", tc.expectedServerErr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.processCertsFromClient(Certificate{Certificate: [][]byte{testCert.Bytes}})
|
||||||
|
if tc.expectedClientErr == "" && err != nil {
|
||||||
|
t.Errorf("Conn.processCertsFromClient unexpected error: %s", err)
|
||||||
|
} else if tc.expectedClientErr != "" && (err == nil || err.Error() != tc.expectedClientErr) {
|
||||||
|
t.Errorf("Conn.processCertsFromClient unexpected error: want %q, got %q", tc.expectedClientErr, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -819,9 +819,12 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
|
|||||||
c.sendAlert(alertBadCertificate)
|
c.sendAlert(alertBadCertificate)
|
||||||
return errors.New("tls: failed to parse client certificate: " + err.Error())
|
return errors.New("tls: failed to parse client certificate: " + err.Error())
|
||||||
}
|
}
|
||||||
if certs[i].PublicKeyAlgorithm == x509.RSA && certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
|
if certs[i].PublicKeyAlgorithm == x509.RSA {
|
||||||
c.sendAlert(alertBadCertificate)
|
n := certs[i].PublicKey.(*rsa.PublicKey).N.BitLen()
|
||||||
return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
|
if max, ok := checkKeySize(n); !ok {
|
||||||
|
c.sendAlert(alertBadCertificate)
|
||||||
|
return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", max)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user