From 979284f821a1fb94586d6f0c40a255de94e6997c Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Sat, 14 Oct 2023 09:56:35 -0400 Subject: [PATCH] crypto/tls: restrict RSA keys in certificates to <= 8192 bits Extremely large RSA keys in certificate chains can cause a client/server to expend significant CPU time verifying signatures. Limit this by restricting the size of RSA keys transmitted during handshakes to <= 8192 bits. Based on a survey of publicly trusted RSA keys, there are currently only three certificates in circulation with keys larger than this, and all three appear to be test certificates that are not actively deployed. It is possible there are larger keys in use in private PKIs, but we target the web PKI, so causing breakage here in the interests of increasing the default safety of users of crypto/tls seems reasonable. Thanks to Mateusz Poliwczak for reporting this issue. Fixes #61460 Fixes CVE-2023-29409 Change-Id: Ie35038515a649199a36a12fc2c5df3af855dca6c Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1912161 Reviewed-by: Damien Neil Reviewed-by: Tatiana Bradley Run-TryBot: Roland Shoemaker Reviewed-on: https://go-review.googlesource.com/c/go/+/515257 TryBot-Result: Gopher Robot Auto-Submit: David Chase Run-TryBot: David Chase --- handshake_client.go | 8 ++++++++ handshake_server.go | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/handshake_client.go b/handshake_client.go index 57e622f..c35e8ee 100644 --- a/handshake_client.go +++ b/handshake_client.go @@ -936,6 +936,10 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error { return nil } +// maxRSAKeySize is the maximum RSA key size in bits that we are willing +// to verify the signatures of during a TLS handshake. +const maxRSAKeySize = 8192 + // verifyServerCertificate parses and verifies the provided chain, setting // c.verifiedChains and c.peerCertificates or sending the appropriate alert. func (c *Conn) verifyServerCertificate(certificates [][]byte) error { @@ -947,6 +951,10 @@ 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) + } activeHandles[i] = cert certs[i] = cert.cert } diff --git a/handshake_server.go b/handshake_server.go index 1c3d74a..5915e31 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -864,6 +864,10 @@ 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 len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {