From ed6f4f73752927d7bc677ad2e23a153b66b885a5 Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Thu, 10 Sep 2026 23:04:52 -0400 Subject: [PATCH] crypto/tls: add LocalCertificate to ConnectionState Adds a new field to ConnectionState, LocalCertificate, which contains the certificate chain which was presented to the connection peer, if one was. Fixes #24673 Change-Id: Iae758fef4a2808e3295324890f4b2f55c71fcc4c Reviewed-on: https://go-review.googlesource.com/c/go/+/788866 Auto-Submit: Roland Shoemaker Reviewed-by: Cherry Mui TryBot-Bypass: Roland Shoemaker Reviewed-by: Daniel McCarney --- common.go | 5 +++++ conn.go | 2 ++ handshake_client.go | 4 ++++ handshake_client_tls13.go | 4 ++++ handshake_server.go | 5 +++++ handshake_server_tls13.go | 3 +++ 6 files changed, 23 insertions(+) diff --git a/common.go b/common.go index ca399db..efd4f6d 100644 --- a/common.go +++ b/common.go @@ -325,6 +325,11 @@ type ConnectionState struct { // are a server, or if we received a HelloRetryRequest if we are a client. HelloRetryRequest bool + // LocalCertificate is the certificate chain presented to the peer, if any, + // during the handshake. This field is only populated for connections which + // are not resumed (DidResume is false). + LocalCertificate [][]byte + // ekm is a closure exposed via ExportKeyingMaterial. ekm func(label string, context []byte, length int) ([]byte, error) diff --git a/conn.go b/conn.go index 8ac81a6..7bfac68 100644 --- a/conn.go +++ b/conn.go @@ -60,6 +60,7 @@ type Conn struct { ocspResponse []byte // stapled OCSP response scts [][]byte // signed certificate timestamps from server peerCertificates []*x509.Certificate + localCertificate [][]byte // verifiedChains contains the certificate chains that we built, as // opposed to the ones presented by the server. verifiedChains [][]*x509.Certificate @@ -1690,6 +1691,7 @@ func (c *Conn) connectionStateLocked() ConnectionState { state.ServerName = c.serverName state.CipherSuite = c.cipherSuite state.PeerCertificates = c.peerCertificates + state.LocalCertificate = c.localCertificate state.VerifiedChains = c.verifiedChains state.SignedCertificateTimestamps = c.scts state.OCSPResponse = c.ocspResponse diff --git a/handshake_client.go b/handshake_client.go index c4140e1..3aa4ef3 100644 --- a/handshake_client.go +++ b/handshake_client.go @@ -730,6 +730,10 @@ func (hs *clientHandshakeState) doFullHandshake() error { } } + if chainToSend != nil { + hs.c.localCertificate = chainToSend.Certificate + } + shd, ok := msg.(*serverHelloDoneMsg) if !ok { c.sendAlert(alertUnexpectedMessage) diff --git a/handshake_client_tls13.go b/handshake_client_tls13.go index c15490b..d5e9d36 100644 --- a/handshake_client_tls13.go +++ b/handshake_client_tls13.go @@ -756,6 +756,10 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { return err } + if cert != nil { + hs.c.localCertificate = cert.Certificate + } + certMsg := new(certificateMsgTLS13) certMsg.certificate = *cert diff --git a/handshake_server.go b/handshake_server.go index a83a78a..020234e 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -280,6 +280,11 @@ 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 } diff --git a/handshake_server_tls13.go b/handshake_server_tls13.go index 9a5839f..454df11 100644 --- a/handshake_server_tls13.go +++ b/handshake_server_tls13.go @@ -587,6 +587,9 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error { } return err } + if certificate != nil { + hs.c.localCertificate = certificate.Certificate + } hs.sigAlg, err = selectSignatureScheme(c.vers, certificate, hs.clientHello.supportedSignatureAlgorithms) if err != nil { // getCertificate returned a certificate that is unsupported or