1
0
mirror of https://github.com/golang/go synced 2024-11-26 19:51:17 -07:00

crypto/tls: use certificate cache in client

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>
This commit is contained in:
Roland Shoemaker 2022-08-29 09:40:50 -07:00
parent 601ad2e457
commit 72ce9ba9cb
3 changed files with 10 additions and 2 deletions

View 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.

View 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

View 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 {