]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: use certificate cache in client
authorRoland Shoemaker <roland@golang.org>
Mon, 29 Aug 2022 16:40:50 +0000 (09:40 -0700)
committerRoland Shoemaker <roland@golang.org>
Mon, 7 Nov 2022 19:47:10 +0000 (19:47 +0000)
In verifyServerCertificate parse certificates using the global
certificate cache.

This should signficiantly reduce memory usage in TLS clients which make
concurrent connections which reuse certificates (anywhere in the chain)
since there will only ever be one copy of the certificate at once.

Fixes #46035

Change-Id: Icf5153d0ea3c14a0bdc8b26c794f21153bf95f85
Reviewed-on: https://go-review.googlesource.com/c/go/+/426455
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
src/crypto/tls/cache.go
src/crypto/tls/conn.go
src/crypto/tls/handshake_client.go

index aa44173c801ce83a015ae7280cef1dcaf843b857..2bdf2d9a011df9a9ca2972e0909bd3b0557ec67e 100644 (file)
@@ -39,6 +39,8 @@ type certCache struct {
        sync.Map
 }
 
+var clientCertCache = new(certCache)
+
 // activeCert is a handle to a certificate held in the cache. Once there are
 // no alive activeCerts for a given certificate, the certificate is removed
 // from the cache by a finalizer.
index 21f693995e0baf6eb200d56bcc94564be05d4f55..03c72633be1fd8defb51c0bf5aa7e1210bd8e800 100644 (file)
@@ -49,6 +49,9 @@ type Conn struct {
        ocspResponse     []byte   // stapled OCSP response
        scts             [][]byte // signed certificate timestamps from server
        peerCertificates []*x509.Certificate
+       // activeCertHandles contains the cache handles to certificates in
+       // peerCertificates that are used to track active references.
+       activeCertHandles []*activeCert
        // verifiedChains contains the certificate chains that we built, as
        // opposed to the ones presented by the server.
        verifiedChains [][]*x509.Certificate
index 721143cb7567f50b80e527f2d4a87f2a6d708c18..2e3b693199620a3938499a3e0dbb5f89b02614c4 100644 (file)
@@ -849,14 +849,16 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
 // 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 {
+       activeHandles := make([]*activeCert, len(certificates))
        certs := make([]*x509.Certificate, len(certificates))
        for i, asn1Data := range certificates {
-               cert, err := x509.ParseCertificate(asn1Data)
+               cert, err := clientCertCache.newCert(asn1Data)
                if err != nil {
                        c.sendAlert(alertBadCertificate)
                        return errors.New("tls: failed to parse certificate from server: " + err.Error())
                }
-               certs[i] = cert
+               activeHandles[i] = cert
+               certs[i] = cert.cert
        }
 
        if !c.config.InsecureSkipVerify {
@@ -886,6 +888,7 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
                return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
        }
 
+       c.activeCertHandles = activeHandles
        c.peerCertificates = certs
 
        if c.config.VerifyPeerCertificate != nil {