diff --git a/conn.go b/conn.go index 9c1f06f..a12d495 100644 --- a/conn.go +++ b/conn.go @@ -1531,6 +1531,11 @@ func (c *Conn) closeNotify() error { // // For control over canceling or setting a timeout on a handshake, use // 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 { return c.HandshakeContext(context.Background()) } diff --git a/handshake_client.go b/handshake_client.go index c35e8ee..502bd88 100644 --- a/handshake_client.go +++ b/handshake_client.go @@ -936,9 +936,23 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error { 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. -const maxRSAKeySize = 8192 +const defaultMaxRSAKeySize = 8192 + +//var tlsmaxrsasize = godebug.New("tlsmaxrsasize") + +func checkKeySize(n int) (max int, ok bool) { + // if v := tlsmaxrsasize.Value(); v != "" { + // if max, err := strconv.Atoi(v); err == nil { + // if (n <= max) != (n <= defaultMaxRSAKeySize) { + // tlsmaxrsasize.IncNonDefault() + // } + // return max, n <= max + // } + // } + return defaultMaxRSAKeySize, n <= defaultMaxRSAKeySize +} // verifyServerCertificate parses and verifies the provided chain, setting // c.verifiedChains and c.peerCertificates or sending the appropriate alert. @@ -951,9 +965,12 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { c.sendAlert(alertBadCertificate) return errors.New("tls: failed to parse certificate from server: " + err.Error()) } - if cert.cert.PublicKeyAlgorithm == x509.RSA && cert.cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize { - c.sendAlert(alertBadCertificate) - return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize) + if cert.cert.PublicKeyAlgorithm == x509.RSA { + n := cert.cert.PublicKey.(*rsa.PublicKey).N.BitLen() + if max, ok := checkKeySize(n); !ok { + c.sendAlert(alertBadCertificate) + return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", max) + } } activeHandles[i] = cert certs[i] = cert.cert diff --git a/handshake_server.go b/handshake_server.go index 5915e31..bddfaba 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -864,9 +864,12 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { c.sendAlert(alertBadCertificate) 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 { - c.sendAlert(alertBadCertificate) - return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize) + if certs[i].PublicKeyAlgorithm == x509.RSA { + n := certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() + if max, ok := checkKeySize(n); !ok { + c.sendAlert(alertBadCertificate) + return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", max) + } } }