Skip to content

Commit caca5f1

Browse files
rolandshoemakergopherbot
authored andcommitted
[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 <[email protected]> Reviewed-by: Russ Cox <[email protected]> Run-TryBot: Roland Shoemaker <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/518536 Auto-Submit: Dmitri Shuralyov <[email protected]>
1 parent c08a5fa commit caca5f1

File tree

4 files changed

+66
-19
lines changed

4 files changed

+66
-19
lines changed

src/crypto/tls/conn.go

+5
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,11 @@ func (c *Conn) closeNotify() error {
14131413
//
14141414
// For control over canceling or setting a timeout on a handshake, use
14151415
// HandshakeContext or the Dialer's DialContext method instead.
1416+
//
1417+
// In order to avoid denial of service attacks, the maximum RSA key size allowed
1418+
// in certificates sent by either the TLS server or client is limited to 8192
1419+
// bits. This limit can be overridden by setting tlsmaxrsasize in the GODEBUG
1420+
// environment variable (e.g. GODEBUG=tlsmaxrsasize=4096).
14161421
func (c *Conn) Handshake() error {
14171422
return c.HandshakeContext(context.Background())
14181423
}

src/crypto/tls/handshake_client.go

+19-5
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ import (
1616
"errors"
1717
"fmt"
1818
"hash"
19+
"internal/godebug"
1920
"io"
2021
"net"
22+
"strconv"
2123
"strings"
2224
"sync/atomic"
2325
"time"
@@ -857,9 +859,18 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
857859
return nil
858860
}
859861

860-
// maxRSAKeySize is the maximum RSA key size in bits that we are willing
862+
// defaultMaxRSAKeySize is the maximum RSA key size in bits that we are willing
861863
// to verify the signatures of during a TLS handshake.
862-
const maxRSAKeySize = 8192
864+
const defaultMaxRSAKeySize = 8192
865+
866+
func checkKeySize(n int) (max int, ok bool) {
867+
if v := godebug.Get("tlsmaxrsasize"); v != "" {
868+
if max, err := strconv.Atoi(v); err == nil {
869+
return max, n <= max
870+
}
871+
}
872+
return defaultMaxRSAKeySize, n <= defaultMaxRSAKeySize
873+
}
863874

864875
// verifyServerCertificate parses and verifies the provided chain, setting
865876
// c.verifiedChains and c.peerCertificates or sending the appropriate alert.
@@ -871,9 +882,12 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
871882
c.sendAlert(alertBadCertificate)
872883
return errors.New("tls: failed to parse certificate from server: " + err.Error())
873884
}
874-
if cert.PublicKeyAlgorithm == x509.RSA && cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
875-
c.sendAlert(alertBadCertificate)
876-
return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
885+
if cert.PublicKeyAlgorithm == x509.RSA {
886+
n := cert.PublicKey.(*rsa.PublicKey).N.BitLen()
887+
if max, ok := checkKeySize(n); !ok {
888+
c.sendAlert(alertBadCertificate)
889+
return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", max)
890+
}
877891
}
878892
certs[i] = cert
879893
}

src/crypto/tls/handshake_client_test.go

+36-11
Original file line numberDiff line numberDiff line change
@@ -2678,19 +2678,44 @@ u58=
26782678
-----END CERTIFICATE-----`
26792679

26802680
func TestHandshakeRSATooBig(t *testing.T) {
2681-
testCert, _ := pem.Decode([]byte(largeRSAKeyCertPEM))
2681+
for _, tc := range []struct {
2682+
name string
2683+
godebug string
2684+
expectedServerErr string
2685+
expectedClientErr string
2686+
}{
2687+
{
2688+
name: "key too large",
2689+
expectedServerErr: "tls: server sent certificate containing RSA key larger than 8192 bits",
2690+
expectedClientErr: "tls: client sent certificate containing RSA key larger than 8192 bits",
2691+
},
2692+
{
2693+
name: "acceptable key (GODEBUG=tlsmaxrsasize=8193)",
2694+
godebug: "tlsmaxrsasize=8193",
2695+
},
2696+
} {
2697+
t.Run(tc.name, func(t *testing.T) {
2698+
if tc.godebug != "" {
2699+
t.Setenv("GODEBUG", tc.godebug)
2700+
}
26822701

2683-
c := &Conn{conn: &discardConn{}, config: testConfig.Clone()}
2702+
testCert, _ := pem.Decode([]byte(largeRSAKeyCertPEM))
26842703

2685-
expectedErr := "tls: server sent certificate containing RSA key larger than 8192 bits"
2686-
err := c.verifyServerCertificate([][]byte{testCert.Bytes})
2687-
if err == nil || err.Error() != expectedErr {
2688-
t.Errorf("Conn.verifyServerCertificate unexpected error: want %q, got %q", expectedErr, err)
2689-
}
2704+
c := &Conn{conn: &discardConn{}, config: testConfig.Clone()}
2705+
2706+
err := c.verifyServerCertificate([][]byte{testCert.Bytes})
2707+
if tc.expectedServerErr == "" && err != nil {
2708+
t.Errorf("Conn.verifyServerCertificate unexpected error: %s", err)
2709+
} else if tc.expectedServerErr != "" && (err == nil || err.Error() != tc.expectedServerErr) {
2710+
t.Errorf("Conn.verifyServerCertificate unexpected error: want %q, got %q", tc.expectedServerErr, err)
2711+
}
26902712

2691-
expectedErr = "tls: client sent certificate containing RSA key larger than 8192 bits"
2692-
err = c.processCertsFromClient(Certificate{Certificate: [][]byte{testCert.Bytes}})
2693-
if err == nil || err.Error() != expectedErr {
2694-
t.Errorf("Conn.processCertsFromClient unexpected error: want %q, got %q", expectedErr, err)
2713+
err = c.processCertsFromClient(Certificate{Certificate: [][]byte{testCert.Bytes}})
2714+
if tc.expectedClientErr == "" && err != nil {
2715+
t.Errorf("Conn.processCertsFromClient unexpected error: %s", err)
2716+
} else if tc.expectedClientErr != "" && (err == nil || err.Error() != tc.expectedClientErr) {
2717+
t.Errorf("Conn.processCertsFromClient unexpected error: want %q, got %q", tc.expectedClientErr, err)
2718+
}
2719+
})
26952720
}
26962721
}

src/crypto/tls/handshake_server.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -819,9 +819,12 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
819819
c.sendAlert(alertBadCertificate)
820820
return errors.New("tls: failed to parse client certificate: " + err.Error())
821821
}
822-
if certs[i].PublicKeyAlgorithm == x509.RSA && certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
823-
c.sendAlert(alertBadCertificate)
824-
return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
822+
if certs[i].PublicKeyAlgorithm == x509.RSA {
823+
n := certs[i].PublicKey.(*rsa.PublicKey).N.BitLen()
824+
if max, ok := checkKeySize(n); !ok {
825+
c.sendAlert(alertBadCertificate)
826+
return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", max)
827+
}
825828
}
826829
}
827830

0 commit comments

Comments
 (0)