processCertsFromClient takes a chain of client certificates either from a Certificates message or from a sessionState and verifies them. It returns the public key of the leaf certificate.
(certificate Certificate)
| 795 | // Certificates message or from a sessionState and verifies them. It returns |
| 796 | // the public key of the leaf certificate. |
| 797 | func (c *Conn) processCertsFromClient(certificate Certificate) error { |
| 798 | certificates := certificate.Certificate |
| 799 | certs := make([]*x509.Certificate, len(certificates)) |
| 800 | var err error |
| 801 | for i, asn1Data := range certificates { |
| 802 | if certs[i], err = x509.ParseCertificate(asn1Data); err != nil { |
| 803 | c.sendAlert(alertBadCertificate) |
| 804 | return errors.New("tls: failed to parse client certificate: " + err.Error()) |
| 805 | } |
| 806 | } |
| 807 | |
| 808 | if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) { |
| 809 | c.sendAlert(alertBadCertificate) |
| 810 | return errors.New("tls: client didn't provide a certificate") |
| 811 | } |
| 812 | |
| 813 | if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 { |
| 814 | opts := x509.VerifyOptions{ |
| 815 | Roots: c.config.ClientCAs, |
| 816 | CurrentTime: c.config.time(), |
| 817 | Intermediates: x509.NewCertPool(), |
| 818 | KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, |
| 819 | } |
| 820 | |
| 821 | for _, cert := range certs[1:] { |
| 822 | opts.Intermediates.AddCert(cert) |
| 823 | } |
| 824 | |
| 825 | chains, err := certs[0].Verify(opts) |
| 826 | if err != nil { |
| 827 | c.sendAlert(alertBadCertificate) |
| 828 | return errors.New("tls: failed to verify client certificate: " + err.Error()) |
| 829 | } |
| 830 | |
| 831 | c.verifiedChains = chains |
| 832 | } |
| 833 | |
| 834 | c.peerCertificates = certs |
| 835 | c.ocspResponse = certificate.OCSPStaple |
| 836 | c.scts = certificate.SignedCertificateTimestamps |
| 837 | |
| 838 | if len(certs) > 0 { |
| 839 | switch certs[0].PublicKey.(type) { |
| 840 | case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey: |
| 841 | default: |
| 842 | c.sendAlert(alertUnsupportedCertificate) |
| 843 | return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey) |
| 844 | } |
| 845 | } |
| 846 | |
| 847 | if c.config.VerifyPeerCertificate != nil { |
| 848 | if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil { |
| 849 | c.sendAlert(alertBadCertificate) |
| 850 | return err |
| 851 | } |
| 852 | } |
| 853 | |
| 854 | return nil |
no test coverage detected