Skip to content

Commit 095cfba

Browse files
rolandshoemakergopherbot
authored andcommitted
[release-branch.go1.20] 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 #61966 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/+/518555 Auto-Submit: Dmitri Shuralyov <[email protected]>
1 parent 1a91bb9 commit 095cfba

File tree

4 files changed

+68
-19
lines changed

4 files changed

+68
-19
lines changed

src/crypto/tls/conn.go

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

src/crypto/tls/handshake_client.go

+21-5
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import (
1717
"errors"
1818
"fmt"
1919
"hash"
20+
"internal/godebug"
2021
"io"
2122
"net"
23+
"strconv"
2224
"strings"
2325
"time"
2426
)
@@ -857,9 +859,20 @@ 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+
var tlsmaxrsasize = godebug.New("tlsmaxrsasize")
867+
868+
func checkKeySize(n int) (max int, ok bool) {
869+
if v := tlsmaxrsasize.Value(); v != "" {
870+
if max, err := strconv.Atoi(v); err == nil {
871+
return max, n <= max
872+
}
873+
}
874+
return defaultMaxRSAKeySize, n <= defaultMaxRSAKeySize
875+
}
863876

864877
// verifyServerCertificate parses and verifies the provided chain, setting
865878
// c.verifiedChains and c.peerCertificates or sending the appropriate alert.
@@ -872,9 +885,12 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
872885
c.sendAlert(alertBadCertificate)
873886
return errors.New("tls: failed to parse certificate from server: " + err.Error())
874887
}
875-
if cert.cert.PublicKeyAlgorithm == x509.RSA && cert.cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
876-
c.sendAlert(alertBadCertificate)
877-
return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
888+
if cert.cert.PublicKeyAlgorithm == x509.RSA {
889+
n := cert.cert.PublicKey.(*rsa.PublicKey).N.BitLen()
890+
if max, ok := checkKeySize(n); !ok {
891+
c.sendAlert(alertBadCertificate)
892+
return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", max)
893+
}
878894
}
879895
activeHandles[i] = cert
880896
certs[i] = cert.cert

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
@@ -818,9 +818,12 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
818818
c.sendAlert(alertBadCertificate)
819819
return errors.New("tls: failed to parse client certificate: " + err.Error())
820820
}
821-
if certs[i].PublicKeyAlgorithm == x509.RSA && certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
822-
c.sendAlert(alertBadCertificate)
823-
return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
821+
if certs[i].PublicKeyAlgorithm == x509.RSA {
822+
n := certs[i].PublicKey.(*rsa.PublicKey).N.BitLen()
823+
if max, ok := checkKeySize(n); !ok {
824+
c.sendAlert(alertBadCertificate)
825+
return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", max)
826+
}
824827
}
825828
}
826829

0 commit comments

Comments
 (0)