diff --git a/api/next/24673.txt b/api/next/24673.txt new file mode 100644 index 00000000000000..a3592794383f23 --- /dev/null +++ b/api/next/24673.txt @@ -0,0 +1 @@ +pkg crypto/tls, type ConnectionState struct, LocalCertificate *Certificate #24673 diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/24673.md b/doc/next/6-stdlib/99-minor/crypto/tls/24673.md new file mode 100644 index 00000000000000..2f9dd7c4f5e601 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/crypto/tls/24673.md @@ -0,0 +1,2 @@ +Make the local party's [Certificate] available via +[ConnectionState.LocalCertificate] if provided during the handshake. \ No newline at end of file diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 6fe6f34cd210d8..a1ff14cb1b539d 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -275,6 +275,13 @@ type ConnectionState struct { // PeerCertificates and its contents should not be modified. PeerCertificates []*x509.Certificate + // LocalCertificate is the local certificate sent by this side of the + // handshake. It's available both on the server and on the client side. + // May be nil if a certificate wasn't exchanged by this party in the + // handshake, e.g. a client opening a connection without providing a client + // cert. + LocalCertificate *Certificate + // VerifiedChains is a list of one or more chains where the first element is // PeerCertificates[0] and the last element is from Config.RootCAs (on the // client side) or Config.ClientCAs (on the server side). diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 09dc9ea94c939f..811c6c0af5f9c4 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -55,6 +55,7 @@ type Conn struct { ocspResponse []byte // stapled OCSP response scts [][]byte // signed certificate timestamps from server peerCertificates []*x509.Certificate + localCertificate *Certificate // verifiedChains contains the certificate chains that we built, as // opposed to the ones presented by the server. verifiedChains [][]*x509.Certificate @@ -1619,6 +1620,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/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 90c5bdacd82318..7b724b71b32474 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -834,6 +834,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { return err } } + hs.c.localCertificate = chainToSend signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash) signOpts := crypto.SignerOpts(sigHash) diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 7018bb2336b8f3..6bcd5d51246134 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -823,6 +823,7 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { if _, err := hs.c.writeHandshakeRecord(certVerifyMsg, hs.transcript); err != nil { return err } + hs.c.localCertificate = cert return nil } diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 088c66fadb2a44..3975ed6bc93547 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -283,6 +283,7 @@ func (hs *serverHandshakeState) processClientHello() error { } return err } + hs.c.localCertificate = hs.cert if hs.clientHello.scts { hs.hello.scts = hs.cert.SignedCertificateTimestamps } diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index c5b0552cae6134..835c2274fb9550 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -533,6 +533,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error { return err } hs.cert = certificate + hs.c.localCertificate = hs.cert return nil }