2014-06-20 20:00:00 +01:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2015-09-29 23:21:04 +01:00
|
|
|
package runner
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2016-06-21 23:19:24 +01:00
|
|
|
"crypto"
|
2014-06-20 20:00:00 +01:00
|
|
|
"crypto/ecdsa"
|
2014-08-24 06:44:23 +01:00
|
|
|
"crypto/elliptic"
|
2014-06-20 20:00:00 +01:00
|
|
|
"crypto/rsa"
|
|
|
|
"crypto/subtle"
|
|
|
|
"crypto/x509"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2014-07-18 20:03:41 +01:00
|
|
|
"math/big"
|
2014-06-20 20:00:00 +01:00
|
|
|
"net"
|
2016-07-26 00:16:28 +01:00
|
|
|
"time"
|
2017-03-29 00:28:44 +01:00
|
|
|
|
2018-09-07 20:51:08 +01:00
|
|
|
"boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519"
|
2014-06-20 20:00:00 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type clientHandshakeState struct {
|
Add DTLS timeout and retransmit tests.
This extends the packet adaptor protocol to send three commands:
type command =
| Packet of []byte
| Timeout of time.Duration
| TimeoutAck
When the shim processes a Timeout in BIO_read, it sends TimeoutAck, fails the
BIO_read, returns out of the SSL stack, advances the clock, calls
DTLSv1_handle_timeout, and continues.
If the Go side sends Timeout right between sending handshake flight N and
reading flight N+1, the shim won't read the Timeout until it has sent flight
N+1 (it only processes packet commands in BIO_read), so the TimeoutAck comes
after N+1. Go then drops all packets before the TimeoutAck, thus dropping one
transmit of flight N+1 without having to actually process the packets to
determine the end of the flight. The shim then sees the updated clock, calls
DTLSv1_handle_timeout, and re-sends flight N+1 for Go to process for real.
When dropping packets, Go checks the epoch and increments sequence numbers so
that we can continue to be strict here. This requires tracking the initial
sequence number of the next epoch.
The final Finished message takes an additional special-case to test. DTLS
triggers retransmits on either a timeout or seeing a stale flight. OpenSSL only
implements the former which should be sufficient (and is necessary) EXCEPT for
the final Finished message. If the peer's final Finished message is lost, it
won't be waiting for a message from us, so it won't time out anything. That
retransmit must be triggered on stale message, so we retransmit the Finished
message in Go.
Change-Id: I3ffbdb1de525beb2ee831b304670a3387877634c
Reviewed-on: https://boringssl-review.googlesource.com/3212
Reviewed-by: Adam Langley <agl@google.com>
2015-01-27 06:09:43 +00:00
|
|
|
c *Conn
|
|
|
|
serverHello *serverHelloMsg
|
|
|
|
hello *clientHelloMsg
|
|
|
|
suite *cipherSuite
|
|
|
|
finishedHash finishedHash
|
2016-07-01 22:50:32 +01:00
|
|
|
keyShares map[CurveID]ecdhCurve
|
Add DTLS timeout and retransmit tests.
This extends the packet adaptor protocol to send three commands:
type command =
| Packet of []byte
| Timeout of time.Duration
| TimeoutAck
When the shim processes a Timeout in BIO_read, it sends TimeoutAck, fails the
BIO_read, returns out of the SSL stack, advances the clock, calls
DTLSv1_handle_timeout, and continues.
If the Go side sends Timeout right between sending handshake flight N and
reading flight N+1, the shim won't read the Timeout until it has sent flight
N+1 (it only processes packet commands in BIO_read), so the TimeoutAck comes
after N+1. Go then drops all packets before the TimeoutAck, thus dropping one
transmit of flight N+1 without having to actually process the packets to
determine the end of the flight. The shim then sees the updated clock, calls
DTLSv1_handle_timeout, and re-sends flight N+1 for Go to process for real.
When dropping packets, Go checks the epoch and increments sequence numbers so
that we can continue to be strict here. This requires tracking the initial
sequence number of the next epoch.
The final Finished message takes an additional special-case to test. DTLS
triggers retransmits on either a timeout or seeing a stale flight. OpenSSL only
implements the former which should be sufficient (and is necessary) EXCEPT for
the final Finished message. If the peer's final Finished message is lost, it
won't be waiting for a message from us, so it won't time out anything. That
retransmit must be triggered on stale message, so we retransmit the Finished
message in Go.
Change-Id: I3ffbdb1de525beb2ee831b304670a3387877634c
Reviewed-on: https://boringssl-review.googlesource.com/3212
Reviewed-by: Adam Langley <agl@google.com>
2015-01-27 06:09:43 +00:00
|
|
|
masterSecret []byte
|
|
|
|
session *ClientSessionState
|
|
|
|
finishedBytes []byte
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2017-06-20 15:55:02 +01:00
|
|
|
func mapClientHelloVersion(vers uint16, isDTLS bool) uint16 {
|
|
|
|
if !isDTLS {
|
|
|
|
return vers
|
|
|
|
}
|
|
|
|
|
|
|
|
switch vers {
|
|
|
|
case VersionTLS12:
|
|
|
|
return VersionDTLS12
|
|
|
|
case VersionTLS10:
|
|
|
|
return VersionDTLS10
|
|
|
|
}
|
|
|
|
|
|
|
|
panic("Unknown ClientHello version.")
|
|
|
|
}
|
|
|
|
|
2018-11-19 21:49:56 +00:00
|
|
|
func fixClientHellos(hello *clientHelloMsg, in []byte) ([]byte, error) {
|
|
|
|
ret := append([]byte{}, in...)
|
|
|
|
newHello := new(clientHelloMsg)
|
|
|
|
if !newHello.unmarshal(ret) {
|
|
|
|
return nil, errors.New("tls: invalid ClientHello")
|
|
|
|
}
|
|
|
|
|
|
|
|
hello.random = newHello.random
|
|
|
|
hello.sessionId = newHello.sessionId
|
|
|
|
|
2018-11-21 20:34:51 +00:00
|
|
|
// Replace |ret|'s key shares with those of |hello|. For simplicity, we
|
|
|
|
// require their lengths match, which is satisfied by matching the
|
|
|
|
// DefaultCurves setting to the selection in the replacement
|
|
|
|
// ClientHello.
|
2018-11-19 21:49:56 +00:00
|
|
|
bb := newByteBuilder()
|
|
|
|
hello.marshalKeyShares(bb)
|
|
|
|
keyShares := bb.finish()
|
|
|
|
if len(keyShares) != len(newHello.keySharesRaw) {
|
2018-11-21 20:34:51 +00:00
|
|
|
return nil, errors.New("tls: ClientHello key share length is inconsistent with DefaultCurves setting")
|
2018-11-19 21:49:56 +00:00
|
|
|
}
|
|
|
|
// |newHello.keySharesRaw| aliases |ret|.
|
|
|
|
copy(newHello.keySharesRaw, keyShares)
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
func (c *Conn) clientHandshake() error {
|
|
|
|
if c.config == nil {
|
|
|
|
c.config = defaultConfig()
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
|
|
|
|
return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
|
|
|
|
}
|
|
|
|
|
2014-08-04 06:23:53 +01:00
|
|
|
c.sendHandshakeSeq = 0
|
|
|
|
c.recvHandshakeSeq = 0
|
|
|
|
|
2014-09-15 21:51:51 +01:00
|
|
|
nextProtosLength := 0
|
|
|
|
for _, proto := range c.config.NextProtos {
|
2015-07-09 19:35:04 +01:00
|
|
|
if l := len(proto); l > 255 {
|
2014-09-15 21:51:51 +01:00
|
|
|
return errors.New("tls: invalid NextProtos value")
|
|
|
|
} else {
|
|
|
|
nextProtosLength += 1 + l
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if nextProtosLength > 0xffff {
|
|
|
|
return errors.New("tls: NextProtos values too large")
|
|
|
|
}
|
|
|
|
|
2016-09-15 21:27:05 +01:00
|
|
|
minVersion := c.config.minVersion(c.isDTLS)
|
2016-09-26 23:30:05 +01:00
|
|
|
maxVersion := c.config.maxVersion(c.isDTLS)
|
2014-06-20 20:00:00 +01:00
|
|
|
hello := &clientHelloMsg{
|
2014-11-16 00:06:08 +00:00
|
|
|
isDTLS: c.isDTLS,
|
|
|
|
compressionMethods: []uint8{compressionNone},
|
|
|
|
random: make([]byte, 32),
|
2016-11-16 00:01:48 +00:00
|
|
|
ocspStapling: !c.config.Bugs.NoOCSPStapling,
|
|
|
|
sctListSupported: !c.config.Bugs.NoSignedCertificateTimestamps,
|
2014-11-16 00:06:08 +00:00
|
|
|
serverName: c.config.ServerName,
|
|
|
|
supportedCurves: c.config.curvePreferences(),
|
|
|
|
supportedPoints: []uint8{pointFormatUncompressed},
|
|
|
|
nextProtoNeg: len(c.config.NextProtos) > 0,
|
|
|
|
secureRenegotiation: []byte{},
|
|
|
|
alpnProtocols: c.config.NextProtos,
|
2017-12-22 23:50:43 +00:00
|
|
|
quicTransportParams: c.config.QUICTransportParams,
|
2014-11-16 00:06:08 +00:00
|
|
|
duplicateExtension: c.config.Bugs.DuplicateExtension,
|
|
|
|
channelIDSupported: c.config.ChannelID != nil,
|
2017-09-21 23:02:22 +01:00
|
|
|
tokenBindingParams: c.config.TokenBindingParams,
|
|
|
|
tokenBindingVersion: c.config.TokenBindingVersion,
|
2016-11-01 17:39:36 +00:00
|
|
|
npnAfterAlpn: c.config.Bugs.SwapNPNAndALPN,
|
2016-09-15 21:27:05 +01:00
|
|
|
extendedMasterSecret: maxVersion >= VersionTLS10,
|
2014-11-16 00:06:08 +00:00
|
|
|
srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
|
|
|
|
srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
|
2015-07-31 02:10:13 +01:00
|
|
|
customExtension: c.config.Bugs.CustomExtension,
|
2016-11-01 17:39:36 +00:00
|
|
|
pskBinderFirst: c.config.Bugs.PSKBinderFirst,
|
2017-07-14 23:40:34 +01:00
|
|
|
omitExtensions: c.config.Bugs.OmitExtensions,
|
|
|
|
emptyExtensions: c.config.Bugs.EmptyExtensions,
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2017-06-20 15:55:02 +01:00
|
|
|
if maxVersion >= VersionTLS13 {
|
|
|
|
hello.vers = mapClientHelloVersion(VersionTLS12, c.isDTLS)
|
|
|
|
if !c.config.Bugs.OmitSupportedVersions {
|
|
|
|
hello.supportedVersions = c.config.supportedVersions(c.isDTLS)
|
|
|
|
}
|
2017-07-14 23:40:34 +01:00
|
|
|
hello.pskKEModes = []byte{pskDHEKEMode}
|
2017-06-20 15:55:02 +01:00
|
|
|
} else {
|
|
|
|
hello.vers = mapClientHelloVersion(maxVersion, c.isDTLS)
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.config.Bugs.SendClientVersion != 0 {
|
|
|
|
hello.vers = c.config.Bugs.SendClientVersion
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(c.config.Bugs.SendSupportedVersions) > 0 {
|
|
|
|
hello.supportedVersions = c.config.Bugs.SendSupportedVersions
|
|
|
|
}
|
|
|
|
|
2016-08-30 04:14:17 +01:00
|
|
|
disableEMS := c.config.Bugs.NoExtendedMasterSecret
|
|
|
|
if c.cipherSuite != nil {
|
|
|
|
disableEMS = c.config.Bugs.NoExtendedMasterSecretOnRenegotiation
|
|
|
|
}
|
|
|
|
|
|
|
|
if disableEMS {
|
2014-10-11 00:23:43 +01:00
|
|
|
hello.extendedMasterSecret = false
|
|
|
|
}
|
|
|
|
|
2015-04-20 19:45:55 +01:00
|
|
|
if c.config.Bugs.NoSupportedCurves {
|
|
|
|
hello.supportedCurves = nil
|
|
|
|
}
|
|
|
|
|
2016-11-01 17:39:36 +00:00
|
|
|
if len(c.config.Bugs.SendPSKKeyExchangeModes) != 0 {
|
|
|
|
hello.pskKEModes = c.config.Bugs.SendPSKKeyExchangeModes
|
|
|
|
}
|
|
|
|
|
2016-09-09 15:34:20 +01:00
|
|
|
if c.config.Bugs.SendCompressionMethods != nil {
|
|
|
|
hello.compressionMethods = c.config.Bugs.SendCompressionMethods
|
|
|
|
}
|
|
|
|
|
2016-12-22 14:16:57 +00:00
|
|
|
if c.config.Bugs.SendSupportedPointFormats != nil {
|
|
|
|
hello.supportedPoints = c.config.Bugs.SendSupportedPointFormats
|
|
|
|
}
|
|
|
|
|
2014-10-29 00:29:33 +00:00
|
|
|
if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
|
|
|
|
if c.config.Bugs.BadRenegotiationInfo {
|
|
|
|
hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
|
|
|
|
hello.secureRenegotiation[0] ^= 0x80
|
|
|
|
} else {
|
|
|
|
hello.secureRenegotiation = c.clientVerify
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-02 17:06:48 +01:00
|
|
|
if c.config.Bugs.DuplicateCompressedCertAlgs {
|
|
|
|
hello.compressedCertAlgs = []uint16{1, 1}
|
|
|
|
} else if len(c.config.CertCompressionAlgs) > 0 {
|
|
|
|
hello.compressedCertAlgs = make([]uint16, 0, len(c.config.CertCompressionAlgs))
|
|
|
|
for id, _ := range c.config.CertCompressionAlgs {
|
|
|
|
hello.compressedCertAlgs = append(hello.compressedCertAlgs, uint16(id))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 01:10:31 +00:00
|
|
|
if c.noRenegotiationInfo() {
|
2014-11-08 17:31:52 +00:00
|
|
|
hello.secureRenegotiation = nil
|
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
var keyShares map[CurveID]ecdhCurve
|
2016-09-26 23:30:05 +01:00
|
|
|
if maxVersion >= VersionTLS13 {
|
2016-07-01 22:50:32 +01:00
|
|
|
keyShares = make(map[CurveID]ecdhCurve)
|
2016-07-16 16:47:31 +01:00
|
|
|
hello.hasKeyShares = true
|
2016-09-21 00:24:40 +01:00
|
|
|
hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
|
2016-07-16 16:47:31 +01:00
|
|
|
curvesToSend := c.config.defaultCurves()
|
2016-07-01 22:50:32 +01:00
|
|
|
for _, curveID := range hello.supportedCurves {
|
2016-07-16 16:47:31 +01:00
|
|
|
if !curvesToSend[curveID] {
|
|
|
|
continue
|
|
|
|
}
|
2018-02-15 00:50:38 +00:00
|
|
|
curve, ok := curveForCurveID(curveID, c.config)
|
2016-07-01 22:50:32 +01:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
publicKey, err := curve.offer(c.config.rand())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-07-15 11:51:15 +01:00
|
|
|
|
|
|
|
if c.config.Bugs.SendCurve != 0 {
|
|
|
|
curveID = c.config.Bugs.SendCurve
|
|
|
|
}
|
|
|
|
if c.config.Bugs.InvalidECDHPoint {
|
|
|
|
publicKey[0] ^= 0xff
|
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
hello.keyShares = append(hello.keyShares, keyShareEntry{
|
|
|
|
group: curveID,
|
|
|
|
keyExchange: publicKey,
|
|
|
|
})
|
|
|
|
keyShares[curveID] = curve
|
2016-07-11 18:19:03 +01:00
|
|
|
|
|
|
|
if c.config.Bugs.DuplicateKeyShares {
|
|
|
|
hello.keyShares = append(hello.keyShares, hello.keyShares[len(hello.keyShares)-1])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.config.Bugs.MissingKeyShare {
|
2016-07-18 17:40:30 +01:00
|
|
|
hello.hasKeyShares = false
|
2016-07-01 22:50:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
possibleCipherSuites := c.config.cipherSuites()
|
|
|
|
hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
|
|
|
|
|
|
|
|
NextCipherSuite:
|
|
|
|
for _, suiteId := range possibleCipherSuites {
|
|
|
|
for _, suite := range cipherSuites {
|
|
|
|
if suite.id != suiteId {
|
|
|
|
continue
|
|
|
|
}
|
2016-10-04 22:51:35 +01:00
|
|
|
// Don't advertise TLS 1.2-only cipher suites unless
|
|
|
|
// we're attempting TLS 1.2.
|
|
|
|
if maxVersion < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
|
|
|
|
continue
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
hello.cipherSuites = append(hello.cipherSuites, suiteId)
|
|
|
|
continue NextCipherSuite
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-04 22:51:35 +01:00
|
|
|
if c.config.Bugs.AdvertiseAllConfiguredCiphers {
|
|
|
|
hello.cipherSuites = possibleCipherSuites
|
|
|
|
}
|
|
|
|
|
2015-06-13 02:27:58 +01:00
|
|
|
if c.config.Bugs.SendRenegotiationSCSV {
|
|
|
|
hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
|
|
|
|
}
|
|
|
|
|
2014-08-02 09:22:02 +01:00
|
|
|
if c.config.Bugs.SendFallbackSCSV {
|
|
|
|
hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
_, err := io.ReadFull(c.config.rand(), hello.random)
|
|
|
|
if err != nil {
|
|
|
|
c.sendAlert(alertInternalError)
|
|
|
|
return errors.New("tls: short read from Rand: " + err.Error())
|
|
|
|
}
|
|
|
|
|
2016-09-26 23:30:05 +01:00
|
|
|
if maxVersion >= VersionTLS12 && !c.config.Bugs.NoSignatureAlgorithms {
|
2016-07-09 19:21:54 +01:00
|
|
|
hello.signatureAlgorithms = c.config.verifySignatureAlgorithms()
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var session *ClientSessionState
|
|
|
|
var cacheKey string
|
|
|
|
sessionCache := c.config.ClientSessionCache
|
|
|
|
|
|
|
|
if sessionCache != nil {
|
2014-11-17 08:19:02 +00:00
|
|
|
hello.ticketSupported = !c.config.SessionTicketsDisabled
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
// Try to resume a previously negotiated TLS session, if
|
|
|
|
// available.
|
|
|
|
cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
|
2016-07-26 00:16:28 +01:00
|
|
|
// TODO(nharper): Support storing more than one session
|
|
|
|
// ticket for TLS 1.3.
|
2014-06-20 20:00:00 +01:00
|
|
|
candidateSession, ok := sessionCache.Get(cacheKey)
|
|
|
|
if ok {
|
2014-11-17 08:19:02 +00:00
|
|
|
ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
// Check that the ciphersuite/version used for the
|
|
|
|
// previous session are still valid.
|
|
|
|
cipherSuiteOk := false
|
2016-11-16 07:11:47 +00:00
|
|
|
if candidateSession.vers <= VersionTLS12 {
|
|
|
|
for _, id := range hello.cipherSuites {
|
|
|
|
if id == candidateSession.cipherSuite {
|
|
|
|
cipherSuiteOk = true
|
|
|
|
break
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2016-11-16 07:11:47 +00:00
|
|
|
} else {
|
|
|
|
// TLS 1.3 allows the cipher to change on
|
|
|
|
// resumption.
|
|
|
|
cipherSuiteOk = true
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2016-09-15 21:27:05 +01:00
|
|
|
versOk := candidateSession.vers >= minVersion &&
|
|
|
|
candidateSession.vers <= maxVersion
|
2014-11-17 08:19:02 +00:00
|
|
|
if ticketOk && versOk && cipherSuiteOk {
|
2014-06-20 20:00:00 +01:00
|
|
|
session = candidateSession
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-01 17:39:36 +00:00
|
|
|
var pskCipherSuite *cipherSuite
|
2016-07-26 00:16:28 +01:00
|
|
|
if session != nil && c.config.time().Before(session.ticketExpiration) {
|
2016-07-18 00:17:13 +01:00
|
|
|
ticket := session.sessionTicket
|
2016-11-01 17:58:25 +00:00
|
|
|
if c.config.Bugs.FilterTicket != nil && len(ticket) > 0 {
|
|
|
|
// Copy the ticket so FilterTicket may act in-place.
|
2016-07-18 00:17:13 +01:00
|
|
|
ticket = make([]byte, len(session.sessionTicket))
|
|
|
|
copy(ticket, session.sessionTicket)
|
2016-11-01 17:58:25 +00:00
|
|
|
|
|
|
|
ticket, err = c.config.Bugs.FilterTicket(ticket)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2014-10-17 03:04:35 +01:00
|
|
|
}
|
2016-07-18 00:17:13 +01:00
|
|
|
}
|
|
|
|
|
2016-08-08 22:25:07 +01:00
|
|
|
if session.vers >= VersionTLS13 || c.config.Bugs.SendBothTickets {
|
2016-11-01 17:39:36 +00:00
|
|
|
pskCipherSuite = cipherSuiteFromID(session.cipherSuite)
|
|
|
|
if pskCipherSuite == nil {
|
|
|
|
return errors.New("tls: client session cache has invalid cipher suite")
|
|
|
|
}
|
2016-07-26 00:16:28 +01:00
|
|
|
// TODO(nharper): Support sending more
|
|
|
|
// than one PSK identity.
|
2016-11-01 17:39:36 +00:00
|
|
|
ticketAge := uint32(c.config.time().Sub(session.ticketCreationTime) / time.Millisecond)
|
2017-03-03 20:05:56 +00:00
|
|
|
if c.config.Bugs.SendTicketAge != 0 {
|
|
|
|
ticketAge = uint32(c.config.Bugs.SendTicketAge / time.Millisecond)
|
|
|
|
}
|
2016-09-01 17:29:49 +01:00
|
|
|
psk := pskIdentity{
|
2016-11-01 17:39:36 +00:00
|
|
|
ticket: ticket,
|
|
|
|
obfuscatedTicketAge: session.ticketAgeAdd + ticketAge,
|
2016-07-26 00:16:28 +01:00
|
|
|
}
|
2016-09-01 17:29:49 +01:00
|
|
|
hello.pskIdentities = []pskIdentity{psk}
|
2016-11-01 16:49:22 +00:00
|
|
|
|
|
|
|
if c.config.Bugs.ExtraPSKIdentity {
|
|
|
|
hello.pskIdentities = append(hello.pskIdentities, psk)
|
|
|
|
}
|
2016-08-08 22:25:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if session.vers < VersionTLS13 || c.config.Bugs.SendBothTickets {
|
|
|
|
if ticket != nil {
|
|
|
|
hello.sessionTicket = ticket
|
|
|
|
// A random session ID is used to detect when the
|
|
|
|
// server accepted the ticket and is resuming a session
|
|
|
|
// (see RFC 5077).
|
|
|
|
sessionIdLen := 16
|
2017-02-09 19:07:17 +00:00
|
|
|
if c.config.Bugs.TicketSessionIDLength != 0 {
|
|
|
|
sessionIdLen = c.config.Bugs.TicketSessionIDLength
|
|
|
|
}
|
|
|
|
if c.config.Bugs.EmptyTicketSessionID {
|
|
|
|
sessionIdLen = 0
|
2016-08-08 22:25:07 +01:00
|
|
|
}
|
|
|
|
hello.sessionId = make([]byte, sessionIdLen)
|
|
|
|
if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
|
|
|
|
c.sendAlert(alertInternalError)
|
|
|
|
return errors.New("tls: short read from Rand: " + err.Error())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hello.sessionId = session.sessionId
|
2014-11-17 08:19:02 +00:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-13 19:58:55 +00:00
|
|
|
// Request compatibility mode from the client by sending a fake session
|
|
|
|
// ID. Although BoringSSL always enables compatibility mode, other
|
|
|
|
// implementations make it conditional on the ClientHello. We test
|
|
|
|
// BoringSSL's expected behavior with SendClientHelloSessionID.
|
|
|
|
if len(hello.sessionId) == 0 && maxVersion >= VersionTLS13 {
|
|
|
|
hello.sessionId = make([]byte, 32)
|
|
|
|
if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
|
|
|
|
c.sendAlert(alertInternalError)
|
|
|
|
return errors.New("tls: short read from Rand: " + err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-12 03:36:06 +00:00
|
|
|
if c.config.Bugs.SendCipherSuites != nil {
|
|
|
|
hello.cipherSuites = c.config.Bugs.SendCipherSuites
|
|
|
|
}
|
|
|
|
|
2016-12-07 00:02:31 +00:00
|
|
|
var sendEarlyData bool
|
2017-01-11 16:34:52 +00:00
|
|
|
if len(hello.pskIdentities) > 0 && c.config.Bugs.SendEarlyData != nil {
|
2016-11-29 18:36:45 +00:00
|
|
|
hello.hasEarlyData = true
|
2016-12-07 00:02:31 +00:00
|
|
|
sendEarlyData = true
|
|
|
|
}
|
|
|
|
if c.config.Bugs.SendFakeEarlyDataLength > 0 {
|
|
|
|
hello.hasEarlyData = true
|
|
|
|
}
|
|
|
|
if c.config.Bugs.OmitEarlyDataExtension {
|
|
|
|
hello.hasEarlyData = false
|
2016-11-29 18:36:45 +00:00
|
|
|
}
|
2017-07-17 16:12:34 +01:00
|
|
|
if c.config.Bugs.SendClientHelloSessionID != nil {
|
|
|
|
hello.sessionId = c.config.Bugs.SendClientHelloSessionID
|
|
|
|
}
|
2016-11-29 18:36:45 +00:00
|
|
|
|
2014-08-02 09:07:12 +01:00
|
|
|
var helloBytes []byte
|
|
|
|
if c.config.Bugs.SendV2ClientHello {
|
2014-11-30 18:54:41 +00:00
|
|
|
// Test that the peer left-pads random.
|
|
|
|
hello.random[0] = 0
|
2014-08-02 09:07:12 +01:00
|
|
|
v2Hello := &v2ClientHelloMsg{
|
|
|
|
vers: hello.vers,
|
|
|
|
cipherSuites: hello.cipherSuites,
|
|
|
|
// No session resumption for V2ClientHello.
|
|
|
|
sessionId: nil,
|
2014-11-30 18:54:41 +00:00
|
|
|
challenge: hello.random[1:],
|
2014-08-02 09:07:12 +01:00
|
|
|
}
|
|
|
|
helloBytes = v2Hello.marshal()
|
|
|
|
c.writeV2Record(helloBytes)
|
|
|
|
} else {
|
2016-11-01 17:39:36 +00:00
|
|
|
if len(hello.pskIdentities) > 0 {
|
2017-10-11 17:29:36 +01:00
|
|
|
version := session.wireVersion
|
|
|
|
// We may have a pre-1.3 session if SendBothTickets is
|
|
|
|
// set. Fill in an arbitrary TLS 1.3 version to compute
|
|
|
|
// the binder.
|
|
|
|
if session.vers < VersionTLS13 {
|
2018-01-22 20:20:31 +00:00
|
|
|
version = tls13Draft23Version
|
2017-10-11 17:29:36 +01:00
|
|
|
}
|
|
|
|
generatePSKBinders(version, hello, pskCipherSuite, session.masterSecret, []byte{}, []byte{}, c.config)
|
2016-11-01 17:39:36 +00:00
|
|
|
}
|
2018-11-19 21:49:56 +00:00
|
|
|
if c.config.Bugs.SendClientHelloWithFixes != nil {
|
|
|
|
helloBytes, err = fixClientHellos(hello, c.config.Bugs.SendClientHelloWithFixes)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
helloBytes = hello.marshal()
|
|
|
|
}
|
2016-11-01 17:39:36 +00:00
|
|
|
|
2016-07-15 04:36:30 +01:00
|
|
|
if c.config.Bugs.PartialClientFinishedWithClientHello {
|
|
|
|
// Include one byte of Finished. We can compute it
|
|
|
|
// without completing the handshake. This assumes we
|
|
|
|
// negotiate TLS 1.3 with no HelloRetryRequest or
|
|
|
|
// CertificateRequest.
|
|
|
|
toWrite := make([]byte, 0, len(helloBytes)+1)
|
|
|
|
toWrite = append(toWrite, helloBytes...)
|
|
|
|
toWrite = append(toWrite, typeFinished)
|
|
|
|
c.writeRecord(recordTypeHandshake, toWrite)
|
|
|
|
} else {
|
|
|
|
c.writeRecord(recordTypeHandshake, helloBytes)
|
|
|
|
}
|
2014-08-02 09:07:12 +01:00
|
|
|
}
|
2016-07-07 20:33:25 +01:00
|
|
|
c.flushHandshake()
|
2014-06-20 20:00:00 +01:00
|
|
|
|
Add DTLS timeout and retransmit tests.
This extends the packet adaptor protocol to send three commands:
type command =
| Packet of []byte
| Timeout of time.Duration
| TimeoutAck
When the shim processes a Timeout in BIO_read, it sends TimeoutAck, fails the
BIO_read, returns out of the SSL stack, advances the clock, calls
DTLSv1_handle_timeout, and continues.
If the Go side sends Timeout right between sending handshake flight N and
reading flight N+1, the shim won't read the Timeout until it has sent flight
N+1 (it only processes packet commands in BIO_read), so the TimeoutAck comes
after N+1. Go then drops all packets before the TimeoutAck, thus dropping one
transmit of flight N+1 without having to actually process the packets to
determine the end of the flight. The shim then sees the updated clock, calls
DTLSv1_handle_timeout, and re-sends flight N+1 for Go to process for real.
When dropping packets, Go checks the epoch and increments sequence numbers so
that we can continue to be strict here. This requires tracking the initial
sequence number of the next epoch.
The final Finished message takes an additional special-case to test. DTLS
triggers retransmits on either a timeout or seeing a stale flight. OpenSSL only
implements the former which should be sufficient (and is necessary) EXCEPT for
the final Finished message. If the peer's final Finished message is lost, it
won't be waiting for a message from us, so it won't time out anything. That
retransmit must be triggered on stale message, so we retransmit the Finished
message in Go.
Change-Id: I3ffbdb1de525beb2ee831b304670a3387877634c
Reviewed-on: https://boringssl-review.googlesource.com/3212
Reviewed-by: Adam Langley <agl@google.com>
2015-01-27 06:09:43 +00:00
|
|
|
if err := c.simulatePacketLoss(nil); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-11-29 18:36:45 +00:00
|
|
|
if c.config.Bugs.SendEarlyAlert {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
}
|
2016-12-07 00:02:31 +00:00
|
|
|
if c.config.Bugs.SendFakeEarlyDataLength > 0 {
|
|
|
|
c.sendFakeEarlyData(c.config.Bugs.SendFakeEarlyDataLength)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Derive early write keys and set Conn state to allow early writes.
|
|
|
|
if sendEarlyData {
|
2017-10-11 17:29:36 +01:00
|
|
|
finishedHash := newFinishedHash(session.wireVersion, c.isDTLS, pskCipherSuite)
|
2016-12-07 00:02:31 +00:00
|
|
|
finishedHash.addEntropy(session.masterSecret)
|
|
|
|
finishedHash.Write(helloBytes)
|
2017-10-11 17:29:36 +01:00
|
|
|
|
2018-01-22 20:20:31 +00:00
|
|
|
if !c.config.Bugs.SkipChangeCipherSpec {
|
2017-11-07 22:09:52 +00:00
|
|
|
c.wireVersion = session.wireVersion
|
2017-12-04 16:15:37 +00:00
|
|
|
c.vers = VersionTLS13
|
2017-11-07 22:09:52 +00:00
|
|
|
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
|
|
|
|
c.wireVersion = 0
|
2017-12-04 16:15:37 +00:00
|
|
|
c.vers = 0
|
2017-11-07 22:09:52 +00:00
|
|
|
}
|
|
|
|
|
2018-01-22 20:20:31 +00:00
|
|
|
earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
|
|
|
|
c.earlyExporterSecret = finishedHash.deriveSecret(earlyExporterLabel)
|
2017-12-08 22:05:06 +00:00
|
|
|
|
2017-10-17 07:56:02 +01:00
|
|
|
c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret)
|
2016-12-07 00:02:31 +00:00
|
|
|
for _, earlyData := range c.config.Bugs.SendEarlyData {
|
|
|
|
if _, err := c.writeRecord(recordTypeApplicationData, earlyData); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2016-11-29 18:36:45 +00:00
|
|
|
}
|
2016-12-07 00:02:31 +00:00
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
msg, err := c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-08-04 06:23:53 +01:00
|
|
|
|
|
|
|
if c.isDTLS {
|
|
|
|
helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
|
|
|
|
if ok {
|
2017-06-20 15:55:02 +01:00
|
|
|
if helloVerifyRequest.vers != VersionDTLS10 {
|
2014-08-16 17:07:27 +01:00
|
|
|
// Per RFC 6347, the version field in
|
|
|
|
// HelloVerifyRequest SHOULD be always DTLS
|
|
|
|
// 1.0. Enforce this for testing purposes.
|
|
|
|
return errors.New("dtls: bad HelloVerifyRequest version")
|
|
|
|
}
|
|
|
|
|
2014-08-04 06:23:53 +01:00
|
|
|
hello.raw = nil
|
|
|
|
hello.cookie = helloVerifyRequest.cookie
|
|
|
|
helloBytes = hello.marshal()
|
|
|
|
c.writeRecord(recordTypeHandshake, helloBytes)
|
2016-07-07 20:33:25 +01:00
|
|
|
c.flushHandshake()
|
2014-08-04 06:23:53 +01:00
|
|
|
|
Add DTLS timeout and retransmit tests.
This extends the packet adaptor protocol to send three commands:
type command =
| Packet of []byte
| Timeout of time.Duration
| TimeoutAck
When the shim processes a Timeout in BIO_read, it sends TimeoutAck, fails the
BIO_read, returns out of the SSL stack, advances the clock, calls
DTLSv1_handle_timeout, and continues.
If the Go side sends Timeout right between sending handshake flight N and
reading flight N+1, the shim won't read the Timeout until it has sent flight
N+1 (it only processes packet commands in BIO_read), so the TimeoutAck comes
after N+1. Go then drops all packets before the TimeoutAck, thus dropping one
transmit of flight N+1 without having to actually process the packets to
determine the end of the flight. The shim then sees the updated clock, calls
DTLSv1_handle_timeout, and re-sends flight N+1 for Go to process for real.
When dropping packets, Go checks the epoch and increments sequence numbers so
that we can continue to be strict here. This requires tracking the initial
sequence number of the next epoch.
The final Finished message takes an additional special-case to test. DTLS
triggers retransmits on either a timeout or seeing a stale flight. OpenSSL only
implements the former which should be sufficient (and is necessary) EXCEPT for
the final Finished message. If the peer's final Finished message is lost, it
won't be waiting for a message from us, so it won't time out anything. That
retransmit must be triggered on stale message, so we retransmit the Finished
message in Go.
Change-Id: I3ffbdb1de525beb2ee831b304670a3387877634c
Reviewed-on: https://boringssl-review.googlesource.com/3212
Reviewed-by: Adam Langley <agl@google.com>
2015-01-27 06:09:43 +00:00
|
|
|
if err := c.simulatePacketLoss(nil); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-08-04 06:23:53 +01:00
|
|
|
msg, err = c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-26 23:30:05 +01:00
|
|
|
var serverWireVersion uint16
|
2016-07-16 16:47:31 +01:00
|
|
|
switch m := msg.(type) {
|
|
|
|
case *helloRetryRequestMsg:
|
2016-09-26 23:30:05 +01:00
|
|
|
serverWireVersion = m.vers
|
2016-07-16 16:47:31 +01:00
|
|
|
case *serverHelloMsg:
|
2016-09-26 23:30:05 +01:00
|
|
|
serverWireVersion = m.vers
|
2016-07-16 16:47:31 +01:00
|
|
|
default:
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg)
|
|
|
|
}
|
|
|
|
|
2017-06-20 15:55:02 +01:00
|
|
|
serverVersion, ok := c.config.isSupportedVersion(serverWireVersion, c.isDTLS)
|
2016-07-16 16:47:31 +01:00
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertProtocolVersion)
|
|
|
|
return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers)
|
|
|
|
}
|
2017-06-20 15:55:02 +01:00
|
|
|
c.wireVersion = serverWireVersion
|
2016-09-15 21:27:05 +01:00
|
|
|
c.vers = serverVersion
|
2016-07-16 16:47:31 +01:00
|
|
|
c.haveVers = true
|
|
|
|
|
2018-01-22 20:20:31 +00:00
|
|
|
if c.vers >= VersionTLS13 {
|
2017-11-16 23:36:38 +00:00
|
|
|
// The first server message must be followed by a ChangeCipherSpec.
|
|
|
|
c.expectTLS13ChangeCipherSpec = true
|
|
|
|
}
|
|
|
|
|
2016-07-16 16:47:31 +01:00
|
|
|
helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
|
|
|
|
var secondHelloBytes []byte
|
|
|
|
if haveHelloRetryRequest {
|
2018-11-12 21:53:42 +00:00
|
|
|
if c.config.Bugs.FailIfHelloRetryRequested {
|
|
|
|
return errors.New("tls: unexpected HelloRetryRequest")
|
|
|
|
}
|
2018-01-22 20:20:31 +00:00
|
|
|
// Explicitly read the ChangeCipherSpec now; it should
|
|
|
|
// be attached to the first flight, not the second flight.
|
|
|
|
if err := c.readTLS13ChangeCipherSpec(); err != nil {
|
|
|
|
return err
|
2017-11-07 22:09:52 +00:00
|
|
|
}
|
|
|
|
|
2016-12-07 00:02:31 +00:00
|
|
|
c.out.resetCipher()
|
2016-10-08 02:10:38 +01:00
|
|
|
if len(helloRetryRequest.cookie) > 0 {
|
|
|
|
hello.tls13Cookie = helloRetryRequest.cookie
|
|
|
|
}
|
|
|
|
|
2016-07-18 17:40:30 +01:00
|
|
|
if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
|
2016-10-08 02:10:38 +01:00
|
|
|
helloRetryRequest.hasSelectedGroup = true
|
2016-07-18 17:40:30 +01:00
|
|
|
helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
|
|
|
|
}
|
2016-10-08 02:10:38 +01:00
|
|
|
if helloRetryRequest.hasSelectedGroup {
|
|
|
|
var hrrCurveFound bool
|
|
|
|
group := helloRetryRequest.selectedGroup
|
|
|
|
for _, curveID := range hello.supportedCurves {
|
|
|
|
if group == curveID {
|
|
|
|
hrrCurveFound = true
|
|
|
|
break
|
|
|
|
}
|
2016-07-16 16:47:31 +01:00
|
|
|
}
|
2016-10-08 02:10:38 +01:00
|
|
|
if !hrrCurveFound || keyShares[group] != nil {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: received invalid HelloRetryRequest")
|
|
|
|
}
|
2018-02-15 00:50:38 +00:00
|
|
|
curve, ok := curveForCurveID(group, c.config)
|
2016-10-08 02:10:38 +01:00
|
|
|
if !ok {
|
|
|
|
return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
|
|
|
|
}
|
|
|
|
publicKey, err := curve.offer(c.config.rand())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
keyShares[group] = curve
|
2016-11-01 17:39:36 +00:00
|
|
|
hello.keyShares = []keyShareEntry{{
|
2016-10-08 02:10:38 +01:00
|
|
|
group: group,
|
|
|
|
keyExchange: publicKey,
|
2016-11-01 17:39:36 +00:00
|
|
|
}}
|
2016-07-16 16:47:31 +01:00
|
|
|
}
|
|
|
|
|
2016-07-18 17:40:30 +01:00
|
|
|
if c.config.Bugs.SecondClientHelloMissingKeyShare {
|
|
|
|
hello.hasKeyShares = false
|
|
|
|
}
|
|
|
|
|
2016-11-29 18:36:45 +00:00
|
|
|
hello.hasEarlyData = c.config.Bugs.SendEarlyDataOnSecondClientHello
|
2016-07-16 16:47:31 +01:00
|
|
|
hello.raw = nil
|
|
|
|
|
2016-11-01 17:39:36 +00:00
|
|
|
if len(hello.pskIdentities) > 0 {
|
2017-10-11 17:29:36 +01:00
|
|
|
generatePSKBinders(c.wireVersion, hello, pskCipherSuite, session.masterSecret, helloBytes, helloRetryRequest.marshal(), c.config)
|
2016-11-01 17:39:36 +00:00
|
|
|
}
|
2016-07-16 16:47:31 +01:00
|
|
|
secondHelloBytes = hello.marshal()
|
2016-11-29 18:36:45 +00:00
|
|
|
|
|
|
|
if c.config.Bugs.InterleaveEarlyData {
|
|
|
|
c.sendFakeEarlyData(4)
|
|
|
|
c.writeRecord(recordTypeHandshake, secondHelloBytes[:16])
|
|
|
|
c.sendFakeEarlyData(4)
|
|
|
|
c.writeRecord(recordTypeHandshake, secondHelloBytes[16:])
|
|
|
|
} else {
|
|
|
|
c.writeRecord(recordTypeHandshake, secondHelloBytes)
|
|
|
|
}
|
2016-07-16 16:47:31 +01:00
|
|
|
c.flushHandshake()
|
|
|
|
|
2016-11-29 18:36:45 +00:00
|
|
|
if c.config.Bugs.SendEarlyDataOnSecondClientHello {
|
|
|
|
c.sendFakeEarlyData(4)
|
|
|
|
}
|
|
|
|
|
2016-07-16 16:47:31 +01:00
|
|
|
msg, err = c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
serverHello, ok := msg.(*serverHelloMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(serverHello, msg)
|
|
|
|
}
|
|
|
|
|
2016-09-26 23:30:05 +01:00
|
|
|
if serverWireVersion != serverHello.vers {
|
2018-05-05 03:00:33 +01:00
|
|
|
c.sendAlert(alertIllegalParameter)
|
2016-09-26 23:30:05 +01:00
|
|
|
return fmt.Errorf("tls: server sent non-matching version %x vs %x", serverWireVersion, serverHello.vers)
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2018-08-13 15:54:48 +01:00
|
|
|
_, supportsTLS13 := c.config.isSupportedVersion(VersionTLS13, false)
|
2018-08-15 04:26:39 +01:00
|
|
|
// Check for downgrade signals in the server random, per RFC 8446, section 4.1.3.
|
2018-11-19 21:49:56 +00:00
|
|
|
gotDowngrade := serverHello.random[len(serverHello.random)-8:]
|
2018-08-13 15:54:48 +01:00
|
|
|
if (supportsTLS13 || c.config.Bugs.CheckTLS13DowngradeRandom) && !c.config.Bugs.IgnoreTLS13DowngradeRandom {
|
|
|
|
if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 {
|
2018-11-19 21:49:56 +00:00
|
|
|
if bytes.Equal(gotDowngrade, downgradeTLS13) {
|
2018-08-13 15:54:48 +01:00
|
|
|
c.sendAlert(alertProtocolVersion)
|
|
|
|
return errors.New("tls: downgrade from TLS 1.3 detected")
|
|
|
|
}
|
2016-07-04 18:11:59 +01:00
|
|
|
}
|
2018-08-13 15:54:48 +01:00
|
|
|
if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 {
|
2018-11-19 21:49:56 +00:00
|
|
|
if bytes.Equal(gotDowngrade, downgradeTLS12) {
|
2018-08-13 15:54:48 +01:00
|
|
|
c.sendAlert(alertProtocolVersion)
|
|
|
|
return errors.New("tls: downgrade from TLS 1.2 detected")
|
|
|
|
}
|
2016-07-04 18:11:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-19 21:49:56 +00:00
|
|
|
if bytes.Equal(gotDowngrade, downgradeJDK11) != c.config.Bugs.ExpectJDK11DowngradeRandom {
|
|
|
|
c.sendAlert(alertProtocolVersion)
|
|
|
|
if c.config.Bugs.ExpectJDK11DowngradeRandom {
|
|
|
|
return errors.New("tls: server did not send a JDK 11 downgrade signal")
|
|
|
|
}
|
|
|
|
return errors.New("tls: server sent an unexpected JDK 11 downgrade signal")
|
|
|
|
}
|
|
|
|
|
2016-07-26 00:16:28 +01:00
|
|
|
suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite)
|
2014-06-20 20:00:00 +01:00
|
|
|
if suite == nil {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return fmt.Errorf("tls: server selected an unsupported cipher suite")
|
|
|
|
}
|
|
|
|
|
2016-10-08 02:10:38 +01:00
|
|
|
if haveHelloRetryRequest && helloRetryRequest.hasSelectedGroup && helloRetryRequest.selectedGroup != serverHello.keyShare.group {
|
2016-07-16 16:47:31 +01:00
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
|
|
|
|
}
|
|
|
|
|
2017-08-31 05:19:57 +01:00
|
|
|
if c.config.Bugs.ExpectOmitExtensions && !serverHello.omitExtensions {
|
|
|
|
return errors.New("tls: ServerHello did not omit extensions")
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
hs := &clientHandshakeState{
|
|
|
|
c: c,
|
|
|
|
serverHello: serverHello,
|
|
|
|
hello: hello,
|
|
|
|
suite: suite,
|
2017-10-11 17:29:36 +01:00
|
|
|
finishedHash: newFinishedHash(c.wireVersion, c.isDTLS, suite),
|
2016-07-01 22:50:32 +01:00
|
|
|
keyShares: keyShares,
|
2014-06-20 20:00:00 +01:00
|
|
|
session: session,
|
|
|
|
}
|
|
|
|
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
|
2016-07-16 16:47:31 +01:00
|
|
|
if haveHelloRetryRequest {
|
2018-01-22 20:20:31 +00:00
|
|
|
err = hs.finishedHash.UpdateForHelloRetryRequest()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2017-10-11 17:29:36 +01:00
|
|
|
}
|
2016-07-16 16:47:31 +01:00
|
|
|
hs.writeServerHash(helloRetryRequest.marshal())
|
|
|
|
hs.writeClientHash(secondHelloBytes)
|
|
|
|
}
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeServerHash(hs.serverHello.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-07-18 00:03:18 +01:00
|
|
|
if c.vers >= VersionTLS13 {
|
2016-07-01 22:50:32 +01:00
|
|
|
if err := hs.doTLS13Handshake(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if c.config.Bugs.EarlyChangeCipherSpec > 0 {
|
|
|
|
hs.establishKeys()
|
|
|
|
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
|
|
|
|
}
|
2014-07-22 03:42:34 +01:00
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
if hs.serverHello.compressionMethod != compressionNone {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return errors.New("tls: server selected unsupported compression format")
|
|
|
|
}
|
2016-07-01 18:40:23 +01:00
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
err = hs.processServerExtensions(&serverHello.extensions)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-07-01 18:40:23 +01:00
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
isResume, err := hs.processServerHello()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
if isResume {
|
|
|
|
if c.config.Bugs.EarlyChangeCipherSpec == 0 {
|
|
|
|
if err := hs.establishKeys(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err := hs.readSessionTicket(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := hs.readFinished(c.firstFinished[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := hs.sendFinished(nil, isResume); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err := hs.doFullHandshake(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-07-22 03:42:34 +01:00
|
|
|
if err := hs.establishKeys(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Most retransmits are triggered by a timeout, but the final
|
|
|
|
// leg of the handshake is retransmited upon re-receiving a
|
|
|
|
// Finished.
|
|
|
|
if err := c.simulatePacketLoss(func() {
|
2016-07-27 22:40:37 +01:00
|
|
|
c.sendHandshakeSeq--
|
2016-07-01 22:50:32 +01:00
|
|
|
c.writeRecord(recordTypeHandshake, hs.finishedBytes)
|
|
|
|
c.flushHandshake()
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := hs.readSessionTicket(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := hs.readFinished(nil); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
|
|
|
|
if sessionCache != nil && hs.session != nil && session != hs.session {
|
|
|
|
if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
|
|
|
|
return errors.New("tls: new session used session IDs instead of tickets")
|
|
|
|
}
|
2018-07-18 02:26:05 +01:00
|
|
|
if c.config.Bugs.RequireSessionIDs && len(hs.session.sessionId) == 0 {
|
|
|
|
return errors.New("tls: new session used session tickets instead of IDs")
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
sessionCache.Put(cacheKey, hs.session)
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
|
|
|
|
c.didResume = isResume
|
2016-07-13 22:57:35 +01:00
|
|
|
c.exporterSecret = hs.masterSecret
|
2016-07-01 22:50:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
c.handshakeComplete = true
|
|
|
|
c.cipherSuite = suite
|
|
|
|
copy(c.clientRandom[:], hs.hello.random)
|
|
|
|
copy(c.serverRandom[:], hs.serverHello.random)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *clientHandshakeState) doTLS13Handshake() error {
|
|
|
|
c := hs.c
|
|
|
|
|
2017-12-04 16:15:37 +00:00
|
|
|
if !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
|
2017-07-17 16:12:34 +01:00
|
|
|
return errors.New("tls: session IDs did not match.")
|
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
// Once the PRF hash is known, TLS 1.3 does not require a handshake
|
|
|
|
// buffer.
|
|
|
|
hs.finishedHash.discardHandshakeBuffer()
|
|
|
|
|
|
|
|
zeroSecret := hs.finishedHash.zeroSecret()
|
|
|
|
|
|
|
|
// Resolve PSK and compute the early secret.
|
|
|
|
//
|
|
|
|
// TODO(davidben): This will need to be handled slightly earlier once
|
|
|
|
// 0-RTT is implemented.
|
2016-09-06 19:13:43 +01:00
|
|
|
if hs.serverHello.hasPSKIdentity {
|
2016-07-26 00:16:28 +01:00
|
|
|
// We send at most one PSK identity.
|
|
|
|
if hs.session == nil || hs.serverHello.pskIdentity != 0 {
|
|
|
|
c.sendAlert(alertUnknownPSKIdentity)
|
|
|
|
return errors.New("tls: server sent unknown PSK identity")
|
|
|
|
}
|
2016-11-16 07:11:47 +00:00
|
|
|
sessionCipher := cipherSuiteFromID(hs.session.cipherSuite)
|
|
|
|
if sessionCipher == nil || sessionCipher.hash() != hs.suite.hash() {
|
2016-07-26 00:16:28 +01:00
|
|
|
c.sendAlert(alertHandshakeFailure)
|
2016-11-16 07:11:47 +00:00
|
|
|
return errors.New("tls: server resumed an invalid session for the cipher suite")
|
2016-07-26 00:16:28 +01:00
|
|
|
}
|
2016-12-04 05:02:43 +00:00
|
|
|
hs.finishedHash.addEntropy(hs.session.masterSecret)
|
2016-07-26 00:16:28 +01:00
|
|
|
c.didResume = true
|
2016-07-01 22:50:32 +01:00
|
|
|
} else {
|
2016-12-04 05:02:43 +00:00
|
|
|
hs.finishedHash.addEntropy(zeroSecret)
|
2016-07-01 22:50:32 +01:00
|
|
|
}
|
|
|
|
|
2016-11-01 17:39:36 +00:00
|
|
|
if !hs.serverHello.hasKeyShare {
|
|
|
|
c.sendAlert(alertUnsupportedExtension)
|
|
|
|
return errors.New("tls: server omitted KeyShare on resumption.")
|
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
// Resolve ECDHE and compute the handshake secret.
|
2016-09-06 19:13:43 +01:00
|
|
|
if !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
|
2016-07-01 22:50:32 +01:00
|
|
|
curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: server selected an unsupported group")
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2016-07-18 17:40:30 +01:00
|
|
|
c.curveID = hs.serverHello.keyShare.group
|
2016-07-01 22:50:32 +01:00
|
|
|
|
2016-12-04 05:02:43 +00:00
|
|
|
ecdheSecret, err := curve.finish(hs.serverHello.keyShare.keyExchange)
|
2016-07-01 22:50:32 +01:00
|
|
|
if err != nil {
|
2014-06-20 20:00:00 +01:00
|
|
|
return err
|
|
|
|
}
|
2017-10-11 17:29:36 +01:00
|
|
|
hs.finishedHash.nextSecret()
|
2016-12-04 05:02:43 +00:00
|
|
|
hs.finishedHash.addEntropy(ecdheSecret)
|
2014-06-20 20:00:00 +01:00
|
|
|
} else {
|
2017-10-11 17:29:36 +01:00
|
|
|
hs.finishedHash.nextSecret()
|
2016-12-04 05:02:43 +00:00
|
|
|
hs.finishedHash.addEntropy(zeroSecret)
|
2016-07-01 22:50:32 +01:00
|
|
|
}
|
|
|
|
|
2016-12-07 00:02:31 +00:00
|
|
|
// Derive handshake traffic keys and switch read key to handshake
|
|
|
|
// traffic key.
|
2018-01-22 20:20:31 +00:00
|
|
|
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
|
|
|
|
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
|
2017-10-17 22:14:58 +01:00
|
|
|
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
|
|
|
|
msg, err := c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(encryptedExtensions, msg)
|
|
|
|
}
|
|
|
|
hs.writeServerHash(encryptedExtensions.marshal())
|
|
|
|
|
|
|
|
err = hs.processServerExtensions(&encryptedExtensions.extensions)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var chainToSend *Certificate
|
2016-07-09 22:26:01 +01:00
|
|
|
var certReq *certificateRequestMsg
|
2016-11-01 17:39:36 +00:00
|
|
|
if c.didResume {
|
2016-07-26 00:16:28 +01:00
|
|
|
// Copy over authentication from the session.
|
|
|
|
c.peerCertificates = hs.session.serverCertificates
|
|
|
|
c.sctList = hs.session.sctList
|
|
|
|
c.ocspResponse = hs.session.ocspResponse
|
2016-07-02 03:40:23 +01:00
|
|
|
} else {
|
2016-07-01 22:50:32 +01:00
|
|
|
msg, err := c.readHandshake()
|
|
|
|
if err != nil {
|
2014-06-20 20:00:00 +01:00
|
|
|
return err
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
|
2016-07-09 22:26:01 +01:00
|
|
|
var ok bool
|
|
|
|
certReq, ok = msg.(*certificateRequestMsg)
|
2016-07-01 22:50:32 +01:00
|
|
|
if ok {
|
2016-08-18 07:32:23 +01:00
|
|
|
if len(certReq.requestContext) != 0 {
|
|
|
|
return errors.New("tls: non-empty certificate request context sent in handshake")
|
|
|
|
}
|
|
|
|
|
2017-10-11 17:29:36 +01:00
|
|
|
if c.config.Bugs.ExpectNoCertificateAuthoritiesExtension && certReq.hasCAExtension {
|
|
|
|
return errors.New("tls: expected no certificate_authorities extension")
|
|
|
|
}
|
|
|
|
|
2018-04-08 18:59:25 +01:00
|
|
|
if err := checkRSAPSSSupport(c.config.Bugs.ExpectRSAPSSSupport, certReq.signatureAlgorithms, certReq.signatureAlgorithmsCert); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-07-18 13:55:02 +01:00
|
|
|
if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
|
|
|
|
certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
|
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
hs.writeServerHash(certReq.marshal())
|
|
|
|
|
|
|
|
chainToSend, err = selectClientCertificate(c, certReq)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
msg, err = c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
|
2018-05-02 17:06:48 +01:00
|
|
|
var certMsg *certificateMsg
|
|
|
|
|
|
|
|
if compressedCertMsg, ok := msg.(*compressedCertificateMsg); ok {
|
|
|
|
hs.writeServerHash(compressedCertMsg.marshal())
|
|
|
|
|
|
|
|
alg, ok := c.config.CertCompressionAlgs[compressedCertMsg.algID]
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertBadCertificate)
|
|
|
|
return fmt.Errorf("tls: received certificate compressed with unknown algorithm %x", compressedCertMsg.algID)
|
|
|
|
}
|
|
|
|
|
|
|
|
decompressed := make([]byte, 4+int(compressedCertMsg.uncompressedLength))
|
|
|
|
if !alg.Decompress(decompressed[4:], compressedCertMsg.compressed) {
|
|
|
|
c.sendAlert(alertBadCertificate)
|
|
|
|
return fmt.Errorf("tls: failed to decompress certificate with algorithm %x", compressedCertMsg.algID)
|
|
|
|
}
|
|
|
|
|
|
|
|
certMsg = &certificateMsg{
|
|
|
|
hasRequestContext: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
if !certMsg.unmarshal(decompressed) {
|
|
|
|
c.sendAlert(alertBadCertificate)
|
|
|
|
return errors.New("tls: failed to parse decompressed certificate")
|
|
|
|
}
|
|
|
|
|
|
|
|
if expected := c.config.Bugs.ExpectedCompressedCert; expected != 0 && expected != compressedCertMsg.algID {
|
|
|
|
return fmt.Errorf("tls: expected certificate compressed with algorithm %x, but message used %x", expected, compressedCertMsg.algID)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if certMsg, ok = msg.(*certificateMsg); !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(certMsg, msg)
|
|
|
|
}
|
|
|
|
hs.writeServerHash(certMsg.marshal())
|
|
|
|
|
|
|
|
if c.config.Bugs.ExpectedCompressedCert != 0 {
|
|
|
|
return errors.New("tls: uncompressed certificate received")
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
}
|
|
|
|
|
2016-11-16 00:01:48 +00:00
|
|
|
// Check for unsolicited extensions.
|
|
|
|
for i, cert := range certMsg.certificates {
|
|
|
|
if c.config.Bugs.NoOCSPStapling && cert.ocspResponse != nil {
|
|
|
|
c.sendAlert(alertUnsupportedExtension)
|
|
|
|
return errors.New("tls: unexpected OCSP response in the server certificate")
|
|
|
|
}
|
|
|
|
if c.config.Bugs.NoSignedCertificateTimestamps && cert.sctList != nil {
|
|
|
|
c.sendAlert(alertUnsupportedExtension)
|
|
|
|
return errors.New("tls: unexpected SCT list in the server certificate")
|
|
|
|
}
|
|
|
|
if i > 0 && c.config.Bugs.ExpectNoExtensionsOnIntermediate && (cert.ocspResponse != nil || cert.sctList != nil) {
|
|
|
|
c.sendAlert(alertUnsupportedExtension)
|
|
|
|
return errors.New("tls: unexpected extensions in the server certificate")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
if err := hs.verifyCertificates(certMsg); err != nil {
|
Add DTLS timeout and retransmit tests.
This extends the packet adaptor protocol to send three commands:
type command =
| Packet of []byte
| Timeout of time.Duration
| TimeoutAck
When the shim processes a Timeout in BIO_read, it sends TimeoutAck, fails the
BIO_read, returns out of the SSL stack, advances the clock, calls
DTLSv1_handle_timeout, and continues.
If the Go side sends Timeout right between sending handshake flight N and
reading flight N+1, the shim won't read the Timeout until it has sent flight
N+1 (it only processes packet commands in BIO_read), so the TimeoutAck comes
after N+1. Go then drops all packets before the TimeoutAck, thus dropping one
transmit of flight N+1 without having to actually process the packets to
determine the end of the flight. The shim then sees the updated clock, calls
DTLSv1_handle_timeout, and re-sends flight N+1 for Go to process for real.
When dropping packets, Go checks the epoch and increments sequence numbers so
that we can continue to be strict here. This requires tracking the initial
sequence number of the next epoch.
The final Finished message takes an additional special-case to test. DTLS
triggers retransmits on either a timeout or seeing a stale flight. OpenSSL only
implements the former which should be sufficient (and is necessary) EXCEPT for
the final Finished message. If the peer's final Finished message is lost, it
won't be waiting for a message from us, so it won't time out anything. That
retransmit must be triggered on stale message, so we retransmit the Finished
message in Go.
Change-Id: I3ffbdb1de525beb2ee831b304670a3387877634c
Reviewed-on: https://boringssl-review.googlesource.com/3212
Reviewed-by: Adam Langley <agl@google.com>
2015-01-27 06:09:43 +00:00
|
|
|
return err
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
leaf := c.peerCertificates[0]
|
2016-11-01 17:39:36 +00:00
|
|
|
c.ocspResponse = certMsg.certificates[0].ocspResponse
|
|
|
|
c.sctList = certMsg.certificates[0].sctList
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
msg, err = c.readHandshake()
|
|
|
|
if err != nil {
|
2014-06-20 20:00:00 +01:00
|
|
|
return err
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
certVerifyMsg, ok := msg.(*certificateVerifyMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(certVerifyMsg, msg)
|
|
|
|
}
|
|
|
|
|
2016-07-14 02:18:49 +01:00
|
|
|
c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
|
2016-07-01 22:50:32 +01:00
|
|
|
input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
|
2017-03-29 00:28:44 +01:00
|
|
|
err = verifyMessage(c.vers, getCertificatePublicKey(leaf), c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
|
2016-07-01 22:50:32 +01:00
|
|
|
if err != nil {
|
2014-06-20 20:00:00 +01:00
|
|
|
return err
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
|
|
|
|
hs.writeServerHash(certVerifyMsg.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
msg, err = c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
serverFinished, ok := msg.(*finishedMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(serverFinished, msg)
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2016-10-03 17:25:56 +01:00
|
|
|
verify := hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
|
2016-07-01 22:50:32 +01:00
|
|
|
if len(verify) != len(serverFinished.verifyData) ||
|
|
|
|
subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: server's Finished message was incorrect")
|
|
|
|
}
|
|
|
|
|
|
|
|
hs.writeServerHash(serverFinished.marshal())
|
2015-09-09 13:44:55 +01:00
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
// The various secrets do not incorporate the client's final leg, so
|
|
|
|
// derive them now before updating the handshake context.
|
2017-10-11 17:29:36 +01:00
|
|
|
hs.finishedHash.nextSecret()
|
2016-12-04 05:02:43 +00:00
|
|
|
hs.finishedHash.addEntropy(zeroSecret)
|
2017-10-11 17:29:36 +01:00
|
|
|
|
2018-01-22 20:20:31 +00:00
|
|
|
clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
|
|
|
|
serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
|
|
|
|
c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
|
2017-02-07 21:06:48 +00:00
|
|
|
|
|
|
|
// Switch to application data keys on read. In particular, any alerts
|
|
|
|
// from the client certificate are read over these keys.
|
2017-10-17 22:14:58 +01:00
|
|
|
if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-12-02 19:08:40 +00:00
|
|
|
|
2017-10-11 17:29:36 +01:00
|
|
|
// If we're expecting 0.5-RTT messages from the server, read them now.
|
|
|
|
var deferredTickets []*newSessionTicketMsg
|
2017-03-26 04:24:23 +01:00
|
|
|
if encryptedExtensions.extensions.hasEarlyData {
|
|
|
|
// BoringSSL will always send two tickets half-RTT when
|
|
|
|
// negotiating 0-RTT.
|
|
|
|
for i := 0; i < shimConfig.HalfRTTTickets; i++ {
|
|
|
|
msg, err := c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("tls: error reading half-RTT ticket: %s", err)
|
|
|
|
}
|
|
|
|
newSessionTicket, ok := msg.(*newSessionTicketMsg)
|
|
|
|
if !ok {
|
|
|
|
return errors.New("tls: expected half-RTT ticket")
|
|
|
|
}
|
2017-10-11 17:29:36 +01:00
|
|
|
// Defer processing until the resumption secret is computed.
|
|
|
|
deferredTickets = append(deferredTickets, newSessionTicket)
|
2016-12-02 19:08:40 +00:00
|
|
|
}
|
2017-03-26 04:24:23 +01:00
|
|
|
for _, expectedMsg := range c.config.Bugs.ExpectHalfRTTData {
|
|
|
|
if err := c.readRecord(recordTypeApplicationData); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !bytes.Equal(c.input.data[c.input.off:], expectedMsg) {
|
|
|
|
return errors.New("ExpectHalfRTTData: did not get expected message")
|
|
|
|
}
|
|
|
|
c.in.freeBlock(c.input)
|
|
|
|
c.input = nil
|
2016-12-02 19:08:40 +00:00
|
|
|
}
|
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
|
2016-12-07 00:02:31 +00:00
|
|
|
// Send EndOfEarlyData and then switch write key to handshake
|
|
|
|
// traffic key.
|
2017-10-11 17:29:36 +01:00
|
|
|
if encryptedExtensions.extensions.hasEarlyData && c.out.cipher != nil && !c.config.Bugs.SkipEndOfEarlyData {
|
2016-12-19 18:19:29 +00:00
|
|
|
if c.config.Bugs.SendStrayEarlyHandshake {
|
|
|
|
helloRequest := new(helloRequestMsg)
|
|
|
|
c.writeRecord(recordTypeHandshake, helloRequest.marshal())
|
|
|
|
}
|
2018-01-22 20:20:31 +00:00
|
|
|
endOfEarlyData := new(endOfEarlyDataMsg)
|
|
|
|
endOfEarlyData.nonEmpty = c.config.Bugs.NonEmptyEndOfEarlyData
|
|
|
|
c.writeRecord(recordTypeHandshake, endOfEarlyData.marshal())
|
|
|
|
hs.writeClientHash(endOfEarlyData.marshal())
|
2016-12-07 00:02:31 +00:00
|
|
|
}
|
2017-06-13 17:45:25 +01:00
|
|
|
|
2017-12-04 16:15:37 +00:00
|
|
|
if !c.config.Bugs.SkipChangeCipherSpec && !hs.hello.hasEarlyData {
|
2017-11-07 22:09:52 +00:00
|
|
|
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < c.config.Bugs.SendExtraChangeCipherSpec; i++ {
|
2017-06-13 17:45:25 +01:00
|
|
|
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
|
|
|
|
}
|
|
|
|
|
2017-10-17 07:56:02 +01:00
|
|
|
c.useOutTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret)
|
2016-12-07 00:02:31 +00:00
|
|
|
|
2016-07-15 11:51:15 +01:00
|
|
|
if certReq != nil && !c.config.Bugs.SkipClientCertificate {
|
2016-07-09 22:26:01 +01:00
|
|
|
certMsg := &certificateMsg{
|
|
|
|
hasRequestContext: true,
|
|
|
|
requestContext: certReq.requestContext,
|
|
|
|
}
|
|
|
|
if chainToSend != nil {
|
2016-11-01 17:39:36 +00:00
|
|
|
for _, certData := range chainToSend.Certificate {
|
|
|
|
certMsg.certificates = append(certMsg.certificates, certificateEntry{
|
|
|
|
data: certData,
|
|
|
|
extraExtension: c.config.Bugs.SendExtensionOnCertificate,
|
|
|
|
})
|
|
|
|
}
|
2016-07-09 22:26:01 +01:00
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
2016-07-15 11:51:15 +01:00
|
|
|
if c.config.Bugs.SendSignatureAlgorithm != 0 {
|
|
|
|
certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
|
|
|
|
}
|
2016-07-09 22:26:01 +01:00
|
|
|
|
2017-08-10 17:01:06 +01:00
|
|
|
if !c.config.Bugs.SkipCertificateVerify {
|
|
|
|
hs.writeClientHash(certVerify.marshal())
|
|
|
|
c.writeRecord(recordTypeHandshake, certVerify.marshal())
|
|
|
|
}
|
2016-07-09 22:26:01 +01:00
|
|
|
}
|
2016-07-01 22:50:32 +01:00
|
|
|
}
|
|
|
|
|
2016-09-24 00:25:11 +01:00
|
|
|
if encryptedExtensions.extensions.channelIDRequested {
|
|
|
|
channelIDHash := crypto.SHA256.New()
|
|
|
|
channelIDHash.Write(hs.finishedHash.certificateVerifyInput(channelIDContextTLS13))
|
|
|
|
channelIDMsgBytes, err := hs.writeChannelIDMessage(channelIDHash.Sum(nil))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
hs.writeClientHash(channelIDMsgBytes)
|
|
|
|
c.writeRecord(recordTypeHandshake, channelIDMsgBytes)
|
|
|
|
}
|
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
// Send a client Finished message.
|
|
|
|
finished := new(finishedMsg)
|
2016-10-03 17:25:56 +01:00
|
|
|
finished.verifyData = hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
|
2016-07-01 22:50:32 +01:00
|
|
|
if c.config.Bugs.BadFinished {
|
|
|
|
finished.verifyData[0]++
|
|
|
|
}
|
2016-07-13 22:57:35 +01:00
|
|
|
hs.writeClientHash(finished.marshal())
|
2016-07-15 04:36:30 +01:00
|
|
|
if c.config.Bugs.PartialClientFinishedWithClientHello {
|
|
|
|
// The first byte has already been sent.
|
|
|
|
c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
|
2016-11-29 18:36:45 +00:00
|
|
|
} else if c.config.Bugs.InterleaveEarlyData {
|
|
|
|
finishedBytes := finished.marshal()
|
|
|
|
c.sendFakeEarlyData(4)
|
|
|
|
c.writeRecord(recordTypeHandshake, finishedBytes[:1])
|
|
|
|
c.sendFakeEarlyData(4)
|
|
|
|
c.writeRecord(recordTypeHandshake, finishedBytes[1:])
|
2016-07-15 04:36:30 +01:00
|
|
|
} else {
|
|
|
|
c.writeRecord(recordTypeHandshake, finished.marshal())
|
|
|
|
}
|
2016-07-27 22:40:37 +01:00
|
|
|
if c.config.Bugs.SendExtraFinished {
|
|
|
|
c.writeRecord(recordTypeHandshake, finished.marshal())
|
|
|
|
}
|
2016-07-08 02:34:12 +01:00
|
|
|
c.flushHandshake()
|
2016-07-01 22:50:32 +01:00
|
|
|
|
|
|
|
// Switch to application data keys.
|
2017-10-17 07:56:02 +01:00
|
|
|
c.useOutTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret)
|
2018-01-22 20:20:31 +00:00
|
|
|
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
|
2017-10-11 17:29:36 +01:00
|
|
|
for _, ticket := range deferredTickets {
|
|
|
|
if err := c.processTLS13NewSessionTicket(ticket, hs.suite); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *clientHandshakeState) doFullHandshake() error {
|
|
|
|
c := hs.c
|
|
|
|
|
2014-10-27 05:06:24 +00:00
|
|
|
var leaf *x509.Certificate
|
|
|
|
if hs.suite.flags&suitePSK == 0 {
|
|
|
|
msg, err := c.readHandshake()
|
2014-06-20 20:00:00 +01:00
|
|
|
if err != nil {
|
2014-10-27 05:06:24 +00:00
|
|
|
return err
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2014-10-27 05:06:24 +00:00
|
|
|
certMsg, ok := msg.(*certificateMsg)
|
2016-07-01 23:58:51 +01:00
|
|
|
if !ok {
|
2014-10-27 05:06:24 +00:00
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(certMsg, msg)
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-10-27 05:06:24 +00:00
|
|
|
hs.writeServerHash(certMsg.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-07-01 23:58:51 +01:00
|
|
|
if err := hs.verifyCertificates(certMsg); err != nil {
|
|
|
|
return err
|
2014-10-27 05:06:24 +00:00
|
|
|
}
|
2016-07-01 23:58:51 +01:00
|
|
|
leaf = c.peerCertificates[0]
|
2014-10-27 05:06:24 +00:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-07-01 16:43:18 +01:00
|
|
|
if hs.serverHello.extensions.ocspStapling {
|
2014-10-27 05:06:24 +00:00
|
|
|
msg, err := c.readHandshake()
|
2014-06-20 20:00:00 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
cs, ok := msg.(*certificateStatusMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(cs, msg)
|
|
|
|
}
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeServerHash(cs.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
if cs.statusType == statusTypeOCSP {
|
|
|
|
c.ocspResponse = cs.response
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-27 05:06:24 +00:00
|
|
|
msg, err := c.readHandshake()
|
2014-06-20 20:00:00 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
keyAgreement := hs.suite.ka(c.vers)
|
|
|
|
|
|
|
|
skx, ok := msg.(*serverKeyExchangeMsg)
|
|
|
|
if ok {
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeServerHash(skx.marshal())
|
2014-10-27 05:06:24 +00:00
|
|
|
err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
|
2014-06-20 20:00:00 +01:00
|
|
|
if err != nil {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return err
|
|
|
|
}
|
2016-07-18 17:40:30 +01:00
|
|
|
if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
|
|
|
|
c.curveID = ecdhe.curveID
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-06-21 23:19:24 +01:00
|
|
|
c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
msg, err = c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var chainToSend *Certificate
|
|
|
|
var certRequested bool
|
|
|
|
certReq, ok := msg.(*certificateRequestMsg)
|
|
|
|
if ok {
|
|
|
|
certRequested = true
|
2018-04-08 18:59:25 +01:00
|
|
|
if err := checkRSAPSSSupport(c.config.Bugs.ExpectRSAPSSSupport, certReq.signatureAlgorithms, certReq.signatureAlgorithmsCert); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-07-09 19:21:54 +01:00
|
|
|
if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
|
|
|
|
certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeServerHash(certReq.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-07-01 23:44:02 +01:00
|
|
|
chainToSend, err = selectClientCertificate(c, certReq)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
msg, err = c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shd, ok := msg.(*serverHelloDoneMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(shd, msg)
|
|
|
|
}
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeServerHash(shd.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
// If the server requested a certificate then we have to send a
|
2016-03-10 20:44:22 +00:00
|
|
|
// Certificate message in TLS, even if it's empty because we don't have
|
|
|
|
// a certificate to send. In SSL 3.0, skip the message and send a
|
|
|
|
// no_certificate warning alert.
|
2014-06-20 20:00:00 +01:00
|
|
|
if certRequested {
|
2016-03-10 20:44:22 +00:00
|
|
|
if c.vers == VersionSSL30 && chainToSend == nil {
|
2017-01-02 13:30:36 +00:00
|
|
|
c.sendAlert(alertNoCertificate)
|
2016-03-10 20:44:22 +00:00
|
|
|
} else if !c.config.Bugs.SkipClientCertificate {
|
|
|
|
certMsg := new(certificateMsg)
|
|
|
|
if chainToSend != nil {
|
2016-11-01 17:39:36 +00:00
|
|
|
for _, certData := range chainToSend.Certificate {
|
|
|
|
certMsg.certificates = append(certMsg.certificates, certificateEntry{
|
|
|
|
data: certData,
|
|
|
|
})
|
|
|
|
}
|
2016-03-10 20:44:22 +00:00
|
|
|
}
|
|
|
|
hs.writeClientHash(certMsg.marshal())
|
|
|
|
c.writeRecord(recordTypeHandshake, certMsg.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-27 05:06:24 +00:00
|
|
|
preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
|
2014-06-20 20:00:00 +01:00
|
|
|
if err != nil {
|
|
|
|
c.sendAlert(alertInternalError)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if ckx != nil {
|
2014-07-22 03:42:34 +01:00
|
|
|
if c.config.Bugs.EarlyChangeCipherSpec < 2 {
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeClientHash(ckx.marshal())
|
2014-07-22 03:42:34 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
c.writeRecord(recordTypeHandshake, ckx.marshal())
|
|
|
|
}
|
|
|
|
|
2016-07-01 16:43:18 +01:00
|
|
|
if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
|
2014-10-11 00:23:43 +01:00
|
|
|
hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
|
|
|
|
c.extendedMasterSecret = true
|
|
|
|
} else {
|
|
|
|
if c.config.Bugs.RequireExtendedMasterSecret {
|
|
|
|
return errors.New("tls: extended master secret required but not supported by peer")
|
|
|
|
}
|
|
|
|
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
|
|
|
|
}
|
2014-08-28 04:13:20 +01:00
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
if chainToSend != nil {
|
|
|
|
certVerify := &certificateVerifyMsg{
|
2016-06-21 23:19:24 +01:00
|
|
|
hasSignatureAlgorithm: c.vers >= VersionTLS12,
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2015-03-16 21:49:43 +00:00
|
|
|
// Determine the hash to sign.
|
2016-06-21 23:19:24 +01:00
|
|
|
privKey := c.config.Certificates[0].PrivateKey
|
|
|
|
|
|
|
|
if certVerify.hasSignatureAlgorithm {
|
2016-07-10 05:02:01 +01:00
|
|
|
certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
|
2016-06-21 23:19:24 +01:00
|
|
|
if err != nil {
|
|
|
|
c.sendAlert(alertInternalError)
|
|
|
|
return err
|
|
|
|
}
|
2015-07-29 03:43:19 +01:00
|
|
|
}
|
2015-03-16 21:49:43 +00:00
|
|
|
|
2016-06-21 23:19:24 +01:00
|
|
|
if c.vers > VersionSSL30 {
|
2016-07-14 02:43:25 +01:00
|
|
|
certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
|
2016-07-09 00:28:04 +01:00
|
|
|
if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
|
|
|
|
certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
|
|
|
|
}
|
2016-06-21 23:19:24 +01:00
|
|
|
} else {
|
|
|
|
// SSL 3.0's client certificate construction is
|
|
|
|
// incompatible with signatureAlgorithm.
|
|
|
|
rsaKey, ok := privKey.(*rsa.PrivateKey)
|
|
|
|
if !ok {
|
|
|
|
err = errors.New("unsupported signature type for client certificate")
|
|
|
|
} else {
|
|
|
|
digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
|
2016-07-14 02:43:25 +01:00
|
|
|
if c.config.Bugs.InvalidSignature {
|
2016-06-21 23:19:24 +01:00
|
|
|
digest[0] ^= 0x80
|
|
|
|
}
|
|
|
|
certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
c.sendAlert(alertInternalError)
|
|
|
|
return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
|
|
|
|
}
|
|
|
|
|
2017-08-10 17:01:06 +01:00
|
|
|
if !c.config.Bugs.SkipCertificateVerify {
|
|
|
|
hs.writeClientHash(certVerify.marshal())
|
|
|
|
c.writeRecord(recordTypeHandshake, certVerify.marshal())
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2016-07-07 22:32:50 +01:00
|
|
|
// flushHandshake will be called in sendFinished.
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-08-28 04:13:20 +01:00
|
|
|
hs.finishedHash.discardHandshakeBuffer()
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-07-01 23:58:51 +01:00
|
|
|
func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
|
|
|
|
c := hs.c
|
|
|
|
|
|
|
|
if len(certMsg.certificates) == 0 {
|
|
|
|
c.sendAlert(alertIllegalParameter)
|
|
|
|
return errors.New("tls: no certificates sent")
|
|
|
|
}
|
|
|
|
|
|
|
|
certs := make([]*x509.Certificate, len(certMsg.certificates))
|
2016-11-01 17:39:36 +00:00
|
|
|
for i, certEntry := range certMsg.certificates {
|
|
|
|
cert, err := x509.ParseCertificate(certEntry.data)
|
2016-07-01 23:58:51 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-29 00:28:44 +01:00
|
|
|
publicKey := getCertificatePublicKey(certs[0])
|
|
|
|
switch publicKey.(type) {
|
|
|
|
case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
|
2016-07-01 23:58:51 +01:00
|
|
|
break
|
|
|
|
default:
|
|
|
|
c.sendAlert(alertUnsupportedCertificate)
|
2017-03-29 00:28:44 +01:00
|
|
|
return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", publicKey)
|
2016-07-01 23:58:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
c.peerCertificates = certs
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
func (hs *clientHandshakeState) establishKeys() error {
|
|
|
|
c := hs.c
|
|
|
|
|
|
|
|
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
|
2016-06-15 02:14:35 +01:00
|
|
|
keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))
|
2014-06-20 20:00:00 +01:00
|
|
|
var clientCipher, serverCipher interface{}
|
|
|
|
var clientHash, serverHash macFunction
|
|
|
|
if hs.suite.cipher != nil {
|
|
|
|
clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
|
|
|
|
clientHash = hs.suite.mac(c.vers, clientMAC)
|
|
|
|
serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
|
|
|
|
serverHash = hs.suite.mac(c.vers, serverMAC)
|
|
|
|
} else {
|
2016-06-15 02:14:35 +01:00
|
|
|
clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
|
|
|
|
serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2017-09-11 18:53:08 +01:00
|
|
|
c.in.prepareCipherSpec(c.wireVersion, serverCipher, serverHash)
|
|
|
|
c.out.prepareCipherSpec(c.wireVersion, clientCipher, clientHash)
|
2014-06-20 20:00:00 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-07-01 18:40:23 +01:00
|
|
|
func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
|
2014-06-20 20:00:00 +01:00
|
|
|
c := hs.c
|
|
|
|
|
2016-07-18 00:03:18 +01:00
|
|
|
if c.vers < VersionTLS13 {
|
2016-07-01 22:50:32 +01:00
|
|
|
if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
|
|
|
|
return errors.New("tls: renegotiation extension missing")
|
|
|
|
}
|
2016-07-01 18:40:23 +01:00
|
|
|
|
2016-07-01 22:50:32 +01:00
|
|
|
if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
|
|
|
|
var expectedRenegInfo []byte
|
|
|
|
expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
|
|
|
|
expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
|
|
|
|
if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return fmt.Errorf("tls: renegotiation mismatch")
|
|
|
|
}
|
2016-07-01 18:40:23 +01:00
|
|
|
}
|
2016-07-14 17:33:14 +01:00
|
|
|
} else if serverExtensions.secureRenegotiation != nil {
|
|
|
|
return errors.New("tls: renegotiation info sent in TLS 1.3")
|
2016-07-01 18:40:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
|
|
|
|
if serverExtensions.customExtension != *expected {
|
|
|
|
return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2014-09-15 21:51:51 +01:00
|
|
|
clientDidNPN := hs.hello.nextProtoNeg
|
|
|
|
clientDidALPN := len(hs.hello.alpnProtocols) > 0
|
2016-07-01 18:40:23 +01:00
|
|
|
serverHasNPN := serverExtensions.nextProtoNeg
|
|
|
|
serverHasALPN := len(serverExtensions.alpnProtocol) > 0
|
2014-09-15 21:51:51 +01:00
|
|
|
|
|
|
|
if !clientDidNPN && serverHasNPN {
|
2014-06-20 20:00:00 +01:00
|
|
|
c.sendAlert(alertHandshakeFailure)
|
2016-07-01 18:40:23 +01:00
|
|
|
return errors.New("server advertised unrequested NPN extension")
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2014-09-15 21:51:51 +01:00
|
|
|
if !clientDidALPN && serverHasALPN {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
2016-07-01 18:40:23 +01:00
|
|
|
return errors.New("server advertised unrequested ALPN extension")
|
2014-09-15 21:51:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if serverHasNPN && serverHasALPN {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
2016-07-01 18:40:23 +01:00
|
|
|
return errors.New("server advertised both NPN and ALPN extensions")
|
2014-09-15 21:51:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if serverHasALPN {
|
2016-07-01 18:40:23 +01:00
|
|
|
c.clientProtocol = serverExtensions.alpnProtocol
|
2014-09-15 21:51:51 +01:00
|
|
|
c.clientProtocolFallback = false
|
2014-09-06 18:21:53 +01:00
|
|
|
c.usedALPN = true
|
2014-09-15 21:51:51 +01:00
|
|
|
}
|
|
|
|
|
2016-07-18 00:03:18 +01:00
|
|
|
if serverHasNPN && c.vers >= VersionTLS13 {
|
2016-07-01 22:50:32 +01:00
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("server advertised NPN over TLS 1.3")
|
|
|
|
}
|
|
|
|
|
2016-07-01 18:40:23 +01:00
|
|
|
if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
|
2014-08-24 06:44:23 +01:00
|
|
|
c.sendAlert(alertHandshakeFailure)
|
2016-07-01 18:40:23 +01:00
|
|
|
return errors.New("server advertised unrequested Channel ID extension")
|
2014-08-24 06:44:23 +01:00
|
|
|
}
|
|
|
|
|
2017-09-21 23:02:22 +01:00
|
|
|
if len(serverExtensions.tokenBindingParams) == 1 {
|
|
|
|
found := false
|
|
|
|
for _, p := range c.config.TokenBindingParams {
|
|
|
|
if p == serverExtensions.tokenBindingParams[0] {
|
|
|
|
c.tokenBindingParam = p
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
return errors.New("tls: server advertised unsupported Token Binding key param")
|
|
|
|
}
|
|
|
|
if serverExtensions.tokenBindingVersion > c.config.TokenBindingVersion {
|
|
|
|
return errors.New("tls: server's Token Binding version is too new")
|
|
|
|
}
|
|
|
|
if c.vers < VersionTLS13 {
|
|
|
|
if !serverExtensions.extendedMasterSecret || serverExtensions.secureRenegotiation == nil {
|
|
|
|
return errors.New("server sent Token Binding without EMS or RI")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c.tokenBindingNegotiated = true
|
|
|
|
}
|
|
|
|
|
2016-07-18 00:03:18 +01:00
|
|
|
if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
|
2016-07-14 02:02:08 +01:00
|
|
|
return errors.New("tls: server advertised extended master secret over TLS 1.3")
|
|
|
|
}
|
|
|
|
|
2016-07-18 00:03:18 +01:00
|
|
|
if serverExtensions.ticketSupported && c.vers >= VersionTLS13 {
|
2016-07-11 18:19:03 +01:00
|
|
|
return errors.New("tls: server advertised ticket extension over TLS 1.3")
|
|
|
|
}
|
|
|
|
|
2016-11-01 17:39:36 +00:00
|
|
|
if serverExtensions.ocspStapling && c.vers >= VersionTLS13 {
|
|
|
|
return errors.New("tls: server advertised OCSP in ServerHello over TLS 1.3")
|
|
|
|
}
|
|
|
|
|
2016-11-16 00:01:48 +00:00
|
|
|
if serverExtensions.ocspStapling && c.config.Bugs.NoOCSPStapling {
|
|
|
|
return errors.New("tls: server advertised unrequested OCSP extension")
|
|
|
|
}
|
|
|
|
|
2016-11-01 17:39:36 +00:00
|
|
|
if len(serverExtensions.sctList) > 0 && c.vers >= VersionTLS13 {
|
|
|
|
return errors.New("tls: server advertised SCTs in ServerHello over TLS 1.3")
|
|
|
|
}
|
|
|
|
|
2016-11-16 00:01:48 +00:00
|
|
|
if len(serverExtensions.sctList) > 0 && c.config.Bugs.NoSignedCertificateTimestamps {
|
|
|
|
return errors.New("tls: server advertised unrequested SCTs")
|
|
|
|
}
|
|
|
|
|
2016-07-01 18:40:23 +01:00
|
|
|
if serverExtensions.srtpProtectionProfile != 0 {
|
|
|
|
if serverExtensions.srtpMasterKeyIdentifier != "" {
|
|
|
|
return errors.New("tls: server selected SRTP MKI value")
|
2014-11-16 00:06:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
found := false
|
|
|
|
for _, p := range c.config.SRTPProtectionProfiles {
|
2016-07-01 18:40:23 +01:00
|
|
|
if p == serverExtensions.srtpProtectionProfile {
|
2014-11-16 00:06:08 +00:00
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
2016-07-01 18:40:23 +01:00
|
|
|
return errors.New("tls: server advertised unsupported SRTP profile")
|
2014-11-16 00:06:08 +00:00
|
|
|
}
|
|
|
|
|
2016-07-01 18:40:23 +01:00
|
|
|
c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
|
2014-11-16 00:06:08 +00:00
|
|
|
}
|
|
|
|
|
2017-01-11 16:34:52 +00:00
|
|
|
if c.vers >= VersionTLS13 && c.didResume {
|
|
|
|
if c.config.Bugs.ExpectEarlyDataAccepted && !serverExtensions.hasEarlyData {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: server did not accept early data when expected")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !c.config.Bugs.ExpectEarlyDataAccepted && serverExtensions.hasEarlyData {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: server accepted early data when not expected")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-22 23:50:43 +00:00
|
|
|
if len(serverExtensions.quicTransportParams) > 0 {
|
|
|
|
if c.vers < VersionTLS13 {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: server sent QUIC transport params for TLS version less than 1.3")
|
|
|
|
}
|
|
|
|
c.quicTransportParams = serverExtensions.quicTransportParams
|
|
|
|
}
|
2018-02-26 21:51:55 +00:00
|
|
|
|
2016-07-01 18:40:23 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *clientHandshakeState) serverResumedSession() bool {
|
|
|
|
// If the server responded with the same sessionId then it means the
|
|
|
|
// sessionTicket is being used to resume a TLS session.
|
2017-02-09 19:07:17 +00:00
|
|
|
//
|
|
|
|
// Note that, if hs.hello.sessionId is a non-nil empty array, this will
|
|
|
|
// accept an empty session ID from the server as resumption. See
|
|
|
|
// EmptyTicketSessionID.
|
2016-07-01 18:40:23 +01:00
|
|
|
return hs.session != nil && hs.hello.sessionId != nil &&
|
|
|
|
bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
|
|
|
c := hs.c
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
if hs.serverResumedSession() {
|
2015-05-13 03:42:52 +01:00
|
|
|
// For test purposes, assert that the server never accepts the
|
|
|
|
// resumption offer on renegotiation.
|
|
|
|
if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
|
|
|
|
return false, errors.New("tls: server resumed session on renegotiation")
|
|
|
|
}
|
|
|
|
|
2016-07-01 16:43:18 +01:00
|
|
|
if hs.serverHello.extensions.sctList != nil {
|
2015-09-16 10:03:30 +01:00
|
|
|
return false, errors.New("tls: server sent SCT extension on session resumption")
|
|
|
|
}
|
|
|
|
|
2016-07-01 16:43:18 +01:00
|
|
|
if hs.serverHello.extensions.ocspStapling {
|
2015-09-16 10:03:30 +01:00
|
|
|
return false, errors.New("tls: server sent OCSP extension on session resumption")
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
// Restore masterSecret and peerCerts from previous state
|
|
|
|
hs.masterSecret = hs.session.masterSecret
|
|
|
|
c.peerCertificates = hs.session.serverCertificates
|
2014-10-11 00:23:43 +01:00
|
|
|
c.extendedMasterSecret = hs.session.extendedMasterSecret
|
2015-09-16 10:03:30 +01:00
|
|
|
c.sctList = hs.session.sctList
|
|
|
|
c.ocspResponse = hs.session.ocspResponse
|
2014-08-28 04:13:20 +01:00
|
|
|
hs.finishedHash.discardHandshakeBuffer()
|
2014-06-20 20:00:00 +01:00
|
|
|
return true, nil
|
|
|
|
}
|
2015-09-16 10:03:30 +01:00
|
|
|
|
2016-07-01 16:43:18 +01:00
|
|
|
if hs.serverHello.extensions.sctList != nil {
|
|
|
|
c.sctList = hs.serverHello.extensions.sctList
|
2015-09-16 10:03:30 +01:00
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2015-06-03 17:57:23 +01:00
|
|
|
func (hs *clientHandshakeState) readFinished(out []byte) error {
|
2014-06-20 20:00:00 +01:00
|
|
|
c := hs.c
|
|
|
|
|
|
|
|
c.readRecord(recordTypeChangeCipherSpec)
|
|
|
|
if err := c.in.error(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
msg, err := c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
serverFinished, ok := msg.(*finishedMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(serverFinished, msg)
|
|
|
|
}
|
|
|
|
|
2014-07-22 03:42:34 +01:00
|
|
|
if c.config.Bugs.EarlyChangeCipherSpec == 0 {
|
|
|
|
verify := hs.finishedHash.serverSum(hs.masterSecret)
|
|
|
|
if len(verify) != len(serverFinished.verifyData) ||
|
|
|
|
subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
|
|
|
|
c.sendAlert(alertHandshakeFailure)
|
|
|
|
return errors.New("tls: server's Finished message was incorrect")
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-10-29 00:29:33 +00:00
|
|
|
c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
|
2015-06-03 17:57:23 +01:00
|
|
|
copy(out, serverFinished.verifyData)
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeServerHash(serverFinished.marshal())
|
2014-06-20 20:00:00 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *clientHandshakeState) readSessionTicket() error {
|
2014-11-17 08:19:02 +00:00
|
|
|
c := hs.c
|
|
|
|
|
|
|
|
// Create a session with no server identifier. Either a
|
|
|
|
// session ID or session ticket will be attached.
|
|
|
|
session := &ClientSessionState{
|
|
|
|
vers: c.vers,
|
2017-10-11 17:29:36 +01:00
|
|
|
wireVersion: c.wireVersion,
|
2014-11-17 08:19:02 +00:00
|
|
|
cipherSuite: hs.suite.id,
|
|
|
|
masterSecret: hs.masterSecret,
|
2016-10-17 23:05:35 +01:00
|
|
|
handshakeHash: hs.finishedHash.Sum(),
|
2014-11-17 08:19:02 +00:00
|
|
|
serverCertificates: c.peerCertificates,
|
2015-09-16 10:03:30 +01:00
|
|
|
sctList: c.sctList,
|
|
|
|
ocspResponse: c.ocspResponse,
|
2016-07-26 00:16:28 +01:00
|
|
|
ticketExpiration: c.config.time().Add(time.Duration(7 * 24 * time.Hour)),
|
2014-11-17 08:19:02 +00:00
|
|
|
}
|
|
|
|
|
2016-07-01 16:43:18 +01:00
|
|
|
if !hs.serverHello.extensions.ticketSupported {
|
2015-06-16 19:16:23 +01:00
|
|
|
if c.config.Bugs.ExpectNewTicket {
|
|
|
|
return errors.New("tls: expected new ticket")
|
|
|
|
}
|
2014-11-17 08:19:02 +00:00
|
|
|
if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
|
|
|
|
session.sessionId = hs.serverHello.sessionId
|
|
|
|
hs.session = session
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-10-10 00:32:41 +01:00
|
|
|
if c.vers == VersionSSL30 {
|
|
|
|
return errors.New("tls: negotiated session tickets in SSL 3.0")
|
|
|
|
}
|
2018-07-18 02:26:05 +01:00
|
|
|
if c.config.Bugs.ExpectNoNewSessionTicket {
|
|
|
|
return errors.New("tls: received unexpected NewSessionTicket")
|
|
|
|
}
|
2015-10-10 00:32:41 +01:00
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
msg, err := c.readHandshake()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
|
|
|
|
if !ok {
|
|
|
|
c.sendAlert(alertUnexpectedMessage)
|
|
|
|
return unexpectedMessageError(sessionTicketMsg, msg)
|
|
|
|
}
|
|
|
|
|
2014-11-17 08:19:02 +00:00
|
|
|
session.sessionTicket = sessionTicketMsg.ticket
|
|
|
|
hs.session = session
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-08-24 06:44:23 +01:00
|
|
|
hs.writeServerHash(sessionTicketMsg.marshal())
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-06-03 17:57:23 +01:00
|
|
|
func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
|
2014-06-20 20:00:00 +01:00
|
|
|
c := hs.c
|
|
|
|
|
2016-07-15 05:39:56 +01:00
|
|
|
var postCCSMsgs [][]byte
|
2014-08-04 06:23:53 +01:00
|
|
|
seqno := hs.c.sendHandshakeSeq
|
2016-07-01 16:43:18 +01:00
|
|
|
if hs.serverHello.extensions.nextProtoNeg {
|
2014-06-20 20:00:00 +01:00
|
|
|
nextProto := new(nextProtoMsg)
|
2016-07-01 16:43:18 +01:00
|
|
|
proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
|
2014-06-20 20:00:00 +01:00
|
|
|
nextProto.proto = proto
|
|
|
|
c.clientProtocol = proto
|
|
|
|
c.clientProtocolFallback = fallback
|
|
|
|
|
2014-07-21 21:14:03 +01:00
|
|
|
nextProtoBytes := nextProto.marshal()
|
2014-08-04 06:23:53 +01:00
|
|
|
hs.writeHash(nextProtoBytes, seqno)
|
|
|
|
seqno++
|
2016-07-15 05:39:56 +01:00
|
|
|
postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2016-07-01 16:43:18 +01:00
|
|
|
if hs.serverHello.extensions.channelIDRequested {
|
2014-08-24 06:44:23 +01:00
|
|
|
var resumeHash []byte
|
|
|
|
if isResume {
|
|
|
|
resumeHash = hs.session.handshakeHash
|
|
|
|
}
|
2016-09-24 00:25:11 +01:00
|
|
|
channelIDMsgBytes, err := hs.writeChannelIDMessage(hs.finishedHash.hashForChannelID(resumeHash))
|
2014-08-24 06:44:23 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-06-30 23:56:53 +01:00
|
|
|
hs.writeHash(channelIDMsgBytes, seqno)
|
2014-08-24 06:44:23 +01:00
|
|
|
seqno++
|
2016-07-15 05:39:56 +01:00
|
|
|
postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
|
2014-08-24 06:44:23 +01:00
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
finished := new(finishedMsg)
|
2014-07-22 03:42:34 +01:00
|
|
|
if c.config.Bugs.EarlyChangeCipherSpec == 2 {
|
|
|
|
finished.verifyData = hs.finishedHash.clientSum(nil)
|
|
|
|
} else {
|
|
|
|
finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
|
|
|
|
}
|
2015-06-03 17:57:23 +01:00
|
|
|
copy(out, finished.verifyData)
|
2015-04-03 00:33:31 +01:00
|
|
|
if c.config.Bugs.BadFinished {
|
|
|
|
finished.verifyData[0]++
|
|
|
|
}
|
2014-10-29 00:29:33 +00:00
|
|
|
c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
|
Add DTLS timeout and retransmit tests.
This extends the packet adaptor protocol to send three commands:
type command =
| Packet of []byte
| Timeout of time.Duration
| TimeoutAck
When the shim processes a Timeout in BIO_read, it sends TimeoutAck, fails the
BIO_read, returns out of the SSL stack, advances the clock, calls
DTLSv1_handle_timeout, and continues.
If the Go side sends Timeout right between sending handshake flight N and
reading flight N+1, the shim won't read the Timeout until it has sent flight
N+1 (it only processes packet commands in BIO_read), so the TimeoutAck comes
after N+1. Go then drops all packets before the TimeoutAck, thus dropping one
transmit of flight N+1 without having to actually process the packets to
determine the end of the flight. The shim then sees the updated clock, calls
DTLSv1_handle_timeout, and re-sends flight N+1 for Go to process for real.
When dropping packets, Go checks the epoch and increments sequence numbers so
that we can continue to be strict here. This requires tracking the initial
sequence number of the next epoch.
The final Finished message takes an additional special-case to test. DTLS
triggers retransmits on either a timeout or seeing a stale flight. OpenSSL only
implements the former which should be sufficient (and is necessary) EXCEPT for
the final Finished message. If the peer's final Finished message is lost, it
won't be waiting for a message from us, so it won't time out anything. That
retransmit must be triggered on stale message, so we retransmit the Finished
message in Go.
Change-Id: I3ffbdb1de525beb2ee831b304670a3387877634c
Reviewed-on: https://boringssl-review.googlesource.com/3212
Reviewed-by: Adam Langley <agl@google.com>
2015-01-27 06:09:43 +00:00
|
|
|
hs.finishedBytes = finished.marshal()
|
|
|
|
hs.writeHash(hs.finishedBytes, seqno)
|
2016-07-15 05:39:56 +01:00
|
|
|
postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
|
2014-07-21 21:14:03 +01:00
|
|
|
|
|
|
|
if c.config.Bugs.FragmentAcrossChangeCipherSpec {
|
2016-07-15 05:39:56 +01:00
|
|
|
c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
|
|
|
|
postCCSMsgs[0] = postCCSMsgs[0][5:]
|
2016-07-15 04:10:43 +01:00
|
|
|
} else if c.config.Bugs.SendUnencryptedFinished {
|
2016-07-15 05:39:56 +01:00
|
|
|
c.writeRecord(recordTypeHandshake, postCCSMsgs[0])
|
|
|
|
postCCSMsgs = postCCSMsgs[1:]
|
2014-07-21 21:14:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if !c.config.Bugs.SkipChangeCipherSpec &&
|
|
|
|
c.config.Bugs.EarlyChangeCipherSpec == 0 {
|
2015-11-26 17:07:28 +00:00
|
|
|
ccs := []byte{1}
|
|
|
|
if c.config.Bugs.BadChangeCipherSpec != nil {
|
|
|
|
ccs = c.config.Bugs.BadChangeCipherSpec
|
|
|
|
}
|
|
|
|
c.writeRecord(recordTypeChangeCipherSpec, ccs)
|
2014-07-21 21:14:03 +01:00
|
|
|
}
|
|
|
|
|
2015-01-26 04:52:39 +00:00
|
|
|
if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
|
|
|
|
c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
|
|
|
|
}
|
2015-03-12 19:09:02 +00:00
|
|
|
if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
|
|
|
|
c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
|
|
|
|
return errors.New("tls: simulating post-CCS alert")
|
|
|
|
}
|
2015-01-26 04:52:39 +00:00
|
|
|
|
2016-07-15 05:39:56 +01:00
|
|
|
if !c.config.Bugs.SkipFinished {
|
|
|
|
for _, msg := range postCCSMsgs {
|
|
|
|
c.writeRecord(recordTypeHandshake, msg)
|
|
|
|
}
|
2016-07-27 22:40:37 +01:00
|
|
|
|
|
|
|
if c.config.Bugs.SendExtraFinished {
|
|
|
|
c.writeRecord(recordTypeHandshake, finished.marshal())
|
|
|
|
}
|
2015-01-31 22:16:01 +00:00
|
|
|
}
|
2017-06-26 03:42:55 +01:00
|
|
|
|
2017-10-12 22:14:45 +01:00
|
|
|
if !isResume || !c.config.Bugs.PackAppDataWithHandshake {
|
|
|
|
c.flushHandshake()
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-09-24 00:25:11 +01:00
|
|
|
func (hs *clientHandshakeState) writeChannelIDMessage(channelIDHash []byte) ([]byte, error) {
|
|
|
|
c := hs.c
|
|
|
|
channelIDMsg := new(channelIDMsg)
|
|
|
|
if c.config.ChannelID.Curve != elliptic.P256() {
|
|
|
|
return nil, fmt.Errorf("tls: Channel ID is not on P-256.")
|
|
|
|
}
|
|
|
|
r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, channelIDHash)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
channelID := make([]byte, 128)
|
|
|
|
writeIntPadded(channelID[0:32], c.config.ChannelID.X)
|
|
|
|
writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
|
|
|
|
writeIntPadded(channelID[64:96], r)
|
|
|
|
writeIntPadded(channelID[96:128], s)
|
|
|
|
if c.config.Bugs.InvalidChannelIDSignature {
|
|
|
|
channelID[64] ^= 1
|
|
|
|
}
|
|
|
|
channelIDMsg.channelID = channelID
|
|
|
|
|
|
|
|
c.channelID = &c.config.ChannelID.PublicKey
|
|
|
|
|
|
|
|
return channelIDMsg.marshal(), nil
|
|
|
|
}
|
|
|
|
|
2014-08-04 06:23:53 +01:00
|
|
|
func (hs *clientHandshakeState) writeClientHash(msg []byte) {
|
|
|
|
// writeClientHash is called before writeRecord.
|
|
|
|
hs.writeHash(msg, hs.c.sendHandshakeSeq)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *clientHandshakeState) writeServerHash(msg []byte) {
|
|
|
|
// writeServerHash is called after readHandshake.
|
|
|
|
hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
|
|
|
|
if hs.c.isDTLS {
|
|
|
|
// This is somewhat hacky. DTLS hashes a slightly different format.
|
|
|
|
// First, the TLS header.
|
|
|
|
hs.finishedHash.Write(msg[:4])
|
|
|
|
// Then the sequence number and reassembled fragment offset (always 0).
|
|
|
|
hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
|
|
|
|
// Then the reassembled fragment (always equal to the message length).
|
|
|
|
hs.finishedHash.Write(msg[1:4])
|
|
|
|
// And then the message body.
|
|
|
|
hs.finishedHash.Write(msg[4:])
|
|
|
|
} else {
|
|
|
|
hs.finishedHash.Write(msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-01 23:44:02 +01:00
|
|
|
// selectClientCertificate selects a certificate for use with the given
|
|
|
|
// certificate, or none if none match. It may return a particular certificate or
|
|
|
|
// nil on success, or an error on internal error.
|
|
|
|
func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
|
2017-08-29 20:50:58 +01:00
|
|
|
if len(c.config.Certificates) == 0 {
|
|
|
|
return nil, nil
|
2016-07-01 23:44:02 +01:00
|
|
|
}
|
|
|
|
|
2017-08-29 20:50:58 +01:00
|
|
|
// The test is assumed to have configured the certificate it meant to
|
|
|
|
// send.
|
|
|
|
if len(c.config.Certificates) > 1 {
|
|
|
|
return nil, errors.New("tls: multiple certificates configured")
|
2016-07-01 23:44:02 +01:00
|
|
|
}
|
|
|
|
|
2017-08-29 20:50:58 +01:00
|
|
|
return &c.config.Certificates[0], nil
|
2016-07-01 23:44:02 +01:00
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
// clientSessionCacheKey returns a key used to cache sessionTickets that could
|
|
|
|
// be used to resume previously negotiated TLS sessions with a server.
|
|
|
|
func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
|
|
|
|
if len(config.ServerName) > 0 {
|
|
|
|
return config.ServerName
|
|
|
|
}
|
|
|
|
return serverAddr.String()
|
|
|
|
}
|
|
|
|
|
2014-09-15 21:51:51 +01:00
|
|
|
// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
|
|
|
|
// given list of possible protocols and a list of the preference order. The
|
|
|
|
// first list must not be empty. It returns the resulting protocol and flag
|
2014-06-20 20:00:00 +01:00
|
|
|
// indicating if the fallback case was reached.
|
2014-09-15 21:51:51 +01:00
|
|
|
func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
|
|
|
|
for _, s := range preferenceProtos {
|
|
|
|
for _, c := range protos {
|
2014-06-20 20:00:00 +01:00
|
|
|
if s == c {
|
|
|
|
return s, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-15 21:51:51 +01:00
|
|
|
return protos[0], true
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-08-24 06:44:23 +01:00
|
|
|
|
|
|
|
// writeIntPadded writes x into b, padded up with leading zeros as
|
|
|
|
// needed.
|
|
|
|
func writeIntPadded(b []byte, x *big.Int) {
|
|
|
|
for i := range b {
|
|
|
|
b[i] = 0
|
|
|
|
}
|
|
|
|
xb := x.Bytes()
|
|
|
|
copy(b[len(b)-len(xb):], xb)
|
|
|
|
}
|
2016-11-01 17:39:36 +00:00
|
|
|
|
2017-10-11 17:29:36 +01:00
|
|
|
func generatePSKBinders(version uint16, hello *clientHelloMsg, pskCipherSuite *cipherSuite, psk, firstClientHello, helloRetryRequest []byte, config *Config) {
|
2016-11-01 17:39:36 +00:00
|
|
|
if config.Bugs.SendNoPSKBinder {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
binderLen := pskCipherSuite.hash().Size()
|
|
|
|
if config.Bugs.SendShortPSKBinder {
|
|
|
|
binderLen--
|
|
|
|
}
|
|
|
|
|
2016-12-01 21:47:56 +00:00
|
|
|
numBinders := 1
|
|
|
|
if config.Bugs.SendExtraPSKBinder {
|
|
|
|
numBinders++
|
|
|
|
}
|
|
|
|
|
2016-11-01 17:39:36 +00:00
|
|
|
// Fill hello.pskBinders with appropriate length arrays of zeros so the
|
|
|
|
// length prefixes are correct when computing the binder over the truncated
|
|
|
|
// ClientHello message.
|
2016-12-01 21:47:56 +00:00
|
|
|
hello.pskBinders = make([][]byte, numBinders)
|
|
|
|
for i := range hello.pskBinders {
|
2016-11-01 17:39:36 +00:00
|
|
|
hello.pskBinders[i] = make([]byte, binderLen)
|
|
|
|
}
|
|
|
|
|
|
|
|
helloBytes := hello.marshal()
|
|
|
|
binderSize := len(hello.pskBinders)*(binderLen+1) + 2
|
|
|
|
truncatedHello := helloBytes[:len(helloBytes)-binderSize]
|
2018-01-22 20:20:31 +00:00
|
|
|
binder := computePSKBinder(psk, version, resumptionPSKBinderLabel, pskCipherSuite, firstClientHello, helloRetryRequest, truncatedHello)
|
2016-11-01 17:39:36 +00:00
|
|
|
if config.Bugs.SendShortPSKBinder {
|
|
|
|
binder = binder[:binderLen]
|
|
|
|
}
|
|
|
|
if config.Bugs.SendInvalidPSKBinder {
|
|
|
|
binder[0] ^= 1
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range hello.pskBinders {
|
|
|
|
hello.pskBinders[i] = binder
|
|
|
|
}
|
|
|
|
|
|
|
|
hello.raw = nil
|
|
|
|
}
|