From 629fee87428f056f5157b4b9a504eb8463b00a09 Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Thu, 10 Sep 2026 23:08:30 -0400 Subject: [PATCH] crypto/tls: only set LocalCertificate when a certificate is presented ConnectionState.LocalCertificate is documented to be populated only for connections which are not resumed. However, the TLS 1.0-1.2 server handshake set it in processClientHello, which runs before checkForResumption, and nothing cleared it on the abbreviated handshake path. Resumed pre-1.3 server connections therefore reported a certificate chain that was never presented to the peer (also visible to VerifyConnection and WrapSession during the handshake). Set the field in doFullHandshake, where the Certificate message is actually written, so it is populated if and only if a chain was presented. TLS 1.3 is unaffected because pickCertificate already returns early for PSK resumption. Also pin MaxVersion in TestLocalCertificate and TestLocalCertificateResumption: they previously set only MinVersion, so every pre-1.3 subtest silently negotiated TLS 1.3 and the broken path had no coverage. With MaxVersion pinned, the resumption test fails without this fix at TLS 1.0-1.2. Verified: strengthened resumption test fails on unpatched master at TLS 1.0/1.1/1.2 and passes with the fix; full `go test crypto/tls` passes; standalone repro from the issue prints len(LocalCertificate)=0 for resumed TLS 1.2 connections. Fixes #79967 Change-Id: Ic5586b05da956c619526b8ef500fcaa4c019a2f3 GitHub-Last-Rev: c2ef0f1 GitHub-Pull-Request: #79968 Reviewed-on: https://go-review.googlesource.com/c/go/+/789862 Auto-Submit: Roland Shoemaker Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Reviewed-by: Roland Shoemaker --- handshake_server.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/handshake_server.go b/handshake_server.go index 020234e..4e8d531 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -281,10 +281,6 @@ func (hs *serverHandshakeState) processClientHello() error { return err } - if hs.cert != nil { - hs.c.localCertificate = hs.cert.Certificate - } - if hs.clientHello.scts { hs.hello.scts = hs.cert.SignedCertificateTimestamps } @@ -619,6 +615,10 @@ func (hs *serverHandshakeState) doFullHandshake() error { certMsg := new(certificateMsg) certMsg.certificates = hs.cert.Certificate + // Set localCertificate here, rather than at certificate selection time, so + // that it is only populated when a certificate is actually presented to the + // peer, and not on resumed connections. + c.localCertificate = hs.cert.Certificate if _, err := hs.c.writeHandshakeRecord(certMsg, &hs.finishedHash); err != nil { return err }