Commit 106db71f authored by Filippo Valsorda's avatar Filippo Valsorda

crypto/tls: implement TLS 1.3 client authentication

Note that the SignatureSchemes passed to GetClientCertificate in TLS 1.2
are now filtered by the requested certificate type. This feels like an
improvement anyway, and the full list can be surfaced as well when
support for signature_algorithms_cert is added, which actually matches
the semantics of the CertificateRequest signature_algorithms in TLS 1.2.

Also, note a subtle behavior change in server side resumption: if a
certificate is requested but not required, and the resumed session did
not include one, it used not to invoke VerifyPeerCertificate. However,
if the resumed session did include a certificate, it would. (If a
certificate was required but not in the session, the session is rejected
in checkForResumption.) This inconsistency could be unexpected, even
dangerous, so now VerifyPeerCertificate is always invoked. Still not
consistent with the client behavior, which does not ever invoke
VerifyPeerCertificate on resumption, but it felt too surprising to
entirely change either.

Updates #9671

Change-Id: Ib2b0dbc30e659208dca3ac07d6c687a407d7aaaf
Reviewed-on: https://go-review.googlesource.com/c/147599Reviewed-by: 's avatarAdam Langley <agl@golang.org>
parent 6435d0cf
......@@ -92,6 +92,7 @@ const (
extensionSupportedVersions uint16 = 43
extensionCookie uint16 = 44
extensionPSKModes uint16 = 45
extensionCertificateAuthorities uint16 = 47
extensionSignatureAlgorithmsCert uint16 = 50
extensionKeyShare uint16 = 51
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
......
......@@ -57,8 +57,8 @@ type Conn struct {
secureRenegotiation bool
// ekm is a closure for exporting keying material.
ekm func(label string, context []byte, length int) ([]byte, error)
// resumptionSecret is the resumption_master_secret for generating or
// handling NewSessionTicket messages. nil if config.SessionTicketsDisabled.
// resumptionSecret is the resumption_master_secret for handling
// NewSessionTicket messages. nil if config.SessionTicketsDisabled.
resumptionSecret []byte
// clientFinishedIsFirst is true if the client sent the first Finished
......
......@@ -519,7 +519,8 @@ func (hs *clientHandshakeState) doFullHandshake() error {
certRequested = true
hs.finishedHash.Write(certReq.marshal())
if chainToSend, err = hs.getCertificate(certReq); err != nil {
cri := certificateRequestInfoFromMsg(certReq)
if chainToSend, err = c.getClientCertificate(cri); err != nil {
c.sendAlert(alertInternalError)
return err
}
......@@ -863,20 +864,15 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
// tls11SignatureSchemes contains the signature schemes that we synthesise for
// a TLS <= 1.1 connection, based on the supported certificate types.
var tls11SignatureSchemes = []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1}
const (
// tls11SignatureSchemesNumECDSA is the number of initial elements of
// tls11SignatureSchemes that use ECDSA.
tls11SignatureSchemesNumECDSA = 3
// tls11SignatureSchemesNumRSA is the number of trailing elements of
// tls11SignatureSchemes that use RSA.
tls11SignatureSchemesNumRSA = 4
var (
tls11SignatureSchemes = []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1}
tls11SignatureSchemesECDSA = tls11SignatureSchemes[:3]
tls11SignatureSchemesRSA = tls11SignatureSchemes[3:]
)
func (hs *clientHandshakeState) getCertificate(certReq *certificateRequestMsg) (*Certificate, error) {
c := hs.c
// certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS
// <= 1.2 CertificateRequest, making an effort to fill in missing information.
func certificateRequestInfoFromMsg(certReq *certificateRequestMsg) *CertificateRequestInfo {
var rsaAvail, ecdsaAvail bool
for _, certType := range certReq.certificateTypes {
switch certType {
......@@ -887,77 +883,84 @@ func (hs *clientHandshakeState) getCertificate(certReq *certificateRequestMsg) (
}
}
if c.config.GetClientCertificate != nil {
var signatureSchemes []SignatureScheme
if !certReq.hasSignatureAlgorithm {
// Prior to TLS 1.2, the signature schemes were not
// included in the certificate request message. In this
// case we use a plausible list based on the acceptable
// certificate types.
signatureSchemes = tls11SignatureSchemes
if !ecdsaAvail {
signatureSchemes = signatureSchemes[tls11SignatureSchemesNumECDSA:]
cri := &CertificateRequestInfo{
AcceptableCAs: certReq.certificateAuthorities,
}
if !certReq.hasSignatureAlgorithm {
// Prior to TLS 1.2, the signature schemes were not
// included in the certificate request message. In this
// case we use a plausible list based on the acceptable
// certificate types.
switch {
case rsaAvail && ecdsaAvail:
cri.SignatureSchemes = tls11SignatureSchemes
case rsaAvail:
cri.SignatureSchemes = tls11SignatureSchemesRSA
case ecdsaAvail:
cri.SignatureSchemes = tls11SignatureSchemesECDSA
}
return cri
}
// In TLS 1.2, the signature schemes apply to both the certificate chain and
// the leaf key, while the certificate types only apply to the leaf key.
// See RFC 5246, Section 7.4.4 (where it calls this "somewhat complicated").
// Filter the signature schemes based on the certificate type.
cri.SignatureSchemes = make([]SignatureScheme, 0, len(certReq.supportedSignatureAlgorithms))
for _, sigScheme := range certReq.supportedSignatureAlgorithms {
switch signatureFromSignatureScheme(sigScheme) {
case signatureECDSA:
if ecdsaAvail {
cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme)
}
if !rsaAvail {
signatureSchemes = signatureSchemes[:len(signatureSchemes)-tls11SignatureSchemesNumRSA]
case signatureRSAPSS, signaturePKCS1v15:
if rsaAvail {
cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme)
}
} else {
signatureSchemes = certReq.supportedSignatureAlgorithms
}
return c.config.GetClientCertificate(&CertificateRequestInfo{
AcceptableCAs: certReq.certificateAuthorities,
SignatureSchemes: signatureSchemes,
})
}
// RFC 4346 on the certificateAuthorities field: A list of the
// distinguished names of acceptable certificate authorities.
// These distinguished names may specify a desired
// distinguished name for a root CA or for a subordinate CA;
// thus, this message can be used to describe both known roots
// and a desired authorization space. If the
// certificate_authorities list is empty then the client MAY
// send any certificate of the appropriate
// ClientCertificateType, unless there is some external
// arrangement to the contrary.
return cri
}
func (c *Conn) getClientCertificate(cri *CertificateRequestInfo) (*Certificate, error) {
if c.config.GetClientCertificate != nil {
return c.config.GetClientCertificate(cri)
}
// We need to search our list of client certs for one
// where SignatureAlgorithm is acceptable to the server and the
// Issuer is in certReq.certificateAuthorities
findCert:
// Issuer is in AcceptableCAs.
for i, chain := range c.config.Certificates {
if !rsaAvail && !ecdsaAvail {
sigOK := false
for _, alg := range signatureSchemesForCertificate(&chain) {
if isSupportedSignatureAlgorithm(alg, cri.SignatureSchemes) {
sigOK = true
break
}
}
if !sigOK {
continue
}
if len(cri.AcceptableCAs) == 0 {
return &chain, nil
}
for j, cert := range chain.Certificate {
x509Cert := chain.Leaf
// parse the certificate if this isn't the leaf
// node, or if chain.Leaf was nil
// Parse the certificate if this isn't the leaf node, or if
// chain.Leaf was nil.
if j != 0 || x509Cert == nil {
var err error
if x509Cert, err = x509.ParseCertificate(cert); err != nil {
c.sendAlert(alertInternalError)
return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
return nil, errors.New("tls: failed to parse configured certificate chain #" + strconv.Itoa(i) + ": " + err.Error())
}
}
switch {
case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
default:
continue findCert
}
if len(certReq.certificateAuthorities) == 0 {
// they gave us an empty list, so just take the
// first cert from c.config.Certificates
return &chain, nil
}
for _, ca := range certReq.certificateAuthorities {
for _, ca := range cri.AcceptableCAs {
if bytes.Equal(x509Cert.RawIssuer, ca) {
return &chain, nil
}
......
......@@ -777,6 +777,7 @@ func TestHandshakeClientCertRSA(t *testing.T) {
runClientTestTLS10(t, test)
runClientTestTLS12(t, test)
runClientTestTLS13(t, test)
test = &clientTest{
name: "ClientCert-RSA-AES256-GCM-SHA384",
......@@ -802,6 +803,7 @@ func TestHandshakeClientCertECDSA(t *testing.T) {
runClientTestTLS10(t, test)
runClientTestTLS12(t, test)
runClientTestTLS13(t, test)
test = &clientTest{
name: "ClientCert-ECDSA-ECDSA",
......@@ -843,6 +845,7 @@ func TestHandshakeClientCertRSAPSS(t *testing.T) {
}
runClientTestTLS12(t, test)
runClientTestTLS13(t, test)
}
func TestHandshakeClientCertRSAPKCS1v15(t *testing.T) {
......@@ -917,6 +920,9 @@ func testResumption(t *testing.T, version uint16) {
ticketKey := clientConfig.ClientSessionCache.(*lruSessionCache).q.Front().Value.(*lruSessionCacheEntry).sessionKey
clientConfig.ClientSessionCache.Put(ticketKey, nil)
}
corruptTicket := func() {
clientConfig.ClientSessionCache.(*lruSessionCache).q.Front().Value.(*lruSessionCacheEntry).state.masterSecret[0] ^= 0xff
}
randomKey := func() [32]byte {
var k [32]byte
if _, err := io.ReadFull(serverConfig.rand(), k[:]); err != nil {
......@@ -978,21 +984,18 @@ func testResumption(t *testing.T, version uint16) {
serverConfig.ClientAuth = RequireAndVerifyClientCert
clientConfig.Certificates = serverConfig.Certificates
testResumeState("InitialHandshake", false)
if version != VersionTLS13 {
// TODO(filippo): reenable when client authentication is implemented
testResumeState("WithClientCertificates", true)
// Tickets should be removed from the session cache on TLS handshake failure
farFuture := func() time.Time { return time.Unix(16725225600, 0) }
serverConfig.Time = farFuture
_, _, err = testHandshake(t, clientConfig, serverConfig)
if err == nil {
t.Fatalf("handshake did not fail after client certificate expiry")
}
serverConfig.Time = nil
testResumeState("AfterHandshakeFailure", false)
serverConfig.ClientAuth = NoClientCert
testResumeState("WithClientCertificates", true)
serverConfig.ClientAuth = NoClientCert
// Tickets should be removed from the session cache on TLS handshake
// failure, and the client should recover from a corrupted PSK
testResumeState("FetchTicketToCorrupt", false)
corruptTicket()
_, _, err = testHandshake(t, clientConfig, serverConfig)
if err == nil {
t.Fatalf("handshake did not fail with a corrupted client secret")
}
testResumeState("AfterHandshakeFailure", false)
clientConfig.ClientSessionCache = nil
testResumeState("WithoutSessionCache", false)
......@@ -1415,6 +1418,11 @@ func TestServerSelectingUnconfiguredCipherSuite(t *testing.T) {
}
func TestVerifyPeerCertificate(t *testing.T) {
t.Run("TLSv12", func(t *testing.T) { testVerifyPeerCertificate(t, VersionTLS12) })
t.Run("TLSv13", func(t *testing.T) { testVerifyPeerCertificate(t, VersionTLS13) })
}
func testVerifyPeerCertificate(t *testing.T, version uint16) {
issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
if err != nil {
panic(err)
......@@ -1548,6 +1556,7 @@ func TestVerifyPeerCertificate(t *testing.T) {
config.ClientAuth = RequireAndVerifyClientCert
config.ClientCAs = rootCAs
config.Time = now
config.MaxVersion = version
test.configureServer(config, &serverCalled)
err = Server(s, config).Handshake()
......@@ -1559,6 +1568,7 @@ func TestVerifyPeerCertificate(t *testing.T) {
config.ServerName = "example.golang"
config.RootCAs = rootCAs
config.Time = now
config.MaxVersion = version
test.configureClient(config, &clientCalled)
clientErr := Client(c, config).Handshake()
c.Close()
......@@ -1757,13 +1767,6 @@ func TestHandshakeRace(t *testing.T) {
}
}
func TestTLS11SignatureSchemes(t *testing.T) {
expected := tls11SignatureSchemesNumECDSA + tls11SignatureSchemesNumRSA
if expected != len(tls11SignatureSchemes) {
t.Errorf("expected to find %d TLS 1.1 signature schemes, but found %d", expected, len(tls11SignatureSchemes))
}
}
var getClientCertificateTests = []struct {
setup func(*Config, *Config)
expectedClientError string
......@@ -1846,6 +1849,11 @@ var getClientCertificateTests = []struct {
}
func TestGetClientCertificate(t *testing.T) {
t.Run("TLSv12", func(t *testing.T) { testGetClientCertificate(t, VersionTLS12) })
t.Run("TLSv13", func(t *testing.T) { testGetClientCertificate(t, VersionTLS13) })
}
func testGetClientCertificate(t *testing.T, version uint16) {
issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
if err != nil {
panic(err)
......@@ -1858,8 +1866,10 @@ func TestGetClientCertificate(t *testing.T) {
serverConfig.RootCAs.AddCert(issuer)
serverConfig.ClientCAs = serverConfig.RootCAs
serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) }
serverConfig.MaxVersion = version
clientConfig := testConfig.Clone()
clientConfig.MaxVersion = version
test.setup(clientConfig, serverConfig)
......
......@@ -8,7 +8,9 @@ import (
"bytes"
"crypto"
"crypto/hmac"
"crypto/rsa"
"errors"
"fmt"
"hash"
"sync/atomic"
"time"
......@@ -447,7 +449,7 @@ func (hs *clientHandshakeStateTLS13) readServerCertificate() error {
}
// See RFC 8446, Section 4.4.3.
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, hs.hello.supportedSignatureAlgorithms) {
if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid certificate signature algorithm")
}
......@@ -521,11 +523,81 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() error {
}
func (hs *clientHandshakeStateTLS13) sendClientCertificate() error {
c := hs.c
if hs.certReq == nil {
return nil
}
return errors.New("tls: TLS 1.3 client authentication unimplemented") // TODO(filippo)
cert, err := c.getClientCertificate(&CertificateRequestInfo{
AcceptableCAs: hs.certReq.certificateAuthorities,
SignatureSchemes: hs.certReq.supportedSignatureAlgorithms,
})
if err != nil {
return err
}
certMsg := new(certificateMsgTLS13)
certMsg.certificate = *cert
certMsg.scts = hs.certReq.scts && len(cert.SignedCertificateTimestamps) > 0
certMsg.ocspStapling = hs.certReq.ocspStapling && len(cert.OCSPStaple) > 0
hs.transcript.Write(certMsg.marshal())
if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
return err
}
// If the client is sending an empty certificate message, skip the CertificateVerify.
if len(cert.Certificate) == 0 {
return nil
}
certVerifyMsg := new(certificateVerifyMsg)
certVerifyMsg.hasSignatureAlgorithm = true
supportedAlgs := signatureSchemesForCertificate(cert)
if supportedAlgs == nil {
c.sendAlert(alertInternalError)
return fmt.Errorf("tls: unsupported certificate key (%T)", cert.PrivateKey)
}
// Pick signature scheme in server preference order, as the client
// preference order is not configurable.
for _, preferredAlg := range hs.certReq.supportedSignatureAlgorithms {
if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) {
certVerifyMsg.signatureAlgorithm = preferredAlg
break
}
}
sigType := signatureFromSignatureScheme(certVerifyMsg.signatureAlgorithm)
sigHash, err := hashFromSignatureScheme(certVerifyMsg.signatureAlgorithm)
if sigType == 0 || err != nil {
// getClientCertificate returned a certificate incompatible with the
// CertificateRequestInfo supported signature algorithms.
c.sendAlert(alertInternalError)
return err
}
h := sigHash.New()
writeSignedMessage(h, clientSignatureContext, hs.transcript)
signOpts := crypto.SignerOpts(sigHash)
if sigType == signatureRSAPSS {
signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash}
}
sig, err := cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), h.Sum(nil), signOpts)
if err != nil {
c.sendAlert(alertInternalError)
return errors.New("tls: failed to sign handshake: " + err.Error())
}
certVerifyMsg.signature = sig
hs.transcript.Write(certVerifyMsg.marshal())
if _, err := c.writeRecord(recordTypeHandshake, certVerifyMsg.marshal()); err != nil {
return err
}
return nil
}
func (hs *clientHandshakeStateTLS13) sendClientFinished() error {
......
......@@ -1071,6 +1071,7 @@ type certificateRequestMsgTLS13 struct {
scts bool
supportedSignatureAlgorithms []SignatureScheme
supportedSignatureAlgorithmsCert []SignatureScheme
certificateAuthorities [][]byte
}
func (m *certificateRequestMsgTLS13) marshal() []byte {
......@@ -1119,6 +1120,18 @@ func (m *certificateRequestMsgTLS13) marshal() []byte {
})
})
}
if len(m.certificateAuthorities) > 0 {
b.AddUint16(extensionCertificateAuthorities)
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
for _, ca := range m.certificateAuthorities {
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
b.AddBytes(ca)
})
}
})
})
}
})
})
......@@ -1177,6 +1190,18 @@ func (m *certificateRequestMsgTLS13) unmarshal(data []byte) bool {
m.supportedSignatureAlgorithmsCert = append(
m.supportedSignatureAlgorithmsCert, SignatureScheme(sigAndAlg))
}
case extensionCertificateAuthorities:
var auths cryptobyte.String
if !extData.ReadUint16LengthPrefixed(&auths) || auths.Empty() {
return false
}
for !auths.Empty() {
var ca []byte
if !readUint16LengthPrefixed(&auths, &ca) || len(ca) == 0 {
return false
}
m.certificateAuthorities = append(m.certificateAuthorities, ca)
}
default:
// Ignore unknown extensions.
continue
......
......@@ -391,6 +391,12 @@ func (*certificateRequestMsgTLS13) Generate(rand *rand.Rand, size int) reflect.V
if rand.Intn(10) > 5 {
m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
}
if rand.Intn(10) > 5 {
m.certificateAuthorities = make([][]byte, 3)
for i := 0; i < 3; i++ {
m.certificateAuthorities[i] = randomBytes(rand.Intn(10)+1, rand)
}
}
return reflect.ValueOf(m)
}
......
......@@ -19,19 +19,18 @@ import (
// serverHandshakeState contains details of a server handshake in progress.
// It's discarded once the handshake has completed.
type serverHandshakeState struct {
c *Conn
clientHello *clientHelloMsg
hello *serverHelloMsg
suite *cipherSuite
ellipticOk bool
ecdsaOk bool
rsaDecryptOk bool
rsaSignOk bool
sessionState *sessionState
finishedHash finishedHash
masterSecret []byte
certsFromClient [][]byte
cert *Certificate
c *Conn
clientHello *clientHelloMsg
hello *serverHelloMsg
suite *cipherSuite
ellipticOk bool
ecdsaOk bool
rsaDecryptOk bool
rsaSignOk bool
sessionState *sessionState
finishedHash finishedHash
masterSecret []byte
cert *Certificate
}
// serverHandshake performs a TLS handshake as a server.
......@@ -383,10 +382,10 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
return err
}
if len(hs.sessionState.certificates) > 0 {
if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
return err
}
if err := c.processCertsFromClient(Certificate{
Certificate: hs.sessionState.certificates,
}); err != nil {
return err
}
hs.masterSecret = hs.sessionState.masterSecret
......@@ -488,29 +487,24 @@ func (hs *serverHandshakeState) doFullHandshake() error {
return err
}
var ok bool
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
if c.config.ClientAuth >= RequestClientCert {
if certMsg, ok = msg.(*certificateMsg); !ok {
certMsg, ok := msg.(*certificateMsg)
if !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certMsg, msg)
}
hs.finishedHash.Write(certMsg.marshal())
if len(certMsg.certificates) == 0 {
// The client didn't actually send a certificate
switch c.config.ClientAuth {
case RequireAnyClientCert, RequireAndVerifyClientCert:
c.sendAlert(alertBadCertificate)
return errors.New("tls: client didn't provide a certificate")
}
}
pub, err = hs.processCertsFromClient(certMsg.certificates)
if err != nil {
if err := c.processCertsFromClient(Certificate{
Certificate: certMsg.certificates,
}); err != nil {
return err
}
if len(certMsg.certificates) != 0 {
pub = c.peerCertificates[0].PublicKey
}
msg, err = c.readHandshake()
if err != nil {
......@@ -654,13 +648,17 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
c := hs.c
m := new(newSessionTicketMsg)
var err error
var certsFromClient [][]byte
for _, cert := range c.peerCertificates {
certsFromClient = append(certsFromClient, cert.Raw)
}
state := sessionState{
vers: c.vers,
cipherSuite: hs.suite.id,
masterSecret: hs.masterSecret,
certificates: hs.certsFromClient,
certificates: certsFromClient,
}
var err error
m.ticket, err = c.encryptTicket(state.marshal())
if err != nil {
return err
......@@ -697,19 +695,22 @@ func (hs *serverHandshakeState) sendFinished(out []byte) error {
// 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.
func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
c := hs.c
hs.certsFromClient = certificates
func (c *Conn) processCertsFromClient(certificate Certificate) error {
certificates := certificate.Certificate
certs := make([]*x509.Certificate, len(certificates))
var err error
for i, asn1Data := range certificates {
if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
c.sendAlert(alertBadCertificate)
return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
return errors.New("tls: failed to parse client certificate: " + err.Error())
}
}
if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {
c.sendAlert(alertBadCertificate)
return errors.New("tls: client didn't provide a certificate")
}
if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
opts := x509.VerifyOptions{
Roots: c.config.ClientCAs,
......@@ -725,7 +726,7 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c
chains, err := certs[0].Verify(opts)
if err != nil {
c.sendAlert(alertBadCertificate)
return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
return errors.New("tls: failed to verify client's certificate: " + err.Error())
}
c.verifiedChains = chains
......@@ -734,24 +735,25 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c
if c.config.VerifyPeerCertificate != nil {
if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
c.sendAlert(alertBadCertificate)
return nil, err
return err
}
}
if len(certs) == 0 {
return nil, nil
return nil
}
var pub crypto.PublicKey
switch key := certs[0].PublicKey.(type) {
switch certs[0].PublicKey.(type) {
case *ecdsa.PublicKey, *rsa.PublicKey:
pub = key
default:
c.sendAlert(alertUnsupportedCertificate)
return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
return fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
}
c.peerCertificates = certs
return pub, nil
c.ocspResponse = certificate.OCSPStaple
c.scts = certificate.SignedCertificateTimestamps
return nil
}
// setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState
......
......@@ -1368,6 +1368,7 @@ func TestClientAuth(t *testing.T) {
config: config,
}
runServerTestTLS12(t, test)
runServerTestTLS13(t, test)
test = &serverTest{
name: "ClientAuthRequestedAndGiven",
......@@ -1377,6 +1378,7 @@ func TestClientAuth(t *testing.T) {
expectedPeerCerts: []string{clientCertificatePEM},
}
runServerTestTLS12(t, test)
runServerTestTLS13(t, test)
test = &serverTest{
name: "ClientAuthRequestedAndECDSAGiven",
......@@ -1386,6 +1388,7 @@ func TestClientAuth(t *testing.T) {
expectedPeerCerts: []string{clientECDSACertificatePEM},
}
runServerTestTLS12(t, test)
runServerTestTLS13(t, test)
test = &serverTest{
name: "ClientAuthRequestedAndPKCS1v15Given",
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
>>> Flow 1 (client to server)
00000000 16 03 01 00 e0 01 00 00 dc 03 03 d7 9c 79 99 50 |.............y.P|
00000010 c9 4b 3a e0 a1 36 a8 fc 40 bb 51 a9 71 a6 ba 2f |.K:..6..@.Q.q../|
00000020 1b ba 13 f3 b6 8b 2b 77 f1 60 27 20 a6 a3 e8 5a |......+w.`' ...Z|
00000030 4b cb 7c 64 05 b4 77 3b af 66 4b e3 5a b3 cb 57 |K.|d..w;.fK.Z..W|
00000040 84 d3 fa 5d 7f 5a cd 94 62 79 31 4a 00 08 13 02 |...].Z..by1J....|
00000050 13 03 13 01 00 ff 01 00 00 8b 00 00 00 0e 00 0c |................|
00000060 00 00 09 31 32 37 2e 30 2e 30 2e 31 00 0b 00 04 |...127.0.0.1....|
00000070 03 00 01 02 00 0a 00 0c 00 0a 00 1d 00 17 00 1e |................|
00000080 00 19 00 18 00 16 00 00 00 17 00 00 00 0d 00 1e |................|
00000090 00 1c 04 03 05 03 06 03 08 07 08 08 08 09 08 0a |................|
000000a0 08 0b 08 04 08 05 08 06 04 01 05 01 06 01 00 2b |...............+|
000000b0 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 |......-.....3.&.|
000000c0 24 00 1d 00 20 c6 c0 3a af 99 9f ef 6d 59 6b bd |$... ..:....mYk.|
000000d0 c3 b0 8a 94 02 c8 fb 13 7d cb a8 3a f4 f1 e0 40 |........}..:...@|
000000e0 03 15 7a 95 06 |..z..|
>>> Flow 2 (server to client)
00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 20 a6 a3 e8 5a |........... ...Z|
00000030 4b cb 7c 64 05 b4 77 3b af 66 4b e3 5a b3 cb 57 |K.|d..w;.fK.Z..W|
00000040 84 d3 fa 5d 7f 5a cd 94 62 79 31 4a 13 02 00 00 |...].Z..by1J....|
00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /|
00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0|
00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.|
00000080 03 03 00 01 01 17 03 03 00 17 d8 15 a1 e7 a9 00 |................|
00000090 bf 9d 8d 63 5d ba b1 5a 08 c2 de 57 7e 73 61 5d |...c]..Z...W~sa]|
000000a0 2f 17 03 03 00 3c 59 ed f4 2a 62 56 2a 02 73 4f |/....<Y..*bV*.sO|
000000b0 d8 a3 79 28 0c 5c c6 d6 da ff f7 80 d1 37 4c 93 |..y(.\.......7L.|
000000c0 7b 67 e0 6c 0f ce bc 64 3b aa 46 d7 65 b0 b0 27 |{g.l...d;.F.e..'|
000000d0 62 27 74 68 18 70 70 e4 67 f8 40 0f 83 dd 74 a8 |b'th.pp.g.@...t.|
000000e0 cf f7 17 03 03 02 6d 92 57 b1 0d 53 fa b4 f7 9e |......m.W..S....|
000000f0 43 8f a4 42 00 48 47 ce ce 30 98 19 c3 af 29 81 |C..B.HG..0....).|
00000100 3d f0 ae bd 47 89 cc 31 92 11 e1 fd b3 7f 30 68 |=...G..1......0h|
00000110 71 96 16 4e 4f ea cb 05 47 67 57 f1 fe 02 82 13 |q..NO...GgW.....|
00000120 81 df 79 7e 66 71 24 97 3d 53 89 2d 3f e4 61 c2 |..y~fq$.=S.-?.a.|
00000130 2d 79 8f 5a 9d 00 b2 2d b0 c2 55 67 61 99 1a 4c |-y.Z...-..Uga..L|
00000140 3a 1c 16 52 48 7a 94 3f 96 f8 58 4a e6 0c 6c b3 |:..RHz.?..XJ..l.|
00000150 8d 83 57 bc 74 23 3b 5b c3 89 86 e4 ce df 5e 96 |..W.t#;[......^.|
00000160 1b 29 17 4b 25 70 e5 f6 b6 e7 c1 e0 d9 37 f2 9d |.).K%p.......7..|
00000170 80 8e 48 7a f2 ad 7c c1 65 56 56 20 ce 28 37 f3 |..Hz..|.eVV .(7.|
00000180 39 5c 99 74 ba 68 d2 1f a1 51 1f 2d b5 a9 25 10 |9\.t.h...Q.-..%.|
00000190 eb c2 3d a1 84 d5 f4 86 6f 20 ba fd c6 6f 42 64 |..=.....o ...oBd|
000001a0 f5 28 2a 9f 19 58 11 40 e1 a3 c6 ae e6 92 1b 33 |.(*..X.@.......3|
000001b0 3d 69 be 86 74 f7 bf 7c 98 f6 2d 71 2d 01 b9 47 |=i..t..|..-q-..G|
000001c0 3a 7a 55 52 95 0f e8 7d 0a fe d3 32 ca 02 85 d6 |:zUR...}...2....|
000001d0 e5 7b 18 2c 9d ff a3 2c 54 b1 f3 7a 8a 6d ca 07 |.{.,...,T..z.m..|
000001e0 98 28 d0 a9 18 c3 2d 87 d2 59 80 2e f8 6a fe b1 |.(....-..Y...j..|
000001f0 0a b1 fe 9e b4 44 bb bc 9d ed 73 69 8d ea 63 cc |.....D....si..c.|
00000200 37 10 6d af bb 3f 61 ad e1 4f 26 8e 01 36 77 1c |7.m..?a..O&..6w.|
00000210 95 cd 24 d9 e2 da 01 86 16 44 ab b3 8f 98 5d cc |..$......D....].|
00000220 d8 2c b9 a4 12 26 60 5b 89 02 4a ef a9 98 7f 7c |.,...&`[..J....||
00000230 b7 f3 e2 45 b5 6d 9b f7 80 d7 ca a8 e3 15 10 d3 |...E.m..........|
00000240 b6 cd ae 27 e5 29 df 77 5d a4 34 45 af 61 7b 64 |...'.).w].4E.a{d|
00000250 03 b6 a6 59 16 c7 dc 98 6c f9 83 eb 70 e1 73 90 |...Y....l...p.s.|
00000260 2c 08 39 cb 61 86 0a 52 2d 45 96 f1 41 0e 31 d4 |,.9.a..R-E..A.1.|
00000270 de 61 54 b9 8c 8f 9b 70 60 d9 db 19 03 0a f2 14 |.aT....p`.......|
00000280 c7 ee 47 f0 2c 27 c7 a7 4f 32 b0 9d 98 b9 09 1f |..G.,'..O2......|
00000290 0e 8f 7a 55 15 9a 63 c7 7b fb 68 82 36 6c 58 55 |..zU..c.{.h.6lXU|
000002a0 b2 db 46 2b 1e 7b 87 20 be aa 7a 43 c8 71 8f e8 |..F+.{. ..zC.q..|
000002b0 f2 05 a9 8b 64 7d 5c 44 81 e9 41 14 2d cf d6 ea |....d}\D..A.-...|
000002c0 d4 0d 53 68 60 4f f5 e3 bd 24 47 7b 62 c3 f6 89 |..Sh`O...$G{b...|
000002d0 7d 3b 65 97 fc ac 60 0a de 0d 7e 31 8a 04 8e 6f |};e...`...~1...o|
000002e0 f6 c2 47 05 d2 64 f1 19 2b 89 c1 8f f8 e8 bb e1 |..G..d..+.......|
000002f0 19 d5 09 c2 b1 41 3c 0d 4f 9f 13 06 f3 02 27 1d |.....A<.O.....'.|
00000300 5d ea 22 1d 1e e0 22 34 2d f0 40 ae c0 a2 b4 1e |]."..."4-.@.....|
00000310 93 16 28 43 e1 d0 e6 ee 3b b4 51 43 bd 6f 8e b7 |..(C....;.QC.o..|
00000320 30 79 7b 29 78 17 52 a6 93 3f c7 9a de 3f fe fb |0y{)x.R..?...?..|
00000330 56 8d 2c bc 21 9e 0c a4 a2 6f 51 39 04 65 5b 81 |V.,.!....oQ9.e[.|
00000340 6e b5 4d 82 ca da 3e 13 a5 16 72 e8 c8 aa ff 34 |n.M...>...r....4|
00000350 2f 45 81 fe 17 03 03 00 99 ef 4a 43 25 8d dd 0d |/E........JC%...|
00000360 e5 af 9e e3 46 e1 84 de f1 68 5f 9b f6 70 17 6f |....F....h_..p.o|
00000370 7e 86 33 45 b6 13 f0 a8 a2 fd 08 1b 4a 4f 92 3f |~.3E........JO.?|
00000380 45 ef db 03 ff 1f 54 55 28 cc de 0e f5 6c af 5c |E.....TU(....l.\|
00000390 86 cc b1 e2 c7 0e ea 24 47 fb e0 37 e8 a2 e7 47 |.......$G..7...G|
000003a0 cd 9e da 02 e5 37 1f a9 b2 ea 57 f8 6f 63 be 5e |.....7....W.oc.^|
000003b0 38 be 1a 09 38 23 46 52 df cf 79 bc ce c1 da 23 |8...8#FR..y....#|
000003c0 34 97 c8 ce 81 74 d5 03 f4 71 ff 4b 17 e0 99 7c |4....t...q.K...||
000003d0 31 bd c9 1e d5 2b d3 d4 ff dc 56 82 07 f5 a6 57 |1....+....V....W|
000003e0 0e ab 18 cf db 38 26 ff d9 51 c2 8f 70 b8 5b 84 |.....8&..Q..p.[.|
000003f0 80 27 17 03 03 00 45 95 7b 2b 46 29 0a 03 4f c6 |.'....E.{+F)..O.|
00000400 37 0c 31 e8 72 8a aa 00 db 90 e8 d3 1f c1 e1 eb |7.1.r...........|
00000410 03 02 bc ae dd 03 a7 28 55 7e 19 0d 5f 76 e6 fa |.......(U~.._v..|
00000420 03 91 c2 5a 10 1d c0 a0 85 3d d2 32 ec 65 af 83 |...Z.....=.2.e..|
00000430 25 d1 77 0f 41 d9 e7 43 56 04 4e fe |%.w.A..CV.N.|
>>> Flow 3 (client to server)
00000000 14 03 03 00 01 01 17 03 03 00 19 6c b2 53 5f 6e |...........l.S_n|
00000010 a9 6a b2 48 da d7 d5 b2 56 81 47 a9 7d a8 5c 6d |.j.H....V.G.}.\m|
00000020 7a a8 23 db 17 03 03 00 45 88 80 32 38 19 22 fd |z.#.....E..28.".|
00000030 09 5c a2 40 50 ba 9c 34 ad 4e 4c 70 7c 4d f0 0e |.\.@P..4.NLp|M..|
00000040 68 3f da d6 c0 6e 6e 29 fa ec d8 11 2e 20 94 38 |h?...nn)..... .8|
00000050 12 b9 08 27 3c e3 0a 8f 9a da cb 1f ab c9 f5 0e |...'<...........|
00000060 da a9 8c 66 24 de 2f b2 92 22 68 53 2f 68 |...f$./.."hS/h|
>>> Flow 4 (server to client)
00000000 17 03 03 00 a3 38 95 dc 12 b1 b8 df 96 ef 91 88 |.....8..........|
00000010 d4 d5 dc 35 ec 19 32 a3 2d 90 0b d5 03 f4 b2 b9 |...5..2.-.......|
00000020 4e 5f 4d b2 18 ae 44 d6 21 f1 7f ef a2 ab 3a 60 |N_M...D.!.....:`|
00000030 df a3 f3 6c 90 68 66 12 8c 3c c2 25 13 36 6c 1d |...l.hf..<.%.6l.|
00000040 51 e7 7e 75 f1 ac 54 fd ae 1b e0 b3 03 6f 0e 96 |Q.~u..T......o..|
00000050 91 5e 88 f5 a7 b6 f0 c5 3c ec a4 e1 3a 46 cd 41 |.^......<...:F.A|
00000060 60 dc 6f 13 d0 eb 76 7e b4 46 31 0f 23 22 0f b1 |`.o...v~.F1.#"..|
00000070 c8 91 14 42 ac 67 6f 83 92 a7 5b 2c 88 16 fc cf |...B.go...[,....|
00000080 ef 97 56 2f 2b 64 92 7d 1a ae a7 94 66 5d 35 f3 |..V/+d.}....f]5.|
00000090 77 63 c2 ef 82 d7 33 6d 0e 60 b2 a3 6b 01 aa 84 |wc....3m.`..k...|
000000a0 32 d0 df 47 e1 01 52 15 17 03 03 00 1e 05 90 37 |2..G..R........7|
000000b0 26 ed e0 a9 8d b1 07 26 42 6d 77 7c 19 aa c2 56 |&......&Bmw|...V|
000000c0 f1 92 eb de 96 46 f2 25 d9 93 df 17 03 03 00 13 |.....F.%........|
000000d0 ed b0 6c 70 1e 85 32 0d 8b ef 55 32 8c d6 fe 1d |..lp..2...U2....|
000000e0 c5 b0 4f |..O|
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment