Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@google.com>2016-07-10 00:26:01 +0300
committerDavid Benjamin <davidben@google.com>2016-07-12 22:23:28 +0300
commit8d343b44bbab829d1a28fdef650ca95f7db4412e (patch)
tree40d6c190ba52a509d1093d434bf9b57940404dcf
parent615119a9e94093062e564d8a7ccc7013fc292048 (diff)
Implement client certificates for TLS 1.3 in Go.
Tested by having client and server talk to each other. This adds the certificate_extensions field to CertificateRequest which I'd previously missed. (We completely ignore the field, with the expectation that the C code won't have anything useful to do with it either.) Change-Id: I74f96acd36747d4b6a6f533535e36ea8e94d2be8 Reviewed-on: https://boringssl-review.googlesource.com/8710 Reviewed-by: David Benjamin <davidben@google.com>
-rw-r--r--ssl/test/runner/handshake_client.go48
-rw-r--r--ssl/test/runner/handshake_messages.go18
-rw-r--r--ssl/test/runner/handshake_server.go67
3 files changed, 121 insertions, 12 deletions
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index a67b2427..4ff70126 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -510,8 +510,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
}
var chainToSend *Certificate
- var certRequested bool
- var certRequestContext []byte
+ var certReq *certificateRequestMsg
if hs.suite.flags&suitePSK != 0 {
if encryptedExtensions.extensions.ocspResponse != nil {
c.sendAlert(alertUnsupportedExtension)
@@ -530,11 +529,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
return err
}
- certReq, ok := msg.(*certificateRequestMsg)
+ var ok bool
+ certReq, ok = msg.(*certificateRequestMsg)
if ok {
hs.writeServerHash(certReq.marshal())
- certRequested = true
- certRequestContext = certReq.requestContext
chainToSend, err = selectClientCertificate(c, certReq)
if err != nil {
@@ -602,10 +600,42 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
masterSecret := hs.finishedHash.extractKey(handshakeSecret, zeroSecret)
trafficSecret := hs.finishedHash.deriveSecret(masterSecret, applicationTrafficLabel)
- if certRequested {
- _ = chainToSend
- _ = certRequestContext
- return errors.New("tls: client auth not implemented.")
+ if certReq != nil {
+ certMsg := &certificateMsg{
+ hasRequestContext: true,
+ requestContext: certReq.requestContext,
+ }
+ if chainToSend != nil {
+ certMsg.certificates = chainToSend.Certificate
+ }
+ hs.writeClientHash(certMsg.marshal())
+ c.writeRecord(recordTypeHandshake, certMsg.marshal())
+
+ if chainToSend != nil {
+ certVerify := &certificateVerifyMsg{
+ hasSignatureAlgorithm: true,
+ }
+
+ // Determine the hash to sign.
+ privKey := chainToSend.PrivateKey
+
+ var err error
+ certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
+ if err != nil {
+ c.sendAlert(alertInternalError)
+ return err
+ }
+
+ input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
+ certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
+ if err != nil {
+ c.sendAlert(alertInternalError)
+ return err
+ }
+
+ hs.writeClientHash(certVerify.marshal())
+ c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ }
}
// Send a client Finished message.
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index baa07bd5..0df3be32 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -1461,6 +1461,11 @@ func (m *certificateRequestMsg) marshal() []byte {
caEntry.addBytes(ca)
}
+ if m.hasRequestContext {
+ // Emit no certificate extensions.
+ body.addU16(0)
+ }
+
m.raw = builder.finish()
return m.raw
}
@@ -1538,6 +1543,19 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
cas = cas[caLen:]
}
+
+ if m.hasRequestContext {
+ // Ignore certificate extensions.
+ if len(data) < 2 {
+ return false
+ }
+ extsLength := int(data[0])<<8 | int(data[1])
+ if len(data) < 2+extsLength {
+ return false
+ }
+ data = data[2+extsLength:]
+ }
+
if len(data) > 0 {
return false
}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index db0b3581..06823edf 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -406,8 +406,25 @@ Curves:
if hs.suite.flags&suitePSK == 0 {
if config.ClientAuth >= RequestClientCert {
- // TODO(davidben): Implement client auth.
- return errors.New("tls: client auth not implemented")
+ // Request a client certificate
+ certReq := &certificateRequestMsg{
+ hasSignatureAlgorithm: true,
+ hasRequestContext: true,
+ }
+ if !config.Bugs.NoSignatureAlgorithms {
+ certReq.signatureAlgorithms = config.signSignatureAlgorithms()
+ }
+
+ // An empty list of certificateAuthorities signals to
+ // the client that it may send any certificate in response
+ // to our request. When we know the CAs we trust, then
+ // we can send them down, so that the client can choose
+ // an appropriate certificate to give to us.
+ if config.ClientCAs != nil {
+ certReq.certificateAuthorities = config.ClientCAs.Subjects()
+ }
+ hs.writeServerHash(certReq.marshal())
+ c.writeRecord(recordTypeHandshake, certReq.marshal())
}
certMsg := &certificateMsg{
@@ -461,7 +478,51 @@ Curves:
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
if config.ClientAuth >= RequestClientCert {
- return errors.New("tls: client certificates not implemented")
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+
+ certMsg, ok := msg.(*certificateMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(certMsg, msg)
+ }
+ hs.writeClientHash(certMsg.marshal())
+
+ if len(certMsg.certificates) == 0 {
+ // The client didn't actually send a certificate
+ switch 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 {
+ return err
+ }
+
+ if len(c.peerCertificates) > 0 {
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
+ }
+
+ certVerify, ok := msg.(*certificateVerifyMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(certVerify, msg)
+ }
+
+ input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
+ if err := verifyMessage(c.vers, pub, config, certVerify.signatureAlgorithm, input, certVerify.signature); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return err
+ }
+ hs.writeClientHash(certVerify.marshal())
+ }
}
// Read the client Finished message.