crypto/tls: extract certificate validation for the client
Moved some code and added a comment in preparation for extending the TLS 1.3 client with certificate validation. No functional change.
This commit is contained in:
parent
9e25a0a25d
commit
928e35b73a
@ -350,6 +350,61 @@ func (hs *clientHandshakeState) pickCipherSuite() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processCertsFromServer takes a chain of server certificates from a
|
||||||
|
// Certificate message and verifies them.
|
||||||
|
func (hs *clientHandshakeState) processCertsFromServer(certificates [][]byte) error {
|
||||||
|
c := hs.c
|
||||||
|
certs := make([]*x509.Certificate, len(certificates))
|
||||||
|
for i, asn1Data := range certificates {
|
||||||
|
cert, err := x509.ParseCertificate(asn1Data)
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertBadCertificate)
|
||||||
|
return errors.New("tls: failed to parse certificate from server: " + err.Error())
|
||||||
|
}
|
||||||
|
certs[i] = cert
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.config.InsecureSkipVerify {
|
||||||
|
opts := x509.VerifyOptions{
|
||||||
|
Roots: c.config.RootCAs,
|
||||||
|
CurrentTime: c.config.time(),
|
||||||
|
DNSName: c.config.ServerName,
|
||||||
|
Intermediates: x509.NewCertPool(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, cert := range certs {
|
||||||
|
if i == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
opts.Intermediates.AddCert(cert)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
c.verifiedChains, err = certs[0].Verify(opts)
|
||||||
|
if err != nil {
|
||||||
|
c.sendAlert(alertBadCertificate)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.config.VerifyPeerCertificate != nil {
|
||||||
|
if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
|
||||||
|
c.sendAlert(alertBadCertificate)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch certs[0].PublicKey.(type) {
|
||||||
|
case *rsa.PublicKey, *ecdsa.PublicKey:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
c.sendAlert(alertUnsupportedCertificate)
|
||||||
|
return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.peerCertificates = certs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (hs *clientHandshakeState) doFullHandshake() error {
|
func (hs *clientHandshakeState) doFullHandshake() error {
|
||||||
c := hs.c
|
c := hs.c
|
||||||
|
|
||||||
@ -367,53 +422,9 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
|||||||
if c.handshakes == 0 {
|
if c.handshakes == 0 {
|
||||||
// If this is the first handshake on a connection, process and
|
// If this is the first handshake on a connection, process and
|
||||||
// (optionally) verify the server's certificates.
|
// (optionally) verify the server's certificates.
|
||||||
certs := make([]*x509.Certificate, len(certMsg.certificates))
|
if err := hs.processCertsFromServer(certMsg.certificates); err != nil {
|
||||||
for i, asn1Data := range certMsg.certificates {
|
return err
|
||||||
cert, err := x509.ParseCertificate(asn1Data)
|
|
||||||
if err != nil {
|
|
||||||
c.sendAlert(alertBadCertificate)
|
|
||||||
return errors.New("tls: failed to parse certificate from server: " + err.Error())
|
|
||||||
}
|
|
||||||
certs[i] = cert
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.config.InsecureSkipVerify {
|
|
||||||
opts := x509.VerifyOptions{
|
|
||||||
Roots: c.config.RootCAs,
|
|
||||||
CurrentTime: c.config.time(),
|
|
||||||
DNSName: c.config.ServerName,
|
|
||||||
Intermediates: x509.NewCertPool(),
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, cert := range certs {
|
|
||||||
if i == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
opts.Intermediates.AddCert(cert)
|
|
||||||
}
|
|
||||||
c.verifiedChains, err = certs[0].Verify(opts)
|
|
||||||
if err != nil {
|
|
||||||
c.sendAlert(alertBadCertificate)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.config.VerifyPeerCertificate != nil {
|
|
||||||
if err := c.config.VerifyPeerCertificate(certMsg.certificates, c.verifiedChains); err != nil {
|
|
||||||
c.sendAlert(alertBadCertificate)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch certs[0].PublicKey.(type) {
|
|
||||||
case *rsa.PublicKey, *ecdsa.PublicKey:
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
c.sendAlert(alertUnsupportedCertificate)
|
|
||||||
return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.peerCertificates = certs
|
|
||||||
} else {
|
} else {
|
||||||
// This is a renegotiation handshake. We require that the
|
// This is a renegotiation handshake. We require that the
|
||||||
// server's identity (i.e. leaf certificate) is unchanged and
|
// server's identity (i.e. leaf certificate) is unchanged and
|
||||||
|
Loading…
Reference in New Issue
Block a user