blob: d074778c030c8eb8ade951dc6adea92dca6b7acd [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Adam Langleydc7e9c42015-09-29 15:21:04 -07005package runner
Adam Langley95c29f32014-06-20 12:00:00 -07006
7import (
8 "bytes"
Nick Harper60edffd2016-06-21 15:19:24 -07009 "crypto"
Adam Langley95c29f32014-06-20 12:00:00 -070010 "crypto/ecdsa"
David Benjamind30a9902014-08-24 01:44:23 -040011 "crypto/elliptic"
Adam Langley95c29f32014-06-20 12:00:00 -070012 "crypto/rsa"
13 "crypto/subtle"
14 "crypto/x509"
Adam Langley95c29f32014-06-20 12:00:00 -070015 "errors"
16 "fmt"
17 "io"
David Benjaminde620d92014-07-18 15:03:41 -040018 "math/big"
Adam Langley95c29f32014-06-20 12:00:00 -070019 "net"
20 "strconv"
Nick Harper0b3625b2016-07-25 16:16:28 -070021 "time"
Adam Langley95c29f32014-06-20 12:00:00 -070022)
23
24type clientHandshakeState struct {
David Benjamin83f90402015-01-27 01:09:43 -050025 c *Conn
26 serverHello *serverHelloMsg
27 hello *clientHelloMsg
28 suite *cipherSuite
29 finishedHash finishedHash
Nick Harperb41d2e42016-07-01 17:50:32 -040030 keyShares map[CurveID]ecdhCurve
David Benjamin83f90402015-01-27 01:09:43 -050031 masterSecret []byte
32 session *ClientSessionState
33 finishedBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070034}
35
36func (c *Conn) clientHandshake() error {
37 if c.config == nil {
38 c.config = defaultConfig()
39 }
40
41 if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
42 return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
43 }
44
David Benjamin83c0bc92014-08-04 01:23:53 -040045 c.sendHandshakeSeq = 0
46 c.recvHandshakeSeq = 0
47
David Benjaminfa055a22014-09-15 16:51:51 -040048 nextProtosLength := 0
49 for _, proto := range c.config.NextProtos {
Adam Langleyefb0e162015-07-09 11:35:04 -070050 if l := len(proto); l > 255 {
David Benjaminfa055a22014-09-15 16:51:51 -040051 return errors.New("tls: invalid NextProtos value")
52 } else {
53 nextProtosLength += 1 + l
54 }
55 }
56 if nextProtosLength > 0xffff {
57 return errors.New("tls: NextProtos values too large")
58 }
59
Steven Valdezfdd10992016-09-15 16:27:05 -040060 minVersion := c.config.minVersion(c.isDTLS)
David Benjamin3c6a1ea2016-09-26 18:30:05 -040061 maxVersion := c.config.maxVersion(c.isDTLS)
Adam Langley95c29f32014-06-20 12:00:00 -070062 hello := &clientHelloMsg{
David Benjaminca6c8262014-11-15 19:06:08 -050063 isDTLS: c.isDTLS,
David Benjamin3c6a1ea2016-09-26 18:30:05 -040064 vers: versionToWire(maxVersion, c.isDTLS),
David Benjaminca6c8262014-11-15 19:06:08 -050065 compressionMethods: []uint8{compressionNone},
66 random: make([]byte, 32),
David Benjamin53210cb2016-11-16 09:01:48 +090067 ocspStapling: !c.config.Bugs.NoOCSPStapling,
68 sctListSupported: !c.config.Bugs.NoSignedCertificateTimestamps,
David Benjaminca6c8262014-11-15 19:06:08 -050069 serverName: c.config.ServerName,
70 supportedCurves: c.config.curvePreferences(),
Steven Valdeza833c352016-11-01 13:39:36 -040071 pskKEModes: []byte{pskDHEKEMode},
David Benjaminca6c8262014-11-15 19:06:08 -050072 supportedPoints: []uint8{pointFormatUncompressed},
73 nextProtoNeg: len(c.config.NextProtos) > 0,
74 secureRenegotiation: []byte{},
75 alpnProtocols: c.config.NextProtos,
76 duplicateExtension: c.config.Bugs.DuplicateExtension,
77 channelIDSupported: c.config.ChannelID != nil,
Steven Valdeza833c352016-11-01 13:39:36 -040078 npnAfterAlpn: c.config.Bugs.SwapNPNAndALPN,
Steven Valdezfdd10992016-09-15 16:27:05 -040079 extendedMasterSecret: maxVersion >= VersionTLS10,
David Benjaminca6c8262014-11-15 19:06:08 -050080 srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
81 srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
Adam Langley09505632015-07-30 18:10:13 -070082 customExtension: c.config.Bugs.CustomExtension,
Steven Valdeza833c352016-11-01 13:39:36 -040083 pskBinderFirst: c.config.Bugs.PSKBinderFirst,
Adam Langley95c29f32014-06-20 12:00:00 -070084 }
85
David Benjamin163c9562016-08-29 23:14:17 -040086 disableEMS := c.config.Bugs.NoExtendedMasterSecret
87 if c.cipherSuite != nil {
88 disableEMS = c.config.Bugs.NoExtendedMasterSecretOnRenegotiation
89 }
90
91 if disableEMS {
Adam Langley75712922014-10-10 16:23:43 -070092 hello.extendedMasterSecret = false
93 }
94
David Benjamin55a43642015-04-20 14:45:55 -040095 if c.config.Bugs.NoSupportedCurves {
96 hello.supportedCurves = nil
97 }
98
Steven Valdeza833c352016-11-01 13:39:36 -040099 if len(c.config.Bugs.SendPSKKeyExchangeModes) != 0 {
100 hello.pskKEModes = c.config.Bugs.SendPSKKeyExchangeModes
101 }
102
David Benjaminc241d792016-09-09 10:34:20 -0400103 if c.config.Bugs.SendCompressionMethods != nil {
104 hello.compressionMethods = c.config.Bugs.SendCompressionMethods
105 }
106
Adam Langley2ae77d22014-10-28 17:29:33 -0700107 if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
108 if c.config.Bugs.BadRenegotiationInfo {
109 hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
110 hello.secureRenegotiation[0] ^= 0x80
111 } else {
112 hello.secureRenegotiation = c.clientVerify
113 }
114 }
115
David Benjamin3e052de2015-11-25 20:10:31 -0500116 if c.noRenegotiationInfo() {
David Benjaminca6554b2014-11-08 12:31:52 -0500117 hello.secureRenegotiation = nil
118 }
119
Nick Harperb41d2e42016-07-01 17:50:32 -0400120 var keyShares map[CurveID]ecdhCurve
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400121 if maxVersion >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400122 keyShares = make(map[CurveID]ecdhCurve)
Nick Harperdcfbc672016-07-16 17:47:31 +0200123 hello.hasKeyShares = true
David Benjamin7e1f9842016-09-20 19:24:40 -0400124 hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
Nick Harperdcfbc672016-07-16 17:47:31 +0200125 curvesToSend := c.config.defaultCurves()
Nick Harperb41d2e42016-07-01 17:50:32 -0400126 for _, curveID := range hello.supportedCurves {
Nick Harperdcfbc672016-07-16 17:47:31 +0200127 if !curvesToSend[curveID] {
128 continue
129 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400130 curve, ok := curveForCurveID(curveID)
131 if !ok {
132 continue
133 }
134 publicKey, err := curve.offer(c.config.rand())
135 if err != nil {
136 return err
137 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400138
139 if c.config.Bugs.SendCurve != 0 {
140 curveID = c.config.Bugs.SendCurve
141 }
142 if c.config.Bugs.InvalidECDHPoint {
143 publicKey[0] ^= 0xff
144 }
145
Nick Harperb41d2e42016-07-01 17:50:32 -0400146 hello.keyShares = append(hello.keyShares, keyShareEntry{
147 group: curveID,
148 keyExchange: publicKey,
149 })
150 keyShares[curveID] = curve
Steven Valdez143e8b32016-07-11 13:19:03 -0400151
152 if c.config.Bugs.DuplicateKeyShares {
153 hello.keyShares = append(hello.keyShares, hello.keyShares[len(hello.keyShares)-1])
154 }
155 }
156
157 if c.config.Bugs.MissingKeyShare {
Steven Valdez5440fe02016-07-18 12:40:30 -0400158 hello.hasKeyShares = false
Nick Harperb41d2e42016-07-01 17:50:32 -0400159 }
160 }
161
Adam Langley95c29f32014-06-20 12:00:00 -0700162 possibleCipherSuites := c.config.cipherSuites()
163 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
164
165NextCipherSuite:
166 for _, suiteId := range possibleCipherSuites {
167 for _, suite := range cipherSuites {
168 if suite.id != suiteId {
169 continue
170 }
David Benjamin5ecb88b2016-10-04 17:51:35 -0400171 // Don't advertise TLS 1.2-only cipher suites unless
172 // we're attempting TLS 1.2.
173 if maxVersion < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
174 continue
175 }
176 // Don't advertise non-DTLS cipher suites in DTLS.
177 if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
178 continue
David Benjamin83c0bc92014-08-04 01:23:53 -0400179 }
Adam Langley95c29f32014-06-20 12:00:00 -0700180 hello.cipherSuites = append(hello.cipherSuites, suiteId)
181 continue NextCipherSuite
182 }
183 }
184
David Benjamin5ecb88b2016-10-04 17:51:35 -0400185 if c.config.Bugs.AdvertiseAllConfiguredCiphers {
186 hello.cipherSuites = possibleCipherSuites
187 }
188
Adam Langley5021b222015-06-12 18:27:58 -0700189 if c.config.Bugs.SendRenegotiationSCSV {
190 hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
191 }
192
David Benjaminbef270a2014-08-02 04:22:02 -0400193 if c.config.Bugs.SendFallbackSCSV {
194 hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
195 }
196
Adam Langley95c29f32014-06-20 12:00:00 -0700197 _, err := io.ReadFull(c.config.rand(), hello.random)
198 if err != nil {
199 c.sendAlert(alertInternalError)
200 return errors.New("tls: short read from Rand: " + err.Error())
201 }
202
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400203 if maxVersion >= VersionTLS12 && !c.config.Bugs.NoSignatureAlgorithms {
David Benjamin7a41d372016-07-09 11:21:54 -0700204 hello.signatureAlgorithms = c.config.verifySignatureAlgorithms()
Adam Langley95c29f32014-06-20 12:00:00 -0700205 }
206
207 var session *ClientSessionState
208 var cacheKey string
209 sessionCache := c.config.ClientSessionCache
Adam Langley95c29f32014-06-20 12:00:00 -0700210
211 if sessionCache != nil {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500212 hello.ticketSupported = !c.config.SessionTicketsDisabled
Adam Langley95c29f32014-06-20 12:00:00 -0700213
214 // Try to resume a previously negotiated TLS session, if
215 // available.
216 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
Nick Harper0b3625b2016-07-25 16:16:28 -0700217 // TODO(nharper): Support storing more than one session
218 // ticket for TLS 1.3.
Adam Langley95c29f32014-06-20 12:00:00 -0700219 candidateSession, ok := sessionCache.Get(cacheKey)
220 if ok {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500221 ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
222
Adam Langley95c29f32014-06-20 12:00:00 -0700223 // Check that the ciphersuite/version used for the
224 // previous session are still valid.
225 cipherSuiteOk := false
David Benjamin2b02f4b2016-11-16 16:11:47 +0900226 if candidateSession.vers <= VersionTLS12 {
227 for _, id := range hello.cipherSuites {
228 if id == candidateSession.cipherSuite {
229 cipherSuiteOk = true
230 break
231 }
Adam Langley95c29f32014-06-20 12:00:00 -0700232 }
David Benjamin2b02f4b2016-11-16 16:11:47 +0900233 } else {
234 // TLS 1.3 allows the cipher to change on
235 // resumption.
236 cipherSuiteOk = true
Adam Langley95c29f32014-06-20 12:00:00 -0700237 }
238
Steven Valdezfdd10992016-09-15 16:27:05 -0400239 versOk := candidateSession.vers >= minVersion &&
240 candidateSession.vers <= maxVersion
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500241 if ticketOk && versOk && cipherSuiteOk {
Adam Langley95c29f32014-06-20 12:00:00 -0700242 session = candidateSession
243 }
244 }
245 }
246
Steven Valdeza833c352016-11-01 13:39:36 -0400247 var pskCipherSuite *cipherSuite
Nick Harper0b3625b2016-07-25 16:16:28 -0700248 if session != nil && c.config.time().Before(session.ticketExpiration) {
David Benjamind5a4ecb2016-07-18 01:17:13 +0200249 ticket := session.sessionTicket
David Benjamin4199b0d2016-11-01 13:58:25 -0400250 if c.config.Bugs.FilterTicket != nil && len(ticket) > 0 {
251 // Copy the ticket so FilterTicket may act in-place.
David Benjamind5a4ecb2016-07-18 01:17:13 +0200252 ticket = make([]byte, len(session.sessionTicket))
253 copy(ticket, session.sessionTicket)
David Benjamin4199b0d2016-11-01 13:58:25 -0400254
255 ticket, err = c.config.Bugs.FilterTicket(ticket)
256 if err != nil {
257 return err
Adam Langley38311732014-10-16 19:04:35 -0700258 }
David Benjamind5a4ecb2016-07-18 01:17:13 +0200259 }
260
David Benjamin405da482016-08-08 17:25:07 -0400261 if session.vers >= VersionTLS13 || c.config.Bugs.SendBothTickets {
Steven Valdeza833c352016-11-01 13:39:36 -0400262 pskCipherSuite = cipherSuiteFromID(session.cipherSuite)
263 if pskCipherSuite == nil {
264 return errors.New("tls: client session cache has invalid cipher suite")
265 }
Nick Harper0b3625b2016-07-25 16:16:28 -0700266 // TODO(nharper): Support sending more
267 // than one PSK identity.
Steven Valdeza833c352016-11-01 13:39:36 -0400268 ticketAge := uint32(c.config.time().Sub(session.ticketCreationTime) / time.Millisecond)
Steven Valdez5b986082016-09-01 12:29:49 -0400269 psk := pskIdentity{
Steven Valdeza833c352016-11-01 13:39:36 -0400270 ticket: ticket,
271 obfuscatedTicketAge: session.ticketAgeAdd + ticketAge,
Nick Harper0b3625b2016-07-25 16:16:28 -0700272 }
Steven Valdez5b986082016-09-01 12:29:49 -0400273 hello.pskIdentities = []pskIdentity{psk}
Steven Valdezaf3b8a92016-11-01 12:49:22 -0400274
275 if c.config.Bugs.ExtraPSKIdentity {
276 hello.pskIdentities = append(hello.pskIdentities, psk)
277 }
David Benjamin405da482016-08-08 17:25:07 -0400278 }
279
280 if session.vers < VersionTLS13 || c.config.Bugs.SendBothTickets {
281 if ticket != nil {
282 hello.sessionTicket = ticket
283 // A random session ID is used to detect when the
284 // server accepted the ticket and is resuming a session
285 // (see RFC 5077).
286 sessionIdLen := 16
287 if c.config.Bugs.OversizedSessionId {
288 sessionIdLen = 33
289 }
290 hello.sessionId = make([]byte, sessionIdLen)
291 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
292 c.sendAlert(alertInternalError)
293 return errors.New("tls: short read from Rand: " + err.Error())
294 }
295 } else {
296 hello.sessionId = session.sessionId
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500297 }
Adam Langley95c29f32014-06-20 12:00:00 -0700298 }
299 }
300
Steven Valdezfdd10992016-09-15 16:27:05 -0400301 if maxVersion == VersionTLS13 && !c.config.Bugs.OmitSupportedVersions {
302 if hello.vers >= VersionTLS13 {
303 hello.vers = VersionTLS12
304 }
305 for version := maxVersion; version >= minVersion; version-- {
306 hello.supportedVersions = append(hello.supportedVersions, versionToWire(version, c.isDTLS))
307 }
308 }
309
310 if len(c.config.Bugs.SendSupportedVersions) > 0 {
311 hello.supportedVersions = c.config.Bugs.SendSupportedVersions
312 }
313
David Benjamineed24012016-08-13 19:26:00 -0400314 if c.config.Bugs.SendClientVersion != 0 {
315 hello.vers = c.config.Bugs.SendClientVersion
316 }
317
David Benjamin75f99142016-11-12 12:36:06 +0900318 if c.config.Bugs.SendCipherSuites != nil {
319 hello.cipherSuites = c.config.Bugs.SendCipherSuites
320 }
321
David Benjamind86c7672014-08-02 04:07:12 -0400322 var helloBytes []byte
323 if c.config.Bugs.SendV2ClientHello {
David Benjamin94d701b2014-11-30 13:54:41 -0500324 // Test that the peer left-pads random.
325 hello.random[0] = 0
David Benjamind86c7672014-08-02 04:07:12 -0400326 v2Hello := &v2ClientHelloMsg{
327 vers: hello.vers,
328 cipherSuites: hello.cipherSuites,
329 // No session resumption for V2ClientHello.
330 sessionId: nil,
David Benjamin94d701b2014-11-30 13:54:41 -0500331 challenge: hello.random[1:],
David Benjamind86c7672014-08-02 04:07:12 -0400332 }
333 helloBytes = v2Hello.marshal()
334 c.writeV2Record(helloBytes)
335 } else {
Steven Valdeza833c352016-11-01 13:39:36 -0400336 if len(hello.pskIdentities) > 0 {
337 generatePSKBinders(hello, pskCipherSuite, session.masterSecret, []byte{}, c.config)
338 }
David Benjamind86c7672014-08-02 04:07:12 -0400339 helloBytes = hello.marshal()
Steven Valdeza833c352016-11-01 13:39:36 -0400340
David Benjamin7964b182016-07-14 23:36:30 -0400341 if c.config.Bugs.PartialClientFinishedWithClientHello {
342 // Include one byte of Finished. We can compute it
343 // without completing the handshake. This assumes we
344 // negotiate TLS 1.3 with no HelloRetryRequest or
345 // CertificateRequest.
346 toWrite := make([]byte, 0, len(helloBytes)+1)
347 toWrite = append(toWrite, helloBytes...)
348 toWrite = append(toWrite, typeFinished)
349 c.writeRecord(recordTypeHandshake, toWrite)
350 } else {
351 c.writeRecord(recordTypeHandshake, helloBytes)
352 }
David Benjamind86c7672014-08-02 04:07:12 -0400353 }
David Benjamin582ba042016-07-07 12:33:25 -0700354 c.flushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700355
David Benjamin83f90402015-01-27 01:09:43 -0500356 if err := c.simulatePacketLoss(nil); err != nil {
357 return err
358 }
Adam Langley95c29f32014-06-20 12:00:00 -0700359 msg, err := c.readHandshake()
360 if err != nil {
361 return err
362 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400363
364 if c.isDTLS {
365 helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
366 if ok {
David Benjaminda4789e2016-10-31 19:23:34 -0400367 if helloVerifyRequest.vers != versionToWire(VersionTLS10, c.isDTLS) {
David Benjamin8bc38f52014-08-16 12:07:27 -0400368 // Per RFC 6347, the version field in
369 // HelloVerifyRequest SHOULD be always DTLS
370 // 1.0. Enforce this for testing purposes.
371 return errors.New("dtls: bad HelloVerifyRequest version")
372 }
373
David Benjamin83c0bc92014-08-04 01:23:53 -0400374 hello.raw = nil
375 hello.cookie = helloVerifyRequest.cookie
376 helloBytes = hello.marshal()
377 c.writeRecord(recordTypeHandshake, helloBytes)
David Benjamin582ba042016-07-07 12:33:25 -0700378 c.flushHandshake()
David Benjamin83c0bc92014-08-04 01:23:53 -0400379
David Benjamin83f90402015-01-27 01:09:43 -0500380 if err := c.simulatePacketLoss(nil); err != nil {
381 return err
382 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400383 msg, err = c.readHandshake()
384 if err != nil {
385 return err
386 }
387 }
388 }
389
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400390 var serverWireVersion uint16
Nick Harperdcfbc672016-07-16 17:47:31 +0200391 switch m := msg.(type) {
392 case *helloRetryRequestMsg:
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400393 serverWireVersion = m.vers
Nick Harperdcfbc672016-07-16 17:47:31 +0200394 case *serverHelloMsg:
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400395 serverWireVersion = m.vers
Nick Harperdcfbc672016-07-16 17:47:31 +0200396 default:
397 c.sendAlert(alertUnexpectedMessage)
398 return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg)
399 }
400
David Benjaminb1dd8cd2016-09-26 19:20:48 -0400401 serverVersion, ok := wireToVersion(serverWireVersion, c.isDTLS)
402 if ok {
Steven Valdezfdd10992016-09-15 16:27:05 -0400403 ok = c.config.isSupportedVersion(serverVersion, c.isDTLS)
David Benjaminb1dd8cd2016-09-26 19:20:48 -0400404 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200405 if !ok {
406 c.sendAlert(alertProtocolVersion)
407 return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers)
408 }
Steven Valdezfdd10992016-09-15 16:27:05 -0400409 c.vers = serverVersion
Nick Harperdcfbc672016-07-16 17:47:31 +0200410 c.haveVers = true
411
412 helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
413 var secondHelloBytes []byte
414 if haveHelloRetryRequest {
David Benjamin3baa6e12016-10-07 21:10:38 -0400415 if len(helloRetryRequest.cookie) > 0 {
416 hello.tls13Cookie = helloRetryRequest.cookie
417 }
418
Steven Valdez5440fe02016-07-18 12:40:30 -0400419 if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
David Benjamin3baa6e12016-10-07 21:10:38 -0400420 helloRetryRequest.hasSelectedGroup = true
Steven Valdez5440fe02016-07-18 12:40:30 -0400421 helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
422 }
David Benjamin3baa6e12016-10-07 21:10:38 -0400423 if helloRetryRequest.hasSelectedGroup {
424 var hrrCurveFound bool
425 group := helloRetryRequest.selectedGroup
426 for _, curveID := range hello.supportedCurves {
427 if group == curveID {
428 hrrCurveFound = true
429 break
430 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200431 }
David Benjamin3baa6e12016-10-07 21:10:38 -0400432 if !hrrCurveFound || keyShares[group] != nil {
433 c.sendAlert(alertHandshakeFailure)
434 return errors.New("tls: received invalid HelloRetryRequest")
435 }
436 curve, ok := curveForCurveID(group)
437 if !ok {
438 return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
439 }
440 publicKey, err := curve.offer(c.config.rand())
441 if err != nil {
442 return err
443 }
444 keyShares[group] = curve
Steven Valdeza833c352016-11-01 13:39:36 -0400445 hello.keyShares = []keyShareEntry{{
David Benjamin3baa6e12016-10-07 21:10:38 -0400446 group: group,
447 keyExchange: publicKey,
Steven Valdeza833c352016-11-01 13:39:36 -0400448 }}
Nick Harperdcfbc672016-07-16 17:47:31 +0200449 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200450
Steven Valdez5440fe02016-07-18 12:40:30 -0400451 if c.config.Bugs.SecondClientHelloMissingKeyShare {
452 hello.hasKeyShares = false
453 }
454
Nick Harperdcfbc672016-07-16 17:47:31 +0200455 hello.hasEarlyData = false
Nick Harperdcfbc672016-07-16 17:47:31 +0200456 hello.raw = nil
457
Steven Valdeza833c352016-11-01 13:39:36 -0400458 if len(hello.pskIdentities) > 0 {
459 generatePSKBinders(hello, pskCipherSuite, session.masterSecret, append(helloBytes, helloRetryRequest.marshal()...), c.config)
460 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200461 secondHelloBytes = hello.marshal()
462 c.writeRecord(recordTypeHandshake, secondHelloBytes)
463 c.flushHandshake()
464
465 msg, err = c.readHandshake()
466 if err != nil {
467 return err
468 }
469 }
470
Adam Langley95c29f32014-06-20 12:00:00 -0700471 serverHello, ok := msg.(*serverHelloMsg)
472 if !ok {
473 c.sendAlert(alertUnexpectedMessage)
474 return unexpectedMessageError(serverHello, msg)
475 }
476
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400477 if serverWireVersion != serverHello.vers {
Adam Langley95c29f32014-06-20 12:00:00 -0700478 c.sendAlert(alertProtocolVersion)
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400479 return fmt.Errorf("tls: server sent non-matching version %x vs %x", serverWireVersion, serverHello.vers)
Adam Langley95c29f32014-06-20 12:00:00 -0700480 }
Adam Langley95c29f32014-06-20 12:00:00 -0700481
Nick Harper85f20c22016-07-04 10:11:59 -0700482 // Check for downgrade signals in the server random, per
David Benjamina128a552016-10-13 14:26:33 -0400483 // draft-ietf-tls-tls13-16, section 4.1.3.
Nick Harper85f20c22016-07-04 10:11:59 -0700484 if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400485 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS13) {
Nick Harper85f20c22016-07-04 10:11:59 -0700486 c.sendAlert(alertProtocolVersion)
487 return errors.New("tls: downgrade from TLS 1.3 detected")
488 }
489 }
490 if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400491 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS12) {
Nick Harper85f20c22016-07-04 10:11:59 -0700492 c.sendAlert(alertProtocolVersion)
493 return errors.New("tls: downgrade from TLS 1.2 detected")
494 }
495 }
496
Nick Harper0b3625b2016-07-25 16:16:28 -0700497 suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite)
Adam Langley95c29f32014-06-20 12:00:00 -0700498 if suite == nil {
499 c.sendAlert(alertHandshakeFailure)
500 return fmt.Errorf("tls: server selected an unsupported cipher suite")
501 }
502
David Benjamin3baa6e12016-10-07 21:10:38 -0400503 if haveHelloRetryRequest && helloRetryRequest.hasSelectedGroup && helloRetryRequest.selectedGroup != serverHello.keyShare.group {
Nick Harperdcfbc672016-07-16 17:47:31 +0200504 c.sendAlert(alertHandshakeFailure)
505 return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
506 }
507
Adam Langley95c29f32014-06-20 12:00:00 -0700508 hs := &clientHandshakeState{
509 c: c,
510 serverHello: serverHello,
511 hello: hello,
512 suite: suite,
513 finishedHash: newFinishedHash(c.vers, suite),
Nick Harperb41d2e42016-07-01 17:50:32 -0400514 keyShares: keyShares,
Adam Langley95c29f32014-06-20 12:00:00 -0700515 session: session,
516 }
517
David Benjamin83c0bc92014-08-04 01:23:53 -0400518 hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
Nick Harperdcfbc672016-07-16 17:47:31 +0200519 if haveHelloRetryRequest {
520 hs.writeServerHash(helloRetryRequest.marshal())
521 hs.writeClientHash(secondHelloBytes)
522 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400523 hs.writeServerHash(hs.serverHello.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700524
David Benjamin8d315d72016-07-18 01:03:18 +0200525 if c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400526 if err := hs.doTLS13Handshake(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700527 return err
528 }
529 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400530 if c.config.Bugs.EarlyChangeCipherSpec > 0 {
531 hs.establishKeys()
532 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
533 }
534
535 if hs.serverHello.compressionMethod != compressionNone {
536 c.sendAlert(alertUnexpectedMessage)
537 return errors.New("tls: server selected unsupported compression format")
538 }
539
540 err = hs.processServerExtensions(&serverHello.extensions)
541 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700542 return err
543 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400544
545 isResume, err := hs.processServerHello()
546 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700547 return err
548 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400549
550 if isResume {
551 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
552 if err := hs.establishKeys(); err != nil {
553 return err
554 }
555 }
556 if err := hs.readSessionTicket(); err != nil {
557 return err
558 }
559 if err := hs.readFinished(c.firstFinished[:]); err != nil {
560 return err
561 }
562 if err := hs.sendFinished(nil, isResume); err != nil {
563 return err
564 }
565 } else {
566 if err := hs.doFullHandshake(); err != nil {
567 return err
568 }
569 if err := hs.establishKeys(); err != nil {
570 return err
571 }
572 if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
573 return err
574 }
575 // Most retransmits are triggered by a timeout, but the final
576 // leg of the handshake is retransmited upon re-receiving a
577 // Finished.
578 if err := c.simulatePacketLoss(func() {
David Benjamin02edcd02016-07-27 17:40:37 -0400579 c.sendHandshakeSeq--
Nick Harperb41d2e42016-07-01 17:50:32 -0400580 c.writeRecord(recordTypeHandshake, hs.finishedBytes)
581 c.flushHandshake()
582 }); err != nil {
583 return err
584 }
585 if err := hs.readSessionTicket(); err != nil {
586 return err
587 }
588 if err := hs.readFinished(nil); err != nil {
589 return err
590 }
Adam Langley95c29f32014-06-20 12:00:00 -0700591 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400592
593 if sessionCache != nil && hs.session != nil && session != hs.session {
594 if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
595 return errors.New("tls: new session used session IDs instead of tickets")
596 }
597 sessionCache.Put(cacheKey, hs.session)
David Benjamin83f90402015-01-27 01:09:43 -0500598 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400599
600 c.didResume = isResume
David Benjamin97a0a082016-07-13 17:57:35 -0400601 c.exporterSecret = hs.masterSecret
Adam Langley95c29f32014-06-20 12:00:00 -0700602 }
603
Adam Langley95c29f32014-06-20 12:00:00 -0700604 c.handshakeComplete = true
David Benjaminc565ebb2015-04-03 04:06:36 -0400605 c.cipherSuite = suite
606 copy(c.clientRandom[:], hs.hello.random)
607 copy(c.serverRandom[:], hs.serverHello.random)
Paul Lietar4fac72e2015-09-09 13:44:55 +0100608
Adam Langley95c29f32014-06-20 12:00:00 -0700609 return nil
610}
611
Nick Harperb41d2e42016-07-01 17:50:32 -0400612func (hs *clientHandshakeState) doTLS13Handshake() error {
613 c := hs.c
614
615 // Once the PRF hash is known, TLS 1.3 does not require a handshake
616 // buffer.
617 hs.finishedHash.discardHandshakeBuffer()
618
619 zeroSecret := hs.finishedHash.zeroSecret()
620
621 // Resolve PSK and compute the early secret.
622 //
623 // TODO(davidben): This will need to be handled slightly earlier once
624 // 0-RTT is implemented.
625 var psk []byte
Steven Valdez803c77a2016-09-06 14:13:43 -0400626 if hs.serverHello.hasPSKIdentity {
Nick Harper0b3625b2016-07-25 16:16:28 -0700627 // We send at most one PSK identity.
628 if hs.session == nil || hs.serverHello.pskIdentity != 0 {
629 c.sendAlert(alertUnknownPSKIdentity)
630 return errors.New("tls: server sent unknown PSK identity")
631 }
David Benjamin2b02f4b2016-11-16 16:11:47 +0900632 sessionCipher := cipherSuiteFromID(hs.session.cipherSuite)
633 if sessionCipher == nil || sessionCipher.hash() != hs.suite.hash() {
Nick Harper0b3625b2016-07-25 16:16:28 -0700634 c.sendAlert(alertHandshakeFailure)
David Benjamin2b02f4b2016-11-16 16:11:47 +0900635 return errors.New("tls: server resumed an invalid session for the cipher suite")
Nick Harper0b3625b2016-07-25 16:16:28 -0700636 }
Steven Valdeza833c352016-11-01 13:39:36 -0400637 psk = hs.session.masterSecret
Nick Harper0b3625b2016-07-25 16:16:28 -0700638 c.didResume = true
Nick Harperb41d2e42016-07-01 17:50:32 -0400639 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400640 psk = zeroSecret
Nick Harperb41d2e42016-07-01 17:50:32 -0400641 }
642
643 earlySecret := hs.finishedHash.extractKey(zeroSecret, psk)
644
Steven Valdeza833c352016-11-01 13:39:36 -0400645 if !hs.serverHello.hasKeyShare {
646 c.sendAlert(alertUnsupportedExtension)
647 return errors.New("tls: server omitted KeyShare on resumption.")
648 }
649
Nick Harperb41d2e42016-07-01 17:50:32 -0400650 // Resolve ECDHE and compute the handshake secret.
651 var ecdheSecret []byte
Steven Valdez803c77a2016-09-06 14:13:43 -0400652 if !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
Nick Harperb41d2e42016-07-01 17:50:32 -0400653 curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
654 if !ok {
655 c.sendAlert(alertHandshakeFailure)
656 return errors.New("tls: server selected an unsupported group")
657 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400658 c.curveID = hs.serverHello.keyShare.group
Nick Harperb41d2e42016-07-01 17:50:32 -0400659
660 var err error
661 ecdheSecret, err = curve.finish(hs.serverHello.keyShare.keyExchange)
662 if err != nil {
663 return err
664 }
665 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400666 ecdheSecret = zeroSecret
667 }
668
669 // Compute the handshake secret.
670 handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
671
672 // Switch to handshake traffic keys.
Steven Valdezc4aa7272016-10-03 12:25:56 -0400673 clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, clientHandshakeTrafficLabel)
Steven Valdeza833c352016-11-01 13:39:36 -0400674 c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
Steven Valdezc4aa7272016-10-03 12:25:56 -0400675 serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, serverHandshakeTrafficLabel)
Steven Valdeza833c352016-11-01 13:39:36 -0400676 c.in.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400677
678 msg, err := c.readHandshake()
679 if err != nil {
680 return err
681 }
682
683 encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
684 if !ok {
685 c.sendAlert(alertUnexpectedMessage)
686 return unexpectedMessageError(encryptedExtensions, msg)
687 }
688 hs.writeServerHash(encryptedExtensions.marshal())
689
690 err = hs.processServerExtensions(&encryptedExtensions.extensions)
691 if err != nil {
692 return err
693 }
694
695 var chainToSend *Certificate
David Benjamin8d343b42016-07-09 14:26:01 -0700696 var certReq *certificateRequestMsg
Steven Valdeza833c352016-11-01 13:39:36 -0400697 if c.didResume {
Nick Harper0b3625b2016-07-25 16:16:28 -0700698 // Copy over authentication from the session.
699 c.peerCertificates = hs.session.serverCertificates
700 c.sctList = hs.session.sctList
701 c.ocspResponse = hs.session.ocspResponse
David Benjamin44b33bc2016-07-01 22:40:23 -0400702 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400703 msg, err := c.readHandshake()
704 if err != nil {
705 return err
706 }
707
David Benjamin8d343b42016-07-09 14:26:01 -0700708 var ok bool
709 certReq, ok = msg.(*certificateRequestMsg)
Nick Harperb41d2e42016-07-01 17:50:32 -0400710 if ok {
David Benjamin8a8349b2016-08-18 02:32:23 -0400711 if len(certReq.requestContext) != 0 {
712 return errors.New("tls: non-empty certificate request context sent in handshake")
713 }
714
David Benjaminb62d2872016-07-18 14:55:02 +0200715 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
716 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
717 }
718
Nick Harperb41d2e42016-07-01 17:50:32 -0400719 hs.writeServerHash(certReq.marshal())
Nick Harperb41d2e42016-07-01 17:50:32 -0400720
721 chainToSend, err = selectClientCertificate(c, certReq)
722 if err != nil {
723 return err
724 }
725
726 msg, err = c.readHandshake()
727 if err != nil {
728 return err
729 }
730 }
731
732 certMsg, ok := msg.(*certificateMsg)
733 if !ok {
734 c.sendAlert(alertUnexpectedMessage)
735 return unexpectedMessageError(certMsg, msg)
736 }
737 hs.writeServerHash(certMsg.marshal())
738
David Benjamin53210cb2016-11-16 09:01:48 +0900739 // Check for unsolicited extensions.
740 for i, cert := range certMsg.certificates {
741 if c.config.Bugs.NoOCSPStapling && cert.ocspResponse != nil {
742 c.sendAlert(alertUnsupportedExtension)
743 return errors.New("tls: unexpected OCSP response in the server certificate")
744 }
745 if c.config.Bugs.NoSignedCertificateTimestamps && cert.sctList != nil {
746 c.sendAlert(alertUnsupportedExtension)
747 return errors.New("tls: unexpected SCT list in the server certificate")
748 }
749 if i > 0 && c.config.Bugs.ExpectNoExtensionsOnIntermediate && (cert.ocspResponse != nil || cert.sctList != nil) {
750 c.sendAlert(alertUnsupportedExtension)
751 return errors.New("tls: unexpected extensions in the server certificate")
752 }
753 }
754
Nick Harperb41d2e42016-07-01 17:50:32 -0400755 if err := hs.verifyCertificates(certMsg); err != nil {
756 return err
757 }
758 leaf := c.peerCertificates[0]
Steven Valdeza833c352016-11-01 13:39:36 -0400759 c.ocspResponse = certMsg.certificates[0].ocspResponse
760 c.sctList = certMsg.certificates[0].sctList
761
Nick Harperb41d2e42016-07-01 17:50:32 -0400762 msg, err = c.readHandshake()
763 if err != nil {
764 return err
765 }
766 certVerifyMsg, ok := msg.(*certificateVerifyMsg)
767 if !ok {
768 c.sendAlert(alertUnexpectedMessage)
769 return unexpectedMessageError(certVerifyMsg, msg)
770 }
771
David Benjaminf74ec792016-07-13 21:18:49 -0400772 c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
Nick Harperb41d2e42016-07-01 17:50:32 -0400773 input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
David Benjamin1fb125c2016-07-08 18:52:12 -0700774 err = verifyMessage(c.vers, leaf.PublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
Nick Harperb41d2e42016-07-01 17:50:32 -0400775 if err != nil {
776 return err
777 }
778
779 hs.writeServerHash(certVerifyMsg.marshal())
780 }
781
782 msg, err = c.readHandshake()
783 if err != nil {
784 return err
785 }
786 serverFinished, ok := msg.(*finishedMsg)
787 if !ok {
788 c.sendAlert(alertUnexpectedMessage)
789 return unexpectedMessageError(serverFinished, msg)
790 }
791
Steven Valdezc4aa7272016-10-03 12:25:56 -0400792 verify := hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
Nick Harperb41d2e42016-07-01 17:50:32 -0400793 if len(verify) != len(serverFinished.verifyData) ||
794 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
795 c.sendAlert(alertHandshakeFailure)
796 return errors.New("tls: server's Finished message was incorrect")
797 }
798
799 hs.writeServerHash(serverFinished.marshal())
800
801 // The various secrets do not incorporate the client's final leg, so
802 // derive them now before updating the handshake context.
803 masterSecret := hs.finishedHash.extractKey(handshakeSecret, zeroSecret)
Steven Valdezc4aa7272016-10-03 12:25:56 -0400804 clientTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, clientApplicationTrafficLabel)
805 serverTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, serverApplicationTrafficLabel)
Nick Harperb41d2e42016-07-01 17:50:32 -0400806
Steven Valdez0ee2e112016-07-15 06:51:15 -0400807 if certReq != nil && !c.config.Bugs.SkipClientCertificate {
David Benjamin8d343b42016-07-09 14:26:01 -0700808 certMsg := &certificateMsg{
809 hasRequestContext: true,
810 requestContext: certReq.requestContext,
811 }
812 if chainToSend != nil {
Steven Valdeza833c352016-11-01 13:39:36 -0400813 for _, certData := range chainToSend.Certificate {
814 certMsg.certificates = append(certMsg.certificates, certificateEntry{
815 data: certData,
816 extraExtension: c.config.Bugs.SendExtensionOnCertificate,
817 })
818 }
David Benjamin8d343b42016-07-09 14:26:01 -0700819 }
820 hs.writeClientHash(certMsg.marshal())
821 c.writeRecord(recordTypeHandshake, certMsg.marshal())
822
823 if chainToSend != nil {
824 certVerify := &certificateVerifyMsg{
825 hasSignatureAlgorithm: true,
826 }
827
828 // Determine the hash to sign.
829 privKey := chainToSend.PrivateKey
830
831 var err error
832 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
833 if err != nil {
834 c.sendAlert(alertInternalError)
835 return err
836 }
837
838 input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
839 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
840 if err != nil {
841 c.sendAlert(alertInternalError)
842 return err
843 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400844 if c.config.Bugs.SendSignatureAlgorithm != 0 {
845 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
846 }
David Benjamin8d343b42016-07-09 14:26:01 -0700847
848 hs.writeClientHash(certVerify.marshal())
849 c.writeRecord(recordTypeHandshake, certVerify.marshal())
850 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400851 }
852
Nick Harper60a85cb2016-09-23 16:25:11 -0700853 if encryptedExtensions.extensions.channelIDRequested {
854 channelIDHash := crypto.SHA256.New()
855 channelIDHash.Write(hs.finishedHash.certificateVerifyInput(channelIDContextTLS13))
856 channelIDMsgBytes, err := hs.writeChannelIDMessage(channelIDHash.Sum(nil))
857 if err != nil {
858 return err
859 }
860 hs.writeClientHash(channelIDMsgBytes)
861 c.writeRecord(recordTypeHandshake, channelIDMsgBytes)
862 }
863
Nick Harperb41d2e42016-07-01 17:50:32 -0400864 // Send a client Finished message.
865 finished := new(finishedMsg)
Steven Valdezc4aa7272016-10-03 12:25:56 -0400866 finished.verifyData = hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
Nick Harperb41d2e42016-07-01 17:50:32 -0400867 if c.config.Bugs.BadFinished {
868 finished.verifyData[0]++
869 }
David Benjamin97a0a082016-07-13 17:57:35 -0400870 hs.writeClientHash(finished.marshal())
David Benjamin7964b182016-07-14 23:36:30 -0400871 if c.config.Bugs.PartialClientFinishedWithClientHello {
872 // The first byte has already been sent.
873 c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
874 } else {
875 c.writeRecord(recordTypeHandshake, finished.marshal())
876 }
David Benjamin02edcd02016-07-27 17:40:37 -0400877 if c.config.Bugs.SendExtraFinished {
878 c.writeRecord(recordTypeHandshake, finished.marshal())
879 }
David Benjaminee51a222016-07-07 18:34:12 -0700880 c.flushHandshake()
Nick Harperb41d2e42016-07-01 17:50:32 -0400881
882 // Switch to application data keys.
Steven Valdeza833c352016-11-01 13:39:36 -0400883 c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
884 c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400885
David Benjamin97a0a082016-07-13 17:57:35 -0400886 c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
David Benjamind5a4ecb2016-07-18 01:17:13 +0200887 c.resumptionSecret = hs.finishedHash.deriveSecret(masterSecret, resumptionLabel)
Nick Harperb41d2e42016-07-01 17:50:32 -0400888 return nil
889}
890
Adam Langley95c29f32014-06-20 12:00:00 -0700891func (hs *clientHandshakeState) doFullHandshake() error {
892 c := hs.c
893
David Benjamin48cae082014-10-27 01:06:24 -0400894 var leaf *x509.Certificate
895 if hs.suite.flags&suitePSK == 0 {
896 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700897 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700898 return err
899 }
Adam Langley95c29f32014-06-20 12:00:00 -0700900
David Benjamin48cae082014-10-27 01:06:24 -0400901 certMsg, ok := msg.(*certificateMsg)
David Benjamin75051442016-07-01 18:58:51 -0400902 if !ok {
David Benjamin48cae082014-10-27 01:06:24 -0400903 c.sendAlert(alertUnexpectedMessage)
904 return unexpectedMessageError(certMsg, msg)
905 }
906 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700907
David Benjamin75051442016-07-01 18:58:51 -0400908 if err := hs.verifyCertificates(certMsg); err != nil {
909 return err
David Benjamin48cae082014-10-27 01:06:24 -0400910 }
David Benjamin75051442016-07-01 18:58:51 -0400911 leaf = c.peerCertificates[0]
David Benjamin48cae082014-10-27 01:06:24 -0400912 }
Adam Langley95c29f32014-06-20 12:00:00 -0700913
Nick Harperb3d51be2016-07-01 11:43:18 -0400914 if hs.serverHello.extensions.ocspStapling {
David Benjamin48cae082014-10-27 01:06:24 -0400915 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700916 if err != nil {
917 return err
918 }
919 cs, ok := msg.(*certificateStatusMsg)
920 if !ok {
921 c.sendAlert(alertUnexpectedMessage)
922 return unexpectedMessageError(cs, msg)
923 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400924 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700925
926 if cs.statusType == statusTypeOCSP {
927 c.ocspResponse = cs.response
928 }
929 }
930
David Benjamin48cae082014-10-27 01:06:24 -0400931 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700932 if err != nil {
933 return err
934 }
935
936 keyAgreement := hs.suite.ka(c.vers)
937
938 skx, ok := msg.(*serverKeyExchangeMsg)
939 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -0400940 hs.writeServerHash(skx.marshal())
David Benjamin48cae082014-10-27 01:06:24 -0400941 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
Adam Langley95c29f32014-06-20 12:00:00 -0700942 if err != nil {
943 c.sendAlert(alertUnexpectedMessage)
944 return err
945 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400946 if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
947 c.curveID = ecdhe.curveID
948 }
Adam Langley95c29f32014-06-20 12:00:00 -0700949
Nick Harper60edffd2016-06-21 15:19:24 -0700950 c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()
951
Adam Langley95c29f32014-06-20 12:00:00 -0700952 msg, err = c.readHandshake()
953 if err != nil {
954 return err
955 }
956 }
957
958 var chainToSend *Certificate
959 var certRequested bool
960 certReq, ok := msg.(*certificateRequestMsg)
961 if ok {
962 certRequested = true
David Benjamin7a41d372016-07-09 11:21:54 -0700963 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
964 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
965 }
Adam Langley95c29f32014-06-20 12:00:00 -0700966
David Benjamin83c0bc92014-08-04 01:23:53 -0400967 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700968
David Benjamina6f82632016-07-01 18:44:02 -0400969 chainToSend, err = selectClientCertificate(c, certReq)
970 if err != nil {
971 return err
Adam Langley95c29f32014-06-20 12:00:00 -0700972 }
973
974 msg, err = c.readHandshake()
975 if err != nil {
976 return err
977 }
978 }
979
980 shd, ok := msg.(*serverHelloDoneMsg)
981 if !ok {
982 c.sendAlert(alertUnexpectedMessage)
983 return unexpectedMessageError(shd, msg)
984 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400985 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700986
987 // If the server requested a certificate then we have to send a
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500988 // Certificate message in TLS, even if it's empty because we don't have
989 // a certificate to send. In SSL 3.0, skip the message and send a
990 // no_certificate warning alert.
Adam Langley95c29f32014-06-20 12:00:00 -0700991 if certRequested {
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500992 if c.vers == VersionSSL30 && chainToSend == nil {
993 c.sendAlert(alertNoCertficate)
994 } else if !c.config.Bugs.SkipClientCertificate {
995 certMsg := new(certificateMsg)
996 if chainToSend != nil {
Steven Valdeza833c352016-11-01 13:39:36 -0400997 for _, certData := range chainToSend.Certificate {
998 certMsg.certificates = append(certMsg.certificates, certificateEntry{
999 data: certData,
1000 })
1001 }
David Benjamin0b7ca7d2016-03-10 15:44:22 -05001002 }
1003 hs.writeClientHash(certMsg.marshal())
1004 c.writeRecord(recordTypeHandshake, certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001005 }
Adam Langley95c29f32014-06-20 12:00:00 -07001006 }
1007
David Benjamin48cae082014-10-27 01:06:24 -04001008 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
Adam Langley95c29f32014-06-20 12:00:00 -07001009 if err != nil {
1010 c.sendAlert(alertInternalError)
1011 return err
1012 }
1013 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -04001014 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -04001015 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -04001016 }
Adam Langley95c29f32014-06-20 12:00:00 -07001017 c.writeRecord(recordTypeHandshake, ckx.marshal())
1018 }
1019
Nick Harperb3d51be2016-07-01 11:43:18 -04001020 if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
Adam Langley75712922014-10-10 16:23:43 -07001021 hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
1022 c.extendedMasterSecret = true
1023 } else {
1024 if c.config.Bugs.RequireExtendedMasterSecret {
1025 return errors.New("tls: extended master secret required but not supported by peer")
1026 }
1027 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
1028 }
David Benjamine098ec22014-08-27 23:13:20 -04001029
Adam Langley95c29f32014-06-20 12:00:00 -07001030 if chainToSend != nil {
Adam Langley95c29f32014-06-20 12:00:00 -07001031 certVerify := &certificateVerifyMsg{
Nick Harper60edffd2016-06-21 15:19:24 -07001032 hasSignatureAlgorithm: c.vers >= VersionTLS12,
Adam Langley95c29f32014-06-20 12:00:00 -07001033 }
1034
David Benjamin72dc7832015-03-16 17:49:43 -04001035 // Determine the hash to sign.
Nick Harper60edffd2016-06-21 15:19:24 -07001036 privKey := c.config.Certificates[0].PrivateKey
David Benjamin72dc7832015-03-16 17:49:43 -04001037
Nick Harper60edffd2016-06-21 15:19:24 -07001038 if certVerify.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -07001039 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
Nick Harper60edffd2016-06-21 15:19:24 -07001040 if err != nil {
1041 c.sendAlert(alertInternalError)
1042 return err
Adam Langley95c29f32014-06-20 12:00:00 -07001043 }
Nick Harper60edffd2016-06-21 15:19:24 -07001044 }
1045
1046 if c.vers > VersionSSL30 {
David Benjamin5208fd42016-07-13 21:43:25 -04001047 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
David Benjamina95e9f32016-07-08 16:28:04 -07001048 if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
1049 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
1050 }
Nick Harper60edffd2016-06-21 15:19:24 -07001051 } else {
1052 // SSL 3.0's client certificate construction is
1053 // incompatible with signatureAlgorithm.
1054 rsaKey, ok := privKey.(*rsa.PrivateKey)
1055 if !ok {
1056 err = errors.New("unsupported signature type for client certificate")
1057 } else {
1058 digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
David Benjamin5208fd42016-07-13 21:43:25 -04001059 if c.config.Bugs.InvalidSignature {
Nick Harper60edffd2016-06-21 15:19:24 -07001060 digest[0] ^= 0x80
1061 }
1062 certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
1063 }
Adam Langley95c29f32014-06-20 12:00:00 -07001064 }
1065 if err != nil {
1066 c.sendAlert(alertInternalError)
1067 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
1068 }
Adam Langley95c29f32014-06-20 12:00:00 -07001069
David Benjamin83c0bc92014-08-04 01:23:53 -04001070 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001071 c.writeRecord(recordTypeHandshake, certVerify.marshal())
1072 }
David Benjamin82261be2016-07-07 14:32:50 -07001073 // flushHandshake will be called in sendFinished.
Adam Langley95c29f32014-06-20 12:00:00 -07001074
David Benjamine098ec22014-08-27 23:13:20 -04001075 hs.finishedHash.discardHandshakeBuffer()
1076
Adam Langley95c29f32014-06-20 12:00:00 -07001077 return nil
1078}
1079
David Benjamin75051442016-07-01 18:58:51 -04001080func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
1081 c := hs.c
1082
1083 if len(certMsg.certificates) == 0 {
1084 c.sendAlert(alertIllegalParameter)
1085 return errors.New("tls: no certificates sent")
1086 }
1087
1088 certs := make([]*x509.Certificate, len(certMsg.certificates))
Steven Valdeza833c352016-11-01 13:39:36 -04001089 for i, certEntry := range certMsg.certificates {
1090 cert, err := x509.ParseCertificate(certEntry.data)
David Benjamin75051442016-07-01 18:58:51 -04001091 if err != nil {
1092 c.sendAlert(alertBadCertificate)
1093 return errors.New("tls: failed to parse certificate from server: " + err.Error())
1094 }
1095 certs[i] = cert
1096 }
1097
1098 if !c.config.InsecureSkipVerify {
1099 opts := x509.VerifyOptions{
1100 Roots: c.config.RootCAs,
1101 CurrentTime: c.config.time(),
1102 DNSName: c.config.ServerName,
1103 Intermediates: x509.NewCertPool(),
1104 }
1105
1106 for i, cert := range certs {
1107 if i == 0 {
1108 continue
1109 }
1110 opts.Intermediates.AddCert(cert)
1111 }
1112 var err error
1113 c.verifiedChains, err = certs[0].Verify(opts)
1114 if err != nil {
1115 c.sendAlert(alertBadCertificate)
1116 return err
1117 }
1118 }
1119
1120 switch certs[0].PublicKey.(type) {
1121 case *rsa.PublicKey, *ecdsa.PublicKey:
1122 break
1123 default:
1124 c.sendAlert(alertUnsupportedCertificate)
1125 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
1126 }
1127
1128 c.peerCertificates = certs
1129 return nil
1130}
1131
Adam Langley95c29f32014-06-20 12:00:00 -07001132func (hs *clientHandshakeState) establishKeys() error {
1133 c := hs.c
1134
1135 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
Nick Harper1fd39d82016-06-14 18:14:35 -07001136 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))
Adam Langley95c29f32014-06-20 12:00:00 -07001137 var clientCipher, serverCipher interface{}
1138 var clientHash, serverHash macFunction
1139 if hs.suite.cipher != nil {
1140 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
1141 clientHash = hs.suite.mac(c.vers, clientMAC)
1142 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
1143 serverHash = hs.suite.mac(c.vers, serverMAC)
1144 } else {
Nick Harper1fd39d82016-06-14 18:14:35 -07001145 clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
1146 serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
Adam Langley95c29f32014-06-20 12:00:00 -07001147 }
1148
1149 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
1150 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
1151 return nil
1152}
1153
David Benjamin75101402016-07-01 13:40:23 -04001154func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
1155 c := hs.c
1156
David Benjamin8d315d72016-07-18 01:03:18 +02001157 if c.vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001158 if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
1159 return errors.New("tls: renegotiation extension missing")
1160 }
David Benjamin75101402016-07-01 13:40:23 -04001161
Nick Harperb41d2e42016-07-01 17:50:32 -04001162 if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
1163 var expectedRenegInfo []byte
1164 expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
1165 expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
1166 if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
1167 c.sendAlert(alertHandshakeFailure)
1168 return fmt.Errorf("tls: renegotiation mismatch")
1169 }
David Benjamin75101402016-07-01 13:40:23 -04001170 }
David Benjamincea0ab42016-07-14 12:33:14 -04001171 } else if serverExtensions.secureRenegotiation != nil {
1172 return errors.New("tls: renegotiation info sent in TLS 1.3")
David Benjamin75101402016-07-01 13:40:23 -04001173 }
1174
1175 if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
1176 if serverExtensions.customExtension != *expected {
1177 return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
1178 }
1179 }
1180
1181 clientDidNPN := hs.hello.nextProtoNeg
1182 clientDidALPN := len(hs.hello.alpnProtocols) > 0
1183 serverHasNPN := serverExtensions.nextProtoNeg
1184 serverHasALPN := len(serverExtensions.alpnProtocol) > 0
1185
1186 if !clientDidNPN && serverHasNPN {
1187 c.sendAlert(alertHandshakeFailure)
1188 return errors.New("server advertised unrequested NPN extension")
1189 }
1190
1191 if !clientDidALPN && serverHasALPN {
1192 c.sendAlert(alertHandshakeFailure)
1193 return errors.New("server advertised unrequested ALPN extension")
1194 }
1195
1196 if serverHasNPN && serverHasALPN {
1197 c.sendAlert(alertHandshakeFailure)
1198 return errors.New("server advertised both NPN and ALPN extensions")
1199 }
1200
1201 if serverHasALPN {
1202 c.clientProtocol = serverExtensions.alpnProtocol
1203 c.clientProtocolFallback = false
1204 c.usedALPN = true
1205 }
1206
David Benjamin8d315d72016-07-18 01:03:18 +02001207 if serverHasNPN && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001208 c.sendAlert(alertHandshakeFailure)
1209 return errors.New("server advertised NPN over TLS 1.3")
1210 }
1211
David Benjamin75101402016-07-01 13:40:23 -04001212 if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
1213 c.sendAlert(alertHandshakeFailure)
1214 return errors.New("server advertised unrequested Channel ID extension")
1215 }
1216
David Benjamin8d315d72016-07-18 01:03:18 +02001217 if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
David Benjamine9077652016-07-13 21:02:08 -04001218 return errors.New("tls: server advertised extended master secret over TLS 1.3")
1219 }
1220
David Benjamin8d315d72016-07-18 01:03:18 +02001221 if serverExtensions.ticketSupported && c.vers >= VersionTLS13 {
Steven Valdez143e8b32016-07-11 13:19:03 -04001222 return errors.New("tls: server advertised ticket extension over TLS 1.3")
1223 }
1224
Steven Valdeza833c352016-11-01 13:39:36 -04001225 if serverExtensions.ocspStapling && c.vers >= VersionTLS13 {
1226 return errors.New("tls: server advertised OCSP in ServerHello over TLS 1.3")
1227 }
1228
David Benjamin53210cb2016-11-16 09:01:48 +09001229 if serverExtensions.ocspStapling && c.config.Bugs.NoOCSPStapling {
1230 return errors.New("tls: server advertised unrequested OCSP extension")
1231 }
1232
Steven Valdeza833c352016-11-01 13:39:36 -04001233 if len(serverExtensions.sctList) > 0 && c.vers >= VersionTLS13 {
1234 return errors.New("tls: server advertised SCTs in ServerHello over TLS 1.3")
1235 }
1236
David Benjamin53210cb2016-11-16 09:01:48 +09001237 if len(serverExtensions.sctList) > 0 && c.config.Bugs.NoSignedCertificateTimestamps {
1238 return errors.New("tls: server advertised unrequested SCTs")
1239 }
1240
David Benjamin75101402016-07-01 13:40:23 -04001241 if serverExtensions.srtpProtectionProfile != 0 {
1242 if serverExtensions.srtpMasterKeyIdentifier != "" {
1243 return errors.New("tls: server selected SRTP MKI value")
1244 }
1245
1246 found := false
1247 for _, p := range c.config.SRTPProtectionProfiles {
1248 if p == serverExtensions.srtpProtectionProfile {
1249 found = true
1250 break
1251 }
1252 }
1253 if !found {
1254 return errors.New("tls: server advertised unsupported SRTP profile")
1255 }
1256
1257 c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
1258 }
1259
1260 return nil
1261}
1262
Adam Langley95c29f32014-06-20 12:00:00 -07001263func (hs *clientHandshakeState) serverResumedSession() bool {
1264 // If the server responded with the same sessionId then it means the
1265 // sessionTicket is being used to resume a TLS session.
1266 return hs.session != nil && hs.hello.sessionId != nil &&
1267 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
1268}
1269
1270func (hs *clientHandshakeState) processServerHello() (bool, error) {
1271 c := hs.c
1272
Adam Langley95c29f32014-06-20 12:00:00 -07001273 if hs.serverResumedSession() {
David Benjamin4b27d9f2015-05-12 22:42:52 -04001274 // For test purposes, assert that the server never accepts the
1275 // resumption offer on renegotiation.
1276 if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
1277 return false, errors.New("tls: server resumed session on renegotiation")
1278 }
1279
Nick Harperb3d51be2016-07-01 11:43:18 -04001280 if hs.serverHello.extensions.sctList != nil {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001281 return false, errors.New("tls: server sent SCT extension on session resumption")
1282 }
1283
Nick Harperb3d51be2016-07-01 11:43:18 -04001284 if hs.serverHello.extensions.ocspStapling {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001285 return false, errors.New("tls: server sent OCSP extension on session resumption")
1286 }
1287
Adam Langley95c29f32014-06-20 12:00:00 -07001288 // Restore masterSecret and peerCerts from previous state
1289 hs.masterSecret = hs.session.masterSecret
1290 c.peerCertificates = hs.session.serverCertificates
Adam Langley75712922014-10-10 16:23:43 -07001291 c.extendedMasterSecret = hs.session.extendedMasterSecret
Paul Lietar62be8ac2015-09-16 10:03:30 +01001292 c.sctList = hs.session.sctList
1293 c.ocspResponse = hs.session.ocspResponse
David Benjamine098ec22014-08-27 23:13:20 -04001294 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -07001295 return true, nil
1296 }
Paul Lietar62be8ac2015-09-16 10:03:30 +01001297
Nick Harperb3d51be2016-07-01 11:43:18 -04001298 if hs.serverHello.extensions.sctList != nil {
1299 c.sctList = hs.serverHello.extensions.sctList
Paul Lietar62be8ac2015-09-16 10:03:30 +01001300 }
1301
Adam Langley95c29f32014-06-20 12:00:00 -07001302 return false, nil
1303}
1304
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001305func (hs *clientHandshakeState) readFinished(out []byte) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001306 c := hs.c
1307
1308 c.readRecord(recordTypeChangeCipherSpec)
1309 if err := c.in.error(); err != nil {
1310 return err
1311 }
1312
1313 msg, err := c.readHandshake()
1314 if err != nil {
1315 return err
1316 }
1317 serverFinished, ok := msg.(*finishedMsg)
1318 if !ok {
1319 c.sendAlert(alertUnexpectedMessage)
1320 return unexpectedMessageError(serverFinished, msg)
1321 }
1322
David Benjaminf3ec83d2014-07-21 22:42:34 -04001323 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
1324 verify := hs.finishedHash.serverSum(hs.masterSecret)
1325 if len(verify) != len(serverFinished.verifyData) ||
1326 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
1327 c.sendAlert(alertHandshakeFailure)
1328 return errors.New("tls: server's Finished message was incorrect")
1329 }
Adam Langley95c29f32014-06-20 12:00:00 -07001330 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001331 c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001332 copy(out, serverFinished.verifyData)
David Benjamin83c0bc92014-08-04 01:23:53 -04001333 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001334 return nil
1335}
1336
1337func (hs *clientHandshakeState) readSessionTicket() error {
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001338 c := hs.c
1339
1340 // Create a session with no server identifier. Either a
1341 // session ID or session ticket will be attached.
1342 session := &ClientSessionState{
1343 vers: c.vers,
1344 cipherSuite: hs.suite.id,
1345 masterSecret: hs.masterSecret,
Nick Harperc9846112016-10-17 15:05:35 -07001346 handshakeHash: hs.finishedHash.Sum(),
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001347 serverCertificates: c.peerCertificates,
Paul Lietar62be8ac2015-09-16 10:03:30 +01001348 sctList: c.sctList,
1349 ocspResponse: c.ocspResponse,
Nick Harper0b3625b2016-07-25 16:16:28 -07001350 ticketExpiration: c.config.time().Add(time.Duration(7 * 24 * time.Hour)),
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001351 }
1352
Nick Harperb3d51be2016-07-01 11:43:18 -04001353 if !hs.serverHello.extensions.ticketSupported {
David Benjamind98452d2015-06-16 14:16:23 -04001354 if c.config.Bugs.ExpectNewTicket {
1355 return errors.New("tls: expected new ticket")
1356 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001357 if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
1358 session.sessionId = hs.serverHello.sessionId
1359 hs.session = session
1360 }
Adam Langley95c29f32014-06-20 12:00:00 -07001361 return nil
1362 }
1363
David Benjaminc7ce9772015-10-09 19:32:41 -04001364 if c.vers == VersionSSL30 {
1365 return errors.New("tls: negotiated session tickets in SSL 3.0")
1366 }
1367
Adam Langley95c29f32014-06-20 12:00:00 -07001368 msg, err := c.readHandshake()
1369 if err != nil {
1370 return err
1371 }
1372 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
1373 if !ok {
1374 c.sendAlert(alertUnexpectedMessage)
1375 return unexpectedMessageError(sessionTicketMsg, msg)
1376 }
Adam Langley95c29f32014-06-20 12:00:00 -07001377
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001378 session.sessionTicket = sessionTicketMsg.ticket
1379 hs.session = session
Adam Langley95c29f32014-06-20 12:00:00 -07001380
David Benjamind30a9902014-08-24 01:44:23 -04001381 hs.writeServerHash(sessionTicketMsg.marshal())
1382
Adam Langley95c29f32014-06-20 12:00:00 -07001383 return nil
1384}
1385
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001386func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001387 c := hs.c
1388
David Benjamin0b8d5da2016-07-15 00:39:56 -04001389 var postCCSMsgs [][]byte
David Benjamin83c0bc92014-08-04 01:23:53 -04001390 seqno := hs.c.sendHandshakeSeq
Nick Harperb3d51be2016-07-01 11:43:18 -04001391 if hs.serverHello.extensions.nextProtoNeg {
Adam Langley95c29f32014-06-20 12:00:00 -07001392 nextProto := new(nextProtoMsg)
Nick Harperb3d51be2016-07-01 11:43:18 -04001393 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
Adam Langley95c29f32014-06-20 12:00:00 -07001394 nextProto.proto = proto
1395 c.clientProtocol = proto
1396 c.clientProtocolFallback = fallback
1397
David Benjamin86271ee2014-07-21 16:14:03 -04001398 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -04001399 hs.writeHash(nextProtoBytes, seqno)
1400 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001401 postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
Adam Langley95c29f32014-06-20 12:00:00 -07001402 }
1403
Nick Harperb3d51be2016-07-01 11:43:18 -04001404 if hs.serverHello.extensions.channelIDRequested {
David Benjamind30a9902014-08-24 01:44:23 -04001405 var resumeHash []byte
1406 if isResume {
1407 resumeHash = hs.session.handshakeHash
1408 }
Nick Harper60a85cb2016-09-23 16:25:11 -07001409 channelIDMsgBytes, err := hs.writeChannelIDMessage(hs.finishedHash.hashForChannelID(resumeHash))
David Benjamind30a9902014-08-24 01:44:23 -04001410 if err != nil {
1411 return err
1412 }
David Benjamin24599a82016-06-30 18:56:53 -04001413 hs.writeHash(channelIDMsgBytes, seqno)
David Benjamind30a9902014-08-24 01:44:23 -04001414 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001415 postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
David Benjamind30a9902014-08-24 01:44:23 -04001416 }
1417
Adam Langley95c29f32014-06-20 12:00:00 -07001418 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -04001419 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
1420 finished.verifyData = hs.finishedHash.clientSum(nil)
1421 } else {
1422 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
1423 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001424 copy(out, finished.verifyData)
David Benjamin513f0ea2015-04-02 19:33:31 -04001425 if c.config.Bugs.BadFinished {
1426 finished.verifyData[0]++
1427 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001428 c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
David Benjamin83f90402015-01-27 01:09:43 -05001429 hs.finishedBytes = finished.marshal()
1430 hs.writeHash(hs.finishedBytes, seqno)
David Benjamin0b8d5da2016-07-15 00:39:56 -04001431 postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
David Benjamin86271ee2014-07-21 16:14:03 -04001432
1433 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001434 c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
1435 postCCSMsgs[0] = postCCSMsgs[0][5:]
David Benjamin61672812016-07-14 23:10:43 -04001436 } else if c.config.Bugs.SendUnencryptedFinished {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001437 c.writeRecord(recordTypeHandshake, postCCSMsgs[0])
1438 postCCSMsgs = postCCSMsgs[1:]
David Benjamin86271ee2014-07-21 16:14:03 -04001439 }
David Benjamin582ba042016-07-07 12:33:25 -07001440 c.flushHandshake()
David Benjamin86271ee2014-07-21 16:14:03 -04001441
1442 if !c.config.Bugs.SkipChangeCipherSpec &&
1443 c.config.Bugs.EarlyChangeCipherSpec == 0 {
David Benjamin8411b242015-11-26 12:07:28 -05001444 ccs := []byte{1}
1445 if c.config.Bugs.BadChangeCipherSpec != nil {
1446 ccs = c.config.Bugs.BadChangeCipherSpec
1447 }
1448 c.writeRecord(recordTypeChangeCipherSpec, ccs)
David Benjamin86271ee2014-07-21 16:14:03 -04001449 }
1450
David Benjamin4189bd92015-01-25 23:52:39 -05001451 if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
1452 c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
1453 }
David Benjamindc3da932015-03-12 15:09:02 -04001454 if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
1455 c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
1456 return errors.New("tls: simulating post-CCS alert")
1457 }
David Benjamin4189bd92015-01-25 23:52:39 -05001458
David Benjamin0b8d5da2016-07-15 00:39:56 -04001459 if !c.config.Bugs.SkipFinished {
1460 for _, msg := range postCCSMsgs {
1461 c.writeRecord(recordTypeHandshake, msg)
1462 }
David Benjamin02edcd02016-07-27 17:40:37 -04001463
1464 if c.config.Bugs.SendExtraFinished {
1465 c.writeRecord(recordTypeHandshake, finished.marshal())
1466 }
1467
David Benjamin582ba042016-07-07 12:33:25 -07001468 c.flushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -05001469 }
Adam Langley95c29f32014-06-20 12:00:00 -07001470 return nil
1471}
1472
Nick Harper60a85cb2016-09-23 16:25:11 -07001473func (hs *clientHandshakeState) writeChannelIDMessage(channelIDHash []byte) ([]byte, error) {
1474 c := hs.c
1475 channelIDMsg := new(channelIDMsg)
1476 if c.config.ChannelID.Curve != elliptic.P256() {
1477 return nil, fmt.Errorf("tls: Channel ID is not on P-256.")
1478 }
1479 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, channelIDHash)
1480 if err != nil {
1481 return nil, err
1482 }
1483 channelID := make([]byte, 128)
1484 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
1485 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
1486 writeIntPadded(channelID[64:96], r)
1487 writeIntPadded(channelID[96:128], s)
1488 if c.config.Bugs.InvalidChannelIDSignature {
1489 channelID[64] ^= 1
1490 }
1491 channelIDMsg.channelID = channelID
1492
1493 c.channelID = &c.config.ChannelID.PublicKey
1494
1495 return channelIDMsg.marshal(), nil
1496}
1497
David Benjamin83c0bc92014-08-04 01:23:53 -04001498func (hs *clientHandshakeState) writeClientHash(msg []byte) {
1499 // writeClientHash is called before writeRecord.
1500 hs.writeHash(msg, hs.c.sendHandshakeSeq)
1501}
1502
1503func (hs *clientHandshakeState) writeServerHash(msg []byte) {
1504 // writeServerHash is called after readHandshake.
1505 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
1506}
1507
1508func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
1509 if hs.c.isDTLS {
1510 // This is somewhat hacky. DTLS hashes a slightly different format.
1511 // First, the TLS header.
1512 hs.finishedHash.Write(msg[:4])
1513 // Then the sequence number and reassembled fragment offset (always 0).
1514 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
1515 // Then the reassembled fragment (always equal to the message length).
1516 hs.finishedHash.Write(msg[1:4])
1517 // And then the message body.
1518 hs.finishedHash.Write(msg[4:])
1519 } else {
1520 hs.finishedHash.Write(msg)
1521 }
1522}
1523
David Benjamina6f82632016-07-01 18:44:02 -04001524// selectClientCertificate selects a certificate for use with the given
1525// certificate, or none if none match. It may return a particular certificate or
1526// nil on success, or an error on internal error.
1527func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
1528 // RFC 4346 on the certificateAuthorities field:
1529 // A list of the distinguished names of acceptable certificate
1530 // authorities. These distinguished names may specify a desired
1531 // distinguished name for a root CA or for a subordinate CA; thus, this
1532 // message can be used to describe both known roots and a desired
1533 // authorization space. If the certificate_authorities list is empty
1534 // then the client MAY send any certificate of the appropriate
1535 // ClientCertificateType, unless there is some external arrangement to
1536 // the contrary.
1537
1538 var rsaAvail, ecdsaAvail bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001539 if !certReq.hasRequestContext {
1540 for _, certType := range certReq.certificateTypes {
1541 switch certType {
1542 case CertTypeRSASign:
1543 rsaAvail = true
1544 case CertTypeECDSASign:
1545 ecdsaAvail = true
1546 }
David Benjamina6f82632016-07-01 18:44:02 -04001547 }
1548 }
1549
1550 // We need to search our list of client certs for one
1551 // where SignatureAlgorithm is RSA and the Issuer is in
1552 // certReq.certificateAuthorities
1553findCert:
1554 for i, chain := range c.config.Certificates {
Nick Harperb41d2e42016-07-01 17:50:32 -04001555 if !certReq.hasRequestContext && !rsaAvail && !ecdsaAvail {
David Benjamina6f82632016-07-01 18:44:02 -04001556 continue
1557 }
1558
1559 // Ensure the private key supports one of the advertised
1560 // signature algorithms.
1561 if certReq.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -07001562 if _, err := selectSignatureAlgorithm(c.vers, chain.PrivateKey, c.config, certReq.signatureAlgorithms); err != nil {
David Benjamina6f82632016-07-01 18:44:02 -04001563 continue
1564 }
1565 }
1566
1567 for j, cert := range chain.Certificate {
1568 x509Cert := chain.Leaf
1569 // parse the certificate if this isn't the leaf
1570 // node, or if chain.Leaf was nil
1571 if j != 0 || x509Cert == nil {
1572 var err error
1573 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
1574 c.sendAlert(alertInternalError)
1575 return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
1576 }
1577 }
1578
Nick Harperb41d2e42016-07-01 17:50:32 -04001579 if !certReq.hasRequestContext {
1580 switch {
1581 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
1582 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
1583 default:
1584 continue findCert
1585 }
David Benjamina6f82632016-07-01 18:44:02 -04001586 }
1587
1588 if len(certReq.certificateAuthorities) == 0 {
1589 // They gave us an empty list, so just take the
1590 // first certificate of valid type from
1591 // c.config.Certificates.
1592 return &chain, nil
1593 }
1594
1595 for _, ca := range certReq.certificateAuthorities {
1596 if bytes.Equal(x509Cert.RawIssuer, ca) {
1597 return &chain, nil
1598 }
1599 }
1600 }
1601 }
1602
1603 return nil, nil
1604}
1605
Adam Langley95c29f32014-06-20 12:00:00 -07001606// clientSessionCacheKey returns a key used to cache sessionTickets that could
1607// be used to resume previously negotiated TLS sessions with a server.
1608func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
1609 if len(config.ServerName) > 0 {
1610 return config.ServerName
1611 }
1612 return serverAddr.String()
1613}
1614
David Benjaminfa055a22014-09-15 16:51:51 -04001615// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
1616// given list of possible protocols and a list of the preference order. The
1617// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -07001618// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -04001619func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
1620 for _, s := range preferenceProtos {
1621 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -07001622 if s == c {
1623 return s, false
1624 }
1625 }
1626 }
1627
David Benjaminfa055a22014-09-15 16:51:51 -04001628 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -07001629}
David Benjamind30a9902014-08-24 01:44:23 -04001630
1631// writeIntPadded writes x into b, padded up with leading zeros as
1632// needed.
1633func writeIntPadded(b []byte, x *big.Int) {
1634 for i := range b {
1635 b[i] = 0
1636 }
1637 xb := x.Bytes()
1638 copy(b[len(b)-len(xb):], xb)
1639}
Steven Valdeza833c352016-11-01 13:39:36 -04001640
1641func generatePSKBinders(hello *clientHelloMsg, pskCipherSuite *cipherSuite, psk, transcript []byte, config *Config) {
1642 if config.Bugs.SendNoPSKBinder {
1643 return
1644 }
1645
1646 binderLen := pskCipherSuite.hash().Size()
1647 if config.Bugs.SendShortPSKBinder {
1648 binderLen--
1649 }
1650
1651 // Fill hello.pskBinders with appropriate length arrays of zeros so the
1652 // length prefixes are correct when computing the binder over the truncated
1653 // ClientHello message.
1654 hello.pskBinders = make([][]byte, len(hello.pskIdentities))
1655 for i := range hello.pskIdentities {
1656 hello.pskBinders[i] = make([]byte, binderLen)
1657 }
1658
1659 helloBytes := hello.marshal()
1660 binderSize := len(hello.pskBinders)*(binderLen+1) + 2
1661 truncatedHello := helloBytes[:len(helloBytes)-binderSize]
1662 binder := computePSKBinder(psk, resumptionPSKBinderLabel, pskCipherSuite, transcript, truncatedHello)
1663 if config.Bugs.SendShortPSKBinder {
1664 binder = binder[:binderLen]
1665 }
1666 if config.Bugs.SendInvalidPSKBinder {
1667 binder[0] ^= 1
1668 }
1669
1670 for i := range hello.pskBinders {
1671 hello.pskBinders[i] = binder
1672 }
1673
1674 hello.raw = nil
1675}