blob: f0bfca489beaee49bfea142fbb507df3a2f659f4 [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"
David Benjamind768c5d2017-03-28 18:28:44 -050022
23 "./ed25519"
Adam Langley95c29f32014-06-20 12:00:00 -070024)
25
26type clientHandshakeState struct {
David Benjamin83f90402015-01-27 01:09:43 -050027 c *Conn
28 serverHello *serverHelloMsg
29 hello *clientHelloMsg
30 suite *cipherSuite
31 finishedHash finishedHash
Nick Harperb41d2e42016-07-01 17:50:32 -040032 keyShares map[CurveID]ecdhCurve
David Benjamin83f90402015-01-27 01:09:43 -050033 masterSecret []byte
34 session *ClientSessionState
35 finishedBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070036}
37
Steven Valdezc94998a2017-06-20 10:55:02 -040038func mapClientHelloVersion(vers uint16, isDTLS bool) uint16 {
39 if !isDTLS {
40 return vers
41 }
42
43 switch vers {
44 case VersionTLS12:
45 return VersionDTLS12
46 case VersionTLS10:
47 return VersionDTLS10
48 }
49
50 panic("Unknown ClientHello version.")
51}
52
Adam Langley95c29f32014-06-20 12:00:00 -070053func (c *Conn) clientHandshake() error {
54 if c.config == nil {
55 c.config = defaultConfig()
56 }
57
58 if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
59 return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
60 }
61
David Benjamin83c0bc92014-08-04 01:23:53 -040062 c.sendHandshakeSeq = 0
63 c.recvHandshakeSeq = 0
64
David Benjaminfa055a22014-09-15 16:51:51 -040065 nextProtosLength := 0
66 for _, proto := range c.config.NextProtos {
Adam Langleyefb0e162015-07-09 11:35:04 -070067 if l := len(proto); l > 255 {
David Benjaminfa055a22014-09-15 16:51:51 -040068 return errors.New("tls: invalid NextProtos value")
69 } else {
70 nextProtosLength += 1 + l
71 }
72 }
73 if nextProtosLength > 0xffff {
74 return errors.New("tls: NextProtos values too large")
75 }
76
Steven Valdezfdd10992016-09-15 16:27:05 -040077 minVersion := c.config.minVersion(c.isDTLS)
David Benjamin3c6a1ea2016-09-26 18:30:05 -040078 maxVersion := c.config.maxVersion(c.isDTLS)
Adam Langley95c29f32014-06-20 12:00:00 -070079 hello := &clientHelloMsg{
David Benjaminca6c8262014-11-15 19:06:08 -050080 isDTLS: c.isDTLS,
David Benjaminca6c8262014-11-15 19:06:08 -050081 compressionMethods: []uint8{compressionNone},
82 random: make([]byte, 32),
David Benjamin53210cb2016-11-16 09:01:48 +090083 ocspStapling: !c.config.Bugs.NoOCSPStapling,
84 sctListSupported: !c.config.Bugs.NoSignedCertificateTimestamps,
David Benjaminca6c8262014-11-15 19:06:08 -050085 serverName: c.config.ServerName,
86 supportedCurves: c.config.curvePreferences(),
Steven Valdeza833c352016-11-01 13:39:36 -040087 pskKEModes: []byte{pskDHEKEMode},
David Benjaminca6c8262014-11-15 19:06:08 -050088 supportedPoints: []uint8{pointFormatUncompressed},
89 nextProtoNeg: len(c.config.NextProtos) > 0,
90 secureRenegotiation: []byte{},
91 alpnProtocols: c.config.NextProtos,
92 duplicateExtension: c.config.Bugs.DuplicateExtension,
93 channelIDSupported: c.config.ChannelID != nil,
Steven Valdeza833c352016-11-01 13:39:36 -040094 npnAfterAlpn: c.config.Bugs.SwapNPNAndALPN,
Steven Valdezfdd10992016-09-15 16:27:05 -040095 extendedMasterSecret: maxVersion >= VersionTLS10,
David Benjaminca6c8262014-11-15 19:06:08 -050096 srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
97 srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
Adam Langley09505632015-07-30 18:10:13 -070098 customExtension: c.config.Bugs.CustomExtension,
Steven Valdeza833c352016-11-01 13:39:36 -040099 pskBinderFirst: c.config.Bugs.PSKBinderFirst,
Adam Langley95c29f32014-06-20 12:00:00 -0700100 }
101
Steven Valdezc94998a2017-06-20 10:55:02 -0400102 if maxVersion >= VersionTLS13 {
103 hello.vers = mapClientHelloVersion(VersionTLS12, c.isDTLS)
104 if !c.config.Bugs.OmitSupportedVersions {
105 hello.supportedVersions = c.config.supportedVersions(c.isDTLS)
106 }
107 } else {
108 hello.vers = mapClientHelloVersion(maxVersion, c.isDTLS)
109 }
110
111 if c.config.Bugs.SendClientVersion != 0 {
112 hello.vers = c.config.Bugs.SendClientVersion
113 }
114
115 if len(c.config.Bugs.SendSupportedVersions) > 0 {
116 hello.supportedVersions = c.config.Bugs.SendSupportedVersions
117 }
118
David Benjamin163c9562016-08-29 23:14:17 -0400119 disableEMS := c.config.Bugs.NoExtendedMasterSecret
120 if c.cipherSuite != nil {
121 disableEMS = c.config.Bugs.NoExtendedMasterSecretOnRenegotiation
122 }
123
124 if disableEMS {
Adam Langley75712922014-10-10 16:23:43 -0700125 hello.extendedMasterSecret = false
126 }
127
David Benjamin55a43642015-04-20 14:45:55 -0400128 if c.config.Bugs.NoSupportedCurves {
129 hello.supportedCurves = nil
130 }
131
Steven Valdeza833c352016-11-01 13:39:36 -0400132 if len(c.config.Bugs.SendPSKKeyExchangeModes) != 0 {
133 hello.pskKEModes = c.config.Bugs.SendPSKKeyExchangeModes
134 }
135
David Benjaminc241d792016-09-09 10:34:20 -0400136 if c.config.Bugs.SendCompressionMethods != nil {
137 hello.compressionMethods = c.config.Bugs.SendCompressionMethods
138 }
139
David Benjamina81967b2016-12-22 09:16:57 -0500140 if c.config.Bugs.SendSupportedPointFormats != nil {
141 hello.supportedPoints = c.config.Bugs.SendSupportedPointFormats
142 }
143
Adam Langley2ae77d22014-10-28 17:29:33 -0700144 if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
145 if c.config.Bugs.BadRenegotiationInfo {
146 hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
147 hello.secureRenegotiation[0] ^= 0x80
148 } else {
149 hello.secureRenegotiation = c.clientVerify
150 }
151 }
152
David Benjamin3e052de2015-11-25 20:10:31 -0500153 if c.noRenegotiationInfo() {
David Benjaminca6554b2014-11-08 12:31:52 -0500154 hello.secureRenegotiation = nil
155 }
156
Nick Harperb41d2e42016-07-01 17:50:32 -0400157 var keyShares map[CurveID]ecdhCurve
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400158 if maxVersion >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400159 keyShares = make(map[CurveID]ecdhCurve)
Nick Harperdcfbc672016-07-16 17:47:31 +0200160 hello.hasKeyShares = true
David Benjamin7e1f9842016-09-20 19:24:40 -0400161 hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
Nick Harperdcfbc672016-07-16 17:47:31 +0200162 curvesToSend := c.config.defaultCurves()
Nick Harperb41d2e42016-07-01 17:50:32 -0400163 for _, curveID := range hello.supportedCurves {
Nick Harperdcfbc672016-07-16 17:47:31 +0200164 if !curvesToSend[curveID] {
165 continue
166 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400167 curve, ok := curveForCurveID(curveID)
168 if !ok {
169 continue
170 }
171 publicKey, err := curve.offer(c.config.rand())
172 if err != nil {
173 return err
174 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400175
176 if c.config.Bugs.SendCurve != 0 {
177 curveID = c.config.Bugs.SendCurve
178 }
179 if c.config.Bugs.InvalidECDHPoint {
180 publicKey[0] ^= 0xff
181 }
182
Nick Harperb41d2e42016-07-01 17:50:32 -0400183 hello.keyShares = append(hello.keyShares, keyShareEntry{
184 group: curveID,
185 keyExchange: publicKey,
186 })
187 keyShares[curveID] = curve
Steven Valdez143e8b32016-07-11 13:19:03 -0400188
189 if c.config.Bugs.DuplicateKeyShares {
190 hello.keyShares = append(hello.keyShares, hello.keyShares[len(hello.keyShares)-1])
191 }
192 }
193
194 if c.config.Bugs.MissingKeyShare {
Steven Valdez5440fe02016-07-18 12:40:30 -0400195 hello.hasKeyShares = false
Nick Harperb41d2e42016-07-01 17:50:32 -0400196 }
197 }
198
Adam Langley95c29f32014-06-20 12:00:00 -0700199 possibleCipherSuites := c.config.cipherSuites()
200 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
201
202NextCipherSuite:
203 for _, suiteId := range possibleCipherSuites {
204 for _, suite := range cipherSuites {
205 if suite.id != suiteId {
206 continue
207 }
David Benjamin5ecb88b2016-10-04 17:51:35 -0400208 // Don't advertise TLS 1.2-only cipher suites unless
209 // we're attempting TLS 1.2.
210 if maxVersion < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
211 continue
212 }
213 // Don't advertise non-DTLS cipher suites in DTLS.
214 if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
215 continue
David Benjamin83c0bc92014-08-04 01:23:53 -0400216 }
Adam Langley95c29f32014-06-20 12:00:00 -0700217 hello.cipherSuites = append(hello.cipherSuites, suiteId)
218 continue NextCipherSuite
219 }
220 }
221
David Benjamin5ecb88b2016-10-04 17:51:35 -0400222 if c.config.Bugs.AdvertiseAllConfiguredCiphers {
223 hello.cipherSuites = possibleCipherSuites
224 }
225
Adam Langley5021b222015-06-12 18:27:58 -0700226 if c.config.Bugs.SendRenegotiationSCSV {
227 hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
228 }
229
David Benjaminbef270a2014-08-02 04:22:02 -0400230 if c.config.Bugs.SendFallbackSCSV {
231 hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
232 }
233
Adam Langley95c29f32014-06-20 12:00:00 -0700234 _, err := io.ReadFull(c.config.rand(), hello.random)
235 if err != nil {
236 c.sendAlert(alertInternalError)
237 return errors.New("tls: short read from Rand: " + err.Error())
238 }
239
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400240 if maxVersion >= VersionTLS12 && !c.config.Bugs.NoSignatureAlgorithms {
David Benjamin7a41d372016-07-09 11:21:54 -0700241 hello.signatureAlgorithms = c.config.verifySignatureAlgorithms()
Adam Langley95c29f32014-06-20 12:00:00 -0700242 }
243
244 var session *ClientSessionState
245 var cacheKey string
246 sessionCache := c.config.ClientSessionCache
Adam Langley95c29f32014-06-20 12:00:00 -0700247
248 if sessionCache != nil {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500249 hello.ticketSupported = !c.config.SessionTicketsDisabled
Adam Langley95c29f32014-06-20 12:00:00 -0700250
251 // Try to resume a previously negotiated TLS session, if
252 // available.
253 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
Nick Harper0b3625b2016-07-25 16:16:28 -0700254 // TODO(nharper): Support storing more than one session
255 // ticket for TLS 1.3.
Adam Langley95c29f32014-06-20 12:00:00 -0700256 candidateSession, ok := sessionCache.Get(cacheKey)
257 if ok {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500258 ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
259
Adam Langley95c29f32014-06-20 12:00:00 -0700260 // Check that the ciphersuite/version used for the
261 // previous session are still valid.
262 cipherSuiteOk := false
David Benjamin2b02f4b2016-11-16 16:11:47 +0900263 if candidateSession.vers <= VersionTLS12 {
264 for _, id := range hello.cipherSuites {
265 if id == candidateSession.cipherSuite {
266 cipherSuiteOk = true
267 break
268 }
Adam Langley95c29f32014-06-20 12:00:00 -0700269 }
David Benjamin2b02f4b2016-11-16 16:11:47 +0900270 } else {
271 // TLS 1.3 allows the cipher to change on
272 // resumption.
273 cipherSuiteOk = true
Adam Langley95c29f32014-06-20 12:00:00 -0700274 }
275
Steven Valdezfdd10992016-09-15 16:27:05 -0400276 versOk := candidateSession.vers >= minVersion &&
277 candidateSession.vers <= maxVersion
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500278 if ticketOk && versOk && cipherSuiteOk {
Adam Langley95c29f32014-06-20 12:00:00 -0700279 session = candidateSession
280 }
281 }
282 }
283
Steven Valdeza833c352016-11-01 13:39:36 -0400284 var pskCipherSuite *cipherSuite
Nick Harper0b3625b2016-07-25 16:16:28 -0700285 if session != nil && c.config.time().Before(session.ticketExpiration) {
David Benjamind5a4ecb2016-07-18 01:17:13 +0200286 ticket := session.sessionTicket
David Benjamin4199b0d2016-11-01 13:58:25 -0400287 if c.config.Bugs.FilterTicket != nil && len(ticket) > 0 {
288 // Copy the ticket so FilterTicket may act in-place.
David Benjamind5a4ecb2016-07-18 01:17:13 +0200289 ticket = make([]byte, len(session.sessionTicket))
290 copy(ticket, session.sessionTicket)
David Benjamin4199b0d2016-11-01 13:58:25 -0400291
292 ticket, err = c.config.Bugs.FilterTicket(ticket)
293 if err != nil {
294 return err
Adam Langley38311732014-10-16 19:04:35 -0700295 }
David Benjamind5a4ecb2016-07-18 01:17:13 +0200296 }
297
David Benjamin405da482016-08-08 17:25:07 -0400298 if session.vers >= VersionTLS13 || c.config.Bugs.SendBothTickets {
Steven Valdeza833c352016-11-01 13:39:36 -0400299 pskCipherSuite = cipherSuiteFromID(session.cipherSuite)
300 if pskCipherSuite == nil {
301 return errors.New("tls: client session cache has invalid cipher suite")
302 }
Nick Harper0b3625b2016-07-25 16:16:28 -0700303 // TODO(nharper): Support sending more
304 // than one PSK identity.
Steven Valdeza833c352016-11-01 13:39:36 -0400305 ticketAge := uint32(c.config.time().Sub(session.ticketCreationTime) / time.Millisecond)
David Benjamin35ac5b72017-03-03 15:05:56 -0500306 if c.config.Bugs.SendTicketAge != 0 {
307 ticketAge = uint32(c.config.Bugs.SendTicketAge / time.Millisecond)
308 }
Steven Valdez5b986082016-09-01 12:29:49 -0400309 psk := pskIdentity{
Steven Valdeza833c352016-11-01 13:39:36 -0400310 ticket: ticket,
311 obfuscatedTicketAge: session.ticketAgeAdd + ticketAge,
Nick Harper0b3625b2016-07-25 16:16:28 -0700312 }
Steven Valdez5b986082016-09-01 12:29:49 -0400313 hello.pskIdentities = []pskIdentity{psk}
Steven Valdezaf3b8a92016-11-01 12:49:22 -0400314
315 if c.config.Bugs.ExtraPSKIdentity {
316 hello.pskIdentities = append(hello.pskIdentities, psk)
317 }
David Benjamin405da482016-08-08 17:25:07 -0400318 }
319
320 if session.vers < VersionTLS13 || c.config.Bugs.SendBothTickets {
321 if ticket != nil {
322 hello.sessionTicket = ticket
323 // A random session ID is used to detect when the
324 // server accepted the ticket and is resuming a session
325 // (see RFC 5077).
326 sessionIdLen := 16
David Benjamind4c349b2017-02-09 14:07:17 -0500327 if c.config.Bugs.TicketSessionIDLength != 0 {
328 sessionIdLen = c.config.Bugs.TicketSessionIDLength
329 }
330 if c.config.Bugs.EmptyTicketSessionID {
331 sessionIdLen = 0
David Benjamin405da482016-08-08 17:25:07 -0400332 }
333 hello.sessionId = make([]byte, sessionIdLen)
334 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
335 c.sendAlert(alertInternalError)
336 return errors.New("tls: short read from Rand: " + err.Error())
337 }
338 } else {
339 hello.sessionId = session.sessionId
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500340 }
Adam Langley95c29f32014-06-20 12:00:00 -0700341 }
342 }
343
David Benjamin75f99142016-11-12 12:36:06 +0900344 if c.config.Bugs.SendCipherSuites != nil {
345 hello.cipherSuites = c.config.Bugs.SendCipherSuites
346 }
347
Nick Harperf2511f12016-12-06 16:02:31 -0800348 var sendEarlyData bool
Steven Valdez2d850622017-01-11 11:34:52 -0500349 if len(hello.pskIdentities) > 0 && c.config.Bugs.SendEarlyData != nil {
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500350 hello.hasEarlyData = true
Nick Harperf2511f12016-12-06 16:02:31 -0800351 sendEarlyData = true
352 }
353 if c.config.Bugs.SendFakeEarlyDataLength > 0 {
354 hello.hasEarlyData = true
355 }
356 if c.config.Bugs.OmitEarlyDataExtension {
357 hello.hasEarlyData = false
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500358 }
359
David Benjamind86c7672014-08-02 04:07:12 -0400360 var helloBytes []byte
361 if c.config.Bugs.SendV2ClientHello {
David Benjamin94d701b2014-11-30 13:54:41 -0500362 // Test that the peer left-pads random.
363 hello.random[0] = 0
David Benjamind86c7672014-08-02 04:07:12 -0400364 v2Hello := &v2ClientHelloMsg{
365 vers: hello.vers,
366 cipherSuites: hello.cipherSuites,
367 // No session resumption for V2ClientHello.
368 sessionId: nil,
David Benjamin94d701b2014-11-30 13:54:41 -0500369 challenge: hello.random[1:],
David Benjamind86c7672014-08-02 04:07:12 -0400370 }
371 helloBytes = v2Hello.marshal()
372 c.writeV2Record(helloBytes)
373 } else {
Steven Valdeza833c352016-11-01 13:39:36 -0400374 if len(hello.pskIdentities) > 0 {
375 generatePSKBinders(hello, pskCipherSuite, session.masterSecret, []byte{}, c.config)
376 }
David Benjamind86c7672014-08-02 04:07:12 -0400377 helloBytes = hello.marshal()
Steven Valdeza833c352016-11-01 13:39:36 -0400378
David Benjamin7964b182016-07-14 23:36:30 -0400379 if c.config.Bugs.PartialClientFinishedWithClientHello {
380 // Include one byte of Finished. We can compute it
381 // without completing the handshake. This assumes we
382 // negotiate TLS 1.3 with no HelloRetryRequest or
383 // CertificateRequest.
384 toWrite := make([]byte, 0, len(helloBytes)+1)
385 toWrite = append(toWrite, helloBytes...)
386 toWrite = append(toWrite, typeFinished)
387 c.writeRecord(recordTypeHandshake, toWrite)
388 } else {
389 c.writeRecord(recordTypeHandshake, helloBytes)
390 }
David Benjamind86c7672014-08-02 04:07:12 -0400391 }
David Benjamin582ba042016-07-07 12:33:25 -0700392 c.flushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700393
David Benjamin83f90402015-01-27 01:09:43 -0500394 if err := c.simulatePacketLoss(nil); err != nil {
395 return err
396 }
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500397 if c.config.Bugs.SendEarlyAlert {
398 c.sendAlert(alertHandshakeFailure)
399 }
Nick Harperf2511f12016-12-06 16:02:31 -0800400 if c.config.Bugs.SendFakeEarlyDataLength > 0 {
401 c.sendFakeEarlyData(c.config.Bugs.SendFakeEarlyDataLength)
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500402 }
Nick Harperf2511f12016-12-06 16:02:31 -0800403
404 // Derive early write keys and set Conn state to allow early writes.
405 if sendEarlyData {
406 finishedHash := newFinishedHash(session.vers, pskCipherSuite)
407 finishedHash.addEntropy(session.masterSecret)
408 finishedHash.Write(helloBytes)
409 earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
410 c.out.useTrafficSecret(session.vers, pskCipherSuite, earlyTrafficSecret, clientWrite)
Nick Harperf2511f12016-12-06 16:02:31 -0800411 for _, earlyData := range c.config.Bugs.SendEarlyData {
412 if _, err := c.writeRecord(recordTypeApplicationData, earlyData); err != nil {
413 return err
414 }
415 }
416 }
417
Adam Langley95c29f32014-06-20 12:00:00 -0700418 msg, err := c.readHandshake()
419 if err != nil {
420 return err
421 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400422
423 if c.isDTLS {
424 helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
425 if ok {
Steven Valdezc94998a2017-06-20 10:55:02 -0400426 if helloVerifyRequest.vers != VersionDTLS10 {
David Benjamin8bc38f52014-08-16 12:07:27 -0400427 // Per RFC 6347, the version field in
428 // HelloVerifyRequest SHOULD be always DTLS
429 // 1.0. Enforce this for testing purposes.
430 return errors.New("dtls: bad HelloVerifyRequest version")
431 }
432
David Benjamin83c0bc92014-08-04 01:23:53 -0400433 hello.raw = nil
434 hello.cookie = helloVerifyRequest.cookie
435 helloBytes = hello.marshal()
436 c.writeRecord(recordTypeHandshake, helloBytes)
David Benjamin582ba042016-07-07 12:33:25 -0700437 c.flushHandshake()
David Benjamin83c0bc92014-08-04 01:23:53 -0400438
David Benjamin83f90402015-01-27 01:09:43 -0500439 if err := c.simulatePacketLoss(nil); err != nil {
440 return err
441 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400442 msg, err = c.readHandshake()
443 if err != nil {
444 return err
445 }
446 }
447 }
448
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400449 var serverWireVersion uint16
Nick Harperdcfbc672016-07-16 17:47:31 +0200450 switch m := msg.(type) {
451 case *helloRetryRequestMsg:
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400452 serverWireVersion = m.vers
Nick Harperdcfbc672016-07-16 17:47:31 +0200453 case *serverHelloMsg:
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400454 serverWireVersion = m.vers
Nick Harperdcfbc672016-07-16 17:47:31 +0200455 default:
456 c.sendAlert(alertUnexpectedMessage)
457 return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg)
458 }
459
Steven Valdezc94998a2017-06-20 10:55:02 -0400460 serverVersion, ok := c.config.isSupportedVersion(serverWireVersion, c.isDTLS)
Nick Harperdcfbc672016-07-16 17:47:31 +0200461 if !ok {
462 c.sendAlert(alertProtocolVersion)
463 return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers)
464 }
Steven Valdezc94998a2017-06-20 10:55:02 -0400465 c.wireVersion = serverWireVersion
Steven Valdezfdd10992016-09-15 16:27:05 -0400466 c.vers = serverVersion
Nick Harperdcfbc672016-07-16 17:47:31 +0200467 c.haveVers = true
468
469 helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
470 var secondHelloBytes []byte
471 if haveHelloRetryRequest {
Nick Harperf2511f12016-12-06 16:02:31 -0800472 c.out.resetCipher()
David Benjamin3baa6e12016-10-07 21:10:38 -0400473 if len(helloRetryRequest.cookie) > 0 {
474 hello.tls13Cookie = helloRetryRequest.cookie
475 }
476
Steven Valdez5440fe02016-07-18 12:40:30 -0400477 if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
David Benjamin3baa6e12016-10-07 21:10:38 -0400478 helloRetryRequest.hasSelectedGroup = true
Steven Valdez5440fe02016-07-18 12:40:30 -0400479 helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
480 }
David Benjamin3baa6e12016-10-07 21:10:38 -0400481 if helloRetryRequest.hasSelectedGroup {
482 var hrrCurveFound bool
483 group := helloRetryRequest.selectedGroup
484 for _, curveID := range hello.supportedCurves {
485 if group == curveID {
486 hrrCurveFound = true
487 break
488 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200489 }
David Benjamin3baa6e12016-10-07 21:10:38 -0400490 if !hrrCurveFound || keyShares[group] != nil {
491 c.sendAlert(alertHandshakeFailure)
492 return errors.New("tls: received invalid HelloRetryRequest")
493 }
494 curve, ok := curveForCurveID(group)
495 if !ok {
496 return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
497 }
498 publicKey, err := curve.offer(c.config.rand())
499 if err != nil {
500 return err
501 }
502 keyShares[group] = curve
Steven Valdeza833c352016-11-01 13:39:36 -0400503 hello.keyShares = []keyShareEntry{{
David Benjamin3baa6e12016-10-07 21:10:38 -0400504 group: group,
505 keyExchange: publicKey,
Steven Valdeza833c352016-11-01 13:39:36 -0400506 }}
Nick Harperdcfbc672016-07-16 17:47:31 +0200507 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200508
Steven Valdez5440fe02016-07-18 12:40:30 -0400509 if c.config.Bugs.SecondClientHelloMissingKeyShare {
510 hello.hasKeyShares = false
511 }
512
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500513 hello.hasEarlyData = c.config.Bugs.SendEarlyDataOnSecondClientHello
Nick Harperdcfbc672016-07-16 17:47:31 +0200514 hello.raw = nil
515
Steven Valdeza833c352016-11-01 13:39:36 -0400516 if len(hello.pskIdentities) > 0 {
517 generatePSKBinders(hello, pskCipherSuite, session.masterSecret, append(helloBytes, helloRetryRequest.marshal()...), c.config)
518 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200519 secondHelloBytes = hello.marshal()
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500520
521 if c.config.Bugs.InterleaveEarlyData {
522 c.sendFakeEarlyData(4)
523 c.writeRecord(recordTypeHandshake, secondHelloBytes[:16])
524 c.sendFakeEarlyData(4)
525 c.writeRecord(recordTypeHandshake, secondHelloBytes[16:])
526 } else {
527 c.writeRecord(recordTypeHandshake, secondHelloBytes)
528 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200529 c.flushHandshake()
530
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500531 if c.config.Bugs.SendEarlyDataOnSecondClientHello {
532 c.sendFakeEarlyData(4)
533 }
534
Nick Harperdcfbc672016-07-16 17:47:31 +0200535 msg, err = c.readHandshake()
536 if err != nil {
537 return err
538 }
539 }
540
Adam Langley95c29f32014-06-20 12:00:00 -0700541 serverHello, ok := msg.(*serverHelloMsg)
542 if !ok {
543 c.sendAlert(alertUnexpectedMessage)
544 return unexpectedMessageError(serverHello, msg)
545 }
546
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400547 if serverWireVersion != serverHello.vers {
Adam Langley95c29f32014-06-20 12:00:00 -0700548 c.sendAlert(alertProtocolVersion)
David Benjamin3c6a1ea2016-09-26 18:30:05 -0400549 return fmt.Errorf("tls: server sent non-matching version %x vs %x", serverWireVersion, serverHello.vers)
Adam Langley95c29f32014-06-20 12:00:00 -0700550 }
Adam Langley95c29f32014-06-20 12:00:00 -0700551
Nick Harper85f20c22016-07-04 10:11:59 -0700552 // Check for downgrade signals in the server random, per
David Benjamina128a552016-10-13 14:26:33 -0400553 // draft-ietf-tls-tls13-16, section 4.1.3.
Nick Harper85f20c22016-07-04 10:11:59 -0700554 if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400555 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS13) {
Nick Harper85f20c22016-07-04 10:11:59 -0700556 c.sendAlert(alertProtocolVersion)
557 return errors.New("tls: downgrade from TLS 1.3 detected")
558 }
559 }
560 if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400561 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS12) {
Nick Harper85f20c22016-07-04 10:11:59 -0700562 c.sendAlert(alertProtocolVersion)
563 return errors.New("tls: downgrade from TLS 1.2 detected")
564 }
565 }
566
Nick Harper0b3625b2016-07-25 16:16:28 -0700567 suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite)
Adam Langley95c29f32014-06-20 12:00:00 -0700568 if suite == nil {
569 c.sendAlert(alertHandshakeFailure)
570 return fmt.Errorf("tls: server selected an unsupported cipher suite")
571 }
572
David Benjamin3baa6e12016-10-07 21:10:38 -0400573 if haveHelloRetryRequest && helloRetryRequest.hasSelectedGroup && helloRetryRequest.selectedGroup != serverHello.keyShare.group {
Nick Harperdcfbc672016-07-16 17:47:31 +0200574 c.sendAlert(alertHandshakeFailure)
575 return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
576 }
577
Adam Langley95c29f32014-06-20 12:00:00 -0700578 hs := &clientHandshakeState{
579 c: c,
580 serverHello: serverHello,
581 hello: hello,
582 suite: suite,
583 finishedHash: newFinishedHash(c.vers, suite),
Nick Harperb41d2e42016-07-01 17:50:32 -0400584 keyShares: keyShares,
Adam Langley95c29f32014-06-20 12:00:00 -0700585 session: session,
586 }
587
David Benjamin83c0bc92014-08-04 01:23:53 -0400588 hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
Nick Harperdcfbc672016-07-16 17:47:31 +0200589 if haveHelloRetryRequest {
590 hs.writeServerHash(helloRetryRequest.marshal())
591 hs.writeClientHash(secondHelloBytes)
592 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400593 hs.writeServerHash(hs.serverHello.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700594
David Benjamin8d315d72016-07-18 01:03:18 +0200595 if c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400596 if err := hs.doTLS13Handshake(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700597 return err
598 }
599 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400600 if c.config.Bugs.EarlyChangeCipherSpec > 0 {
601 hs.establishKeys()
602 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
603 }
604
605 if hs.serverHello.compressionMethod != compressionNone {
606 c.sendAlert(alertUnexpectedMessage)
607 return errors.New("tls: server selected unsupported compression format")
608 }
609
610 err = hs.processServerExtensions(&serverHello.extensions)
611 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700612 return err
613 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400614
615 isResume, err := hs.processServerHello()
616 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700617 return err
618 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400619
620 if isResume {
621 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
622 if err := hs.establishKeys(); err != nil {
623 return err
624 }
625 }
626 if err := hs.readSessionTicket(); err != nil {
627 return err
628 }
629 if err := hs.readFinished(c.firstFinished[:]); err != nil {
630 return err
631 }
632 if err := hs.sendFinished(nil, isResume); err != nil {
633 return err
634 }
635 } else {
636 if err := hs.doFullHandshake(); err != nil {
637 return err
638 }
639 if err := hs.establishKeys(); err != nil {
640 return err
641 }
642 if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
643 return err
644 }
645 // Most retransmits are triggered by a timeout, but the final
646 // leg of the handshake is retransmited upon re-receiving a
647 // Finished.
648 if err := c.simulatePacketLoss(func() {
David Benjamin02edcd02016-07-27 17:40:37 -0400649 c.sendHandshakeSeq--
Nick Harperb41d2e42016-07-01 17:50:32 -0400650 c.writeRecord(recordTypeHandshake, hs.finishedBytes)
651 c.flushHandshake()
652 }); err != nil {
653 return err
654 }
655 if err := hs.readSessionTicket(); err != nil {
656 return err
657 }
658 if err := hs.readFinished(nil); err != nil {
659 return err
660 }
Adam Langley95c29f32014-06-20 12:00:00 -0700661 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400662
663 if sessionCache != nil && hs.session != nil && session != hs.session {
664 if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
665 return errors.New("tls: new session used session IDs instead of tickets")
666 }
667 sessionCache.Put(cacheKey, hs.session)
David Benjamin83f90402015-01-27 01:09:43 -0500668 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400669
670 c.didResume = isResume
David Benjamin97a0a082016-07-13 17:57:35 -0400671 c.exporterSecret = hs.masterSecret
Adam Langley95c29f32014-06-20 12:00:00 -0700672 }
673
Adam Langley95c29f32014-06-20 12:00:00 -0700674 c.handshakeComplete = true
David Benjaminc565ebb2015-04-03 04:06:36 -0400675 c.cipherSuite = suite
676 copy(c.clientRandom[:], hs.hello.random)
677 copy(c.serverRandom[:], hs.serverHello.random)
Paul Lietar4fac72e2015-09-09 13:44:55 +0100678
Adam Langley95c29f32014-06-20 12:00:00 -0700679 return nil
680}
681
Nick Harperb41d2e42016-07-01 17:50:32 -0400682func (hs *clientHandshakeState) doTLS13Handshake() error {
683 c := hs.c
684
685 // Once the PRF hash is known, TLS 1.3 does not require a handshake
686 // buffer.
687 hs.finishedHash.discardHandshakeBuffer()
688
689 zeroSecret := hs.finishedHash.zeroSecret()
690
691 // Resolve PSK and compute the early secret.
692 //
693 // TODO(davidben): This will need to be handled slightly earlier once
694 // 0-RTT is implemented.
Steven Valdez803c77a2016-09-06 14:13:43 -0400695 if hs.serverHello.hasPSKIdentity {
Nick Harper0b3625b2016-07-25 16:16:28 -0700696 // We send at most one PSK identity.
697 if hs.session == nil || hs.serverHello.pskIdentity != 0 {
698 c.sendAlert(alertUnknownPSKIdentity)
699 return errors.New("tls: server sent unknown PSK identity")
700 }
David Benjamin2b02f4b2016-11-16 16:11:47 +0900701 sessionCipher := cipherSuiteFromID(hs.session.cipherSuite)
702 if sessionCipher == nil || sessionCipher.hash() != hs.suite.hash() {
Nick Harper0b3625b2016-07-25 16:16:28 -0700703 c.sendAlert(alertHandshakeFailure)
David Benjamin2b02f4b2016-11-16 16:11:47 +0900704 return errors.New("tls: server resumed an invalid session for the cipher suite")
Nick Harper0b3625b2016-07-25 16:16:28 -0700705 }
David Benjamin48891ad2016-12-04 00:02:43 -0500706 hs.finishedHash.addEntropy(hs.session.masterSecret)
Nick Harper0b3625b2016-07-25 16:16:28 -0700707 c.didResume = true
Nick Harperb41d2e42016-07-01 17:50:32 -0400708 } else {
David Benjamin48891ad2016-12-04 00:02:43 -0500709 hs.finishedHash.addEntropy(zeroSecret)
Nick Harperb41d2e42016-07-01 17:50:32 -0400710 }
711
Steven Valdeza833c352016-11-01 13:39:36 -0400712 if !hs.serverHello.hasKeyShare {
713 c.sendAlert(alertUnsupportedExtension)
714 return errors.New("tls: server omitted KeyShare on resumption.")
715 }
716
Nick Harperb41d2e42016-07-01 17:50:32 -0400717 // Resolve ECDHE and compute the handshake secret.
Steven Valdez803c77a2016-09-06 14:13:43 -0400718 if !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
Nick Harperb41d2e42016-07-01 17:50:32 -0400719 curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
720 if !ok {
721 c.sendAlert(alertHandshakeFailure)
722 return errors.New("tls: server selected an unsupported group")
723 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400724 c.curveID = hs.serverHello.keyShare.group
Nick Harperb41d2e42016-07-01 17:50:32 -0400725
David Benjamin48891ad2016-12-04 00:02:43 -0500726 ecdheSecret, err := curve.finish(hs.serverHello.keyShare.keyExchange)
Nick Harperb41d2e42016-07-01 17:50:32 -0400727 if err != nil {
728 return err
729 }
David Benjamin48891ad2016-12-04 00:02:43 -0500730 hs.finishedHash.addEntropy(ecdheSecret)
Nick Harperb41d2e42016-07-01 17:50:32 -0400731 } else {
David Benjamin48891ad2016-12-04 00:02:43 -0500732 hs.finishedHash.addEntropy(zeroSecret)
Nick Harperb41d2e42016-07-01 17:50:32 -0400733 }
734
Nick Harperf2511f12016-12-06 16:02:31 -0800735 // Derive handshake traffic keys and switch read key to handshake
736 // traffic key.
David Benjamin48891ad2016-12-04 00:02:43 -0500737 clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
David Benjamin48891ad2016-12-04 00:02:43 -0500738 serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
Steven Valdeza833c352016-11-01 13:39:36 -0400739 c.in.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400740
741 msg, err := c.readHandshake()
742 if err != nil {
743 return err
744 }
745
746 encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
747 if !ok {
748 c.sendAlert(alertUnexpectedMessage)
749 return unexpectedMessageError(encryptedExtensions, msg)
750 }
751 hs.writeServerHash(encryptedExtensions.marshal())
752
753 err = hs.processServerExtensions(&encryptedExtensions.extensions)
754 if err != nil {
755 return err
756 }
757
758 var chainToSend *Certificate
David Benjamin8d343b42016-07-09 14:26:01 -0700759 var certReq *certificateRequestMsg
Steven Valdeza833c352016-11-01 13:39:36 -0400760 if c.didResume {
Nick Harper0b3625b2016-07-25 16:16:28 -0700761 // Copy over authentication from the session.
762 c.peerCertificates = hs.session.serverCertificates
763 c.sctList = hs.session.sctList
764 c.ocspResponse = hs.session.ocspResponse
David Benjamin44b33bc2016-07-01 22:40:23 -0400765 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400766 msg, err := c.readHandshake()
767 if err != nil {
768 return err
769 }
770
David Benjamin8d343b42016-07-09 14:26:01 -0700771 var ok bool
772 certReq, ok = msg.(*certificateRequestMsg)
Nick Harperb41d2e42016-07-01 17:50:32 -0400773 if ok {
David Benjamin8a8349b2016-08-18 02:32:23 -0400774 if len(certReq.requestContext) != 0 {
775 return errors.New("tls: non-empty certificate request context sent in handshake")
776 }
777
David Benjaminb62d2872016-07-18 14:55:02 +0200778 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
779 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
780 }
781
Nick Harperb41d2e42016-07-01 17:50:32 -0400782 hs.writeServerHash(certReq.marshal())
Nick Harperb41d2e42016-07-01 17:50:32 -0400783
784 chainToSend, err = selectClientCertificate(c, certReq)
785 if err != nil {
786 return err
787 }
788
789 msg, err = c.readHandshake()
790 if err != nil {
791 return err
792 }
793 }
794
795 certMsg, ok := msg.(*certificateMsg)
796 if !ok {
797 c.sendAlert(alertUnexpectedMessage)
798 return unexpectedMessageError(certMsg, msg)
799 }
800 hs.writeServerHash(certMsg.marshal())
801
David Benjamin53210cb2016-11-16 09:01:48 +0900802 // Check for unsolicited extensions.
803 for i, cert := range certMsg.certificates {
804 if c.config.Bugs.NoOCSPStapling && cert.ocspResponse != nil {
805 c.sendAlert(alertUnsupportedExtension)
806 return errors.New("tls: unexpected OCSP response in the server certificate")
807 }
808 if c.config.Bugs.NoSignedCertificateTimestamps && cert.sctList != nil {
809 c.sendAlert(alertUnsupportedExtension)
810 return errors.New("tls: unexpected SCT list in the server certificate")
811 }
812 if i > 0 && c.config.Bugs.ExpectNoExtensionsOnIntermediate && (cert.ocspResponse != nil || cert.sctList != nil) {
813 c.sendAlert(alertUnsupportedExtension)
814 return errors.New("tls: unexpected extensions in the server certificate")
815 }
816 }
817
Nick Harperb41d2e42016-07-01 17:50:32 -0400818 if err := hs.verifyCertificates(certMsg); err != nil {
819 return err
820 }
821 leaf := c.peerCertificates[0]
Steven Valdeza833c352016-11-01 13:39:36 -0400822 c.ocspResponse = certMsg.certificates[0].ocspResponse
823 c.sctList = certMsg.certificates[0].sctList
824
Nick Harperb41d2e42016-07-01 17:50:32 -0400825 msg, err = c.readHandshake()
826 if err != nil {
827 return err
828 }
829 certVerifyMsg, ok := msg.(*certificateVerifyMsg)
830 if !ok {
831 c.sendAlert(alertUnexpectedMessage)
832 return unexpectedMessageError(certVerifyMsg, msg)
833 }
834
David Benjaminf74ec792016-07-13 21:18:49 -0400835 c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
Nick Harperb41d2e42016-07-01 17:50:32 -0400836 input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
David Benjamind768c5d2017-03-28 18:28:44 -0500837 err = verifyMessage(c.vers, getCertificatePublicKey(leaf), c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
Nick Harperb41d2e42016-07-01 17:50:32 -0400838 if err != nil {
839 return err
840 }
841
842 hs.writeServerHash(certVerifyMsg.marshal())
843 }
844
845 msg, err = c.readHandshake()
846 if err != nil {
847 return err
848 }
849 serverFinished, ok := msg.(*finishedMsg)
850 if !ok {
851 c.sendAlert(alertUnexpectedMessage)
852 return unexpectedMessageError(serverFinished, msg)
853 }
854
Steven Valdezc4aa7272016-10-03 12:25:56 -0400855 verify := hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
Nick Harperb41d2e42016-07-01 17:50:32 -0400856 if len(verify) != len(serverFinished.verifyData) ||
857 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
858 c.sendAlert(alertHandshakeFailure)
859 return errors.New("tls: server's Finished message was incorrect")
860 }
861
862 hs.writeServerHash(serverFinished.marshal())
863
864 // The various secrets do not incorporate the client's final leg, so
865 // derive them now before updating the handshake context.
David Benjamin48891ad2016-12-04 00:02:43 -0500866 hs.finishedHash.addEntropy(zeroSecret)
867 clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
868 serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
David Benjamincdb6fe92017-02-07 16:06:48 -0500869 c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
870
871 // Switch to application data keys on read. In particular, any alerts
872 // from the client certificate are read over these keys.
Nick Harper7cd0a972016-12-02 11:08:40 -0800873 c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
874
875 // If we're expecting 0.5-RTT messages from the server, read them
876 // now.
David Benjamin794cc592017-03-25 22:24:23 -0500877 if encryptedExtensions.extensions.hasEarlyData {
878 // BoringSSL will always send two tickets half-RTT when
879 // negotiating 0-RTT.
880 for i := 0; i < shimConfig.HalfRTTTickets; i++ {
881 msg, err := c.readHandshake()
882 if err != nil {
883 return fmt.Errorf("tls: error reading half-RTT ticket: %s", err)
884 }
885 newSessionTicket, ok := msg.(*newSessionTicketMsg)
886 if !ok {
887 return errors.New("tls: expected half-RTT ticket")
888 }
889 if err := c.processTLS13NewSessionTicket(newSessionTicket, hs.suite); err != nil {
890 return err
891 }
Nick Harper7cd0a972016-12-02 11:08:40 -0800892 }
David Benjamin794cc592017-03-25 22:24:23 -0500893 for _, expectedMsg := range c.config.Bugs.ExpectHalfRTTData {
894 if err := c.readRecord(recordTypeApplicationData); err != nil {
895 return err
896 }
897 if !bytes.Equal(c.input.data[c.input.off:], expectedMsg) {
898 return errors.New("ExpectHalfRTTData: did not get expected message")
899 }
900 c.in.freeBlock(c.input)
901 c.input = nil
Nick Harper7cd0a972016-12-02 11:08:40 -0800902 }
Nick Harper7cd0a972016-12-02 11:08:40 -0800903 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400904
Nick Harperf2511f12016-12-06 16:02:31 -0800905 // Send EndOfEarlyData and then switch write key to handshake
906 // traffic key.
David Benjamin32c89272017-03-26 13:54:21 -0500907 if c.out.cipher != nil && !c.config.Bugs.SkipEndOfEarlyData {
Steven Valdez681eb6a2016-12-19 13:19:29 -0500908 if c.config.Bugs.SendStrayEarlyHandshake {
909 helloRequest := new(helloRequestMsg)
910 c.writeRecord(recordTypeHandshake, helloRequest.marshal())
911 }
Nick Harperf2511f12016-12-06 16:02:31 -0800912 c.sendAlert(alertEndOfEarlyData)
913 }
914 c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
915
Steven Valdez0ee2e112016-07-15 06:51:15 -0400916 if certReq != nil && !c.config.Bugs.SkipClientCertificate {
David Benjamin8d343b42016-07-09 14:26:01 -0700917 certMsg := &certificateMsg{
918 hasRequestContext: true,
919 requestContext: certReq.requestContext,
920 }
921 if chainToSend != nil {
Steven Valdeza833c352016-11-01 13:39:36 -0400922 for _, certData := range chainToSend.Certificate {
923 certMsg.certificates = append(certMsg.certificates, certificateEntry{
924 data: certData,
925 extraExtension: c.config.Bugs.SendExtensionOnCertificate,
926 })
927 }
David Benjamin8d343b42016-07-09 14:26:01 -0700928 }
929 hs.writeClientHash(certMsg.marshal())
930 c.writeRecord(recordTypeHandshake, certMsg.marshal())
931
932 if chainToSend != nil {
933 certVerify := &certificateVerifyMsg{
934 hasSignatureAlgorithm: true,
935 }
936
937 // Determine the hash to sign.
938 privKey := chainToSend.PrivateKey
939
940 var err error
941 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
942 if err != nil {
943 c.sendAlert(alertInternalError)
944 return err
945 }
946
947 input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
948 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
949 if err != nil {
950 c.sendAlert(alertInternalError)
951 return err
952 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400953 if c.config.Bugs.SendSignatureAlgorithm != 0 {
954 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
955 }
David Benjamin8d343b42016-07-09 14:26:01 -0700956
957 hs.writeClientHash(certVerify.marshal())
958 c.writeRecord(recordTypeHandshake, certVerify.marshal())
959 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400960 }
961
Nick Harper60a85cb2016-09-23 16:25:11 -0700962 if encryptedExtensions.extensions.channelIDRequested {
963 channelIDHash := crypto.SHA256.New()
964 channelIDHash.Write(hs.finishedHash.certificateVerifyInput(channelIDContextTLS13))
965 channelIDMsgBytes, err := hs.writeChannelIDMessage(channelIDHash.Sum(nil))
966 if err != nil {
967 return err
968 }
969 hs.writeClientHash(channelIDMsgBytes)
970 c.writeRecord(recordTypeHandshake, channelIDMsgBytes)
971 }
972
Nick Harperb41d2e42016-07-01 17:50:32 -0400973 // Send a client Finished message.
974 finished := new(finishedMsg)
Steven Valdezc4aa7272016-10-03 12:25:56 -0400975 finished.verifyData = hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
Nick Harperb41d2e42016-07-01 17:50:32 -0400976 if c.config.Bugs.BadFinished {
977 finished.verifyData[0]++
978 }
David Benjamin97a0a082016-07-13 17:57:35 -0400979 hs.writeClientHash(finished.marshal())
David Benjamin7964b182016-07-14 23:36:30 -0400980 if c.config.Bugs.PartialClientFinishedWithClientHello {
981 // The first byte has already been sent.
982 c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
Steven Valdeza4ee74d2016-11-29 13:36:45 -0500983 } else if c.config.Bugs.InterleaveEarlyData {
984 finishedBytes := finished.marshal()
985 c.sendFakeEarlyData(4)
986 c.writeRecord(recordTypeHandshake, finishedBytes[:1])
987 c.sendFakeEarlyData(4)
988 c.writeRecord(recordTypeHandshake, finishedBytes[1:])
David Benjamin7964b182016-07-14 23:36:30 -0400989 } else {
990 c.writeRecord(recordTypeHandshake, finished.marshal())
991 }
David Benjamin02edcd02016-07-27 17:40:37 -0400992 if c.config.Bugs.SendExtraFinished {
993 c.writeRecord(recordTypeHandshake, finished.marshal())
994 }
David Benjaminee51a222016-07-07 18:34:12 -0700995 c.flushHandshake()
Nick Harperb41d2e42016-07-01 17:50:32 -0400996
997 // Switch to application data keys.
Steven Valdeza833c352016-11-01 13:39:36 -0400998 c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400999
David Benjamin48891ad2016-12-04 00:02:43 -05001000 c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
Nick Harperb41d2e42016-07-01 17:50:32 -04001001 return nil
1002}
1003
Adam Langley95c29f32014-06-20 12:00:00 -07001004func (hs *clientHandshakeState) doFullHandshake() error {
1005 c := hs.c
1006
David Benjamin48cae082014-10-27 01:06:24 -04001007 var leaf *x509.Certificate
1008 if hs.suite.flags&suitePSK == 0 {
1009 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -07001010 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -07001011 return err
1012 }
Adam Langley95c29f32014-06-20 12:00:00 -07001013
David Benjamin48cae082014-10-27 01:06:24 -04001014 certMsg, ok := msg.(*certificateMsg)
David Benjamin75051442016-07-01 18:58:51 -04001015 if !ok {
David Benjamin48cae082014-10-27 01:06:24 -04001016 c.sendAlert(alertUnexpectedMessage)
1017 return unexpectedMessageError(certMsg, msg)
1018 }
1019 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001020
David Benjamin75051442016-07-01 18:58:51 -04001021 if err := hs.verifyCertificates(certMsg); err != nil {
1022 return err
David Benjamin48cae082014-10-27 01:06:24 -04001023 }
David Benjamin75051442016-07-01 18:58:51 -04001024 leaf = c.peerCertificates[0]
David Benjamin48cae082014-10-27 01:06:24 -04001025 }
Adam Langley95c29f32014-06-20 12:00:00 -07001026
Nick Harperb3d51be2016-07-01 11:43:18 -04001027 if hs.serverHello.extensions.ocspStapling {
David Benjamin48cae082014-10-27 01:06:24 -04001028 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -07001029 if err != nil {
1030 return err
1031 }
1032 cs, ok := msg.(*certificateStatusMsg)
1033 if !ok {
1034 c.sendAlert(alertUnexpectedMessage)
1035 return unexpectedMessageError(cs, msg)
1036 }
David Benjamin83c0bc92014-08-04 01:23:53 -04001037 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001038
1039 if cs.statusType == statusTypeOCSP {
1040 c.ocspResponse = cs.response
1041 }
1042 }
1043
David Benjamin48cae082014-10-27 01:06:24 -04001044 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -07001045 if err != nil {
1046 return err
1047 }
1048
1049 keyAgreement := hs.suite.ka(c.vers)
1050
1051 skx, ok := msg.(*serverKeyExchangeMsg)
1052 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -04001053 hs.writeServerHash(skx.marshal())
David Benjamin48cae082014-10-27 01:06:24 -04001054 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
Adam Langley95c29f32014-06-20 12:00:00 -07001055 if err != nil {
1056 c.sendAlert(alertUnexpectedMessage)
1057 return err
1058 }
Steven Valdez5440fe02016-07-18 12:40:30 -04001059 if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
1060 c.curveID = ecdhe.curveID
1061 }
Adam Langley95c29f32014-06-20 12:00:00 -07001062
Nick Harper60edffd2016-06-21 15:19:24 -07001063 c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()
1064
Adam Langley95c29f32014-06-20 12:00:00 -07001065 msg, err = c.readHandshake()
1066 if err != nil {
1067 return err
1068 }
1069 }
1070
1071 var chainToSend *Certificate
1072 var certRequested bool
1073 certReq, ok := msg.(*certificateRequestMsg)
1074 if ok {
1075 certRequested = true
David Benjamin7a41d372016-07-09 11:21:54 -07001076 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
1077 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
1078 }
Adam Langley95c29f32014-06-20 12:00:00 -07001079
David Benjamin83c0bc92014-08-04 01:23:53 -04001080 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001081
David Benjamina6f82632016-07-01 18:44:02 -04001082 chainToSend, err = selectClientCertificate(c, certReq)
1083 if err != nil {
1084 return err
Adam Langley95c29f32014-06-20 12:00:00 -07001085 }
1086
1087 msg, err = c.readHandshake()
1088 if err != nil {
1089 return err
1090 }
1091 }
1092
1093 shd, ok := msg.(*serverHelloDoneMsg)
1094 if !ok {
1095 c.sendAlert(alertUnexpectedMessage)
1096 return unexpectedMessageError(shd, msg)
1097 }
David Benjamin83c0bc92014-08-04 01:23:53 -04001098 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001099
1100 // If the server requested a certificate then we have to send a
David Benjamin0b7ca7d2016-03-10 15:44:22 -05001101 // Certificate message in TLS, even if it's empty because we don't have
1102 // a certificate to send. In SSL 3.0, skip the message and send a
1103 // no_certificate warning alert.
Adam Langley95c29f32014-06-20 12:00:00 -07001104 if certRequested {
David Benjamin0b7ca7d2016-03-10 15:44:22 -05001105 if c.vers == VersionSSL30 && chainToSend == nil {
David Benjamin053fee92017-01-02 08:30:36 -05001106 c.sendAlert(alertNoCertificate)
David Benjamin0b7ca7d2016-03-10 15:44:22 -05001107 } else if !c.config.Bugs.SkipClientCertificate {
1108 certMsg := new(certificateMsg)
1109 if chainToSend != nil {
Steven Valdeza833c352016-11-01 13:39:36 -04001110 for _, certData := range chainToSend.Certificate {
1111 certMsg.certificates = append(certMsg.certificates, certificateEntry{
1112 data: certData,
1113 })
1114 }
David Benjamin0b7ca7d2016-03-10 15:44:22 -05001115 }
1116 hs.writeClientHash(certMsg.marshal())
1117 c.writeRecord(recordTypeHandshake, certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001118 }
Adam Langley95c29f32014-06-20 12:00:00 -07001119 }
1120
David Benjamin48cae082014-10-27 01:06:24 -04001121 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
Adam Langley95c29f32014-06-20 12:00:00 -07001122 if err != nil {
1123 c.sendAlert(alertInternalError)
1124 return err
1125 }
1126 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -04001127 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -04001128 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -04001129 }
Adam Langley95c29f32014-06-20 12:00:00 -07001130 c.writeRecord(recordTypeHandshake, ckx.marshal())
1131 }
1132
Nick Harperb3d51be2016-07-01 11:43:18 -04001133 if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
Adam Langley75712922014-10-10 16:23:43 -07001134 hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
1135 c.extendedMasterSecret = true
1136 } else {
1137 if c.config.Bugs.RequireExtendedMasterSecret {
1138 return errors.New("tls: extended master secret required but not supported by peer")
1139 }
1140 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
1141 }
David Benjamine098ec22014-08-27 23:13:20 -04001142
Adam Langley95c29f32014-06-20 12:00:00 -07001143 if chainToSend != nil {
Adam Langley95c29f32014-06-20 12:00:00 -07001144 certVerify := &certificateVerifyMsg{
Nick Harper60edffd2016-06-21 15:19:24 -07001145 hasSignatureAlgorithm: c.vers >= VersionTLS12,
Adam Langley95c29f32014-06-20 12:00:00 -07001146 }
1147
David Benjamin72dc7832015-03-16 17:49:43 -04001148 // Determine the hash to sign.
Nick Harper60edffd2016-06-21 15:19:24 -07001149 privKey := c.config.Certificates[0].PrivateKey
David Benjamin72dc7832015-03-16 17:49:43 -04001150
Nick Harper60edffd2016-06-21 15:19:24 -07001151 if certVerify.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -07001152 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
Nick Harper60edffd2016-06-21 15:19:24 -07001153 if err != nil {
1154 c.sendAlert(alertInternalError)
1155 return err
Adam Langley95c29f32014-06-20 12:00:00 -07001156 }
Nick Harper60edffd2016-06-21 15:19:24 -07001157 }
1158
1159 if c.vers > VersionSSL30 {
David Benjamin5208fd42016-07-13 21:43:25 -04001160 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
David Benjamina95e9f32016-07-08 16:28:04 -07001161 if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
1162 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
1163 }
Nick Harper60edffd2016-06-21 15:19:24 -07001164 } else {
1165 // SSL 3.0's client certificate construction is
1166 // incompatible with signatureAlgorithm.
1167 rsaKey, ok := privKey.(*rsa.PrivateKey)
1168 if !ok {
1169 err = errors.New("unsupported signature type for client certificate")
1170 } else {
1171 digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
David Benjamin5208fd42016-07-13 21:43:25 -04001172 if c.config.Bugs.InvalidSignature {
Nick Harper60edffd2016-06-21 15:19:24 -07001173 digest[0] ^= 0x80
1174 }
1175 certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
1176 }
Adam Langley95c29f32014-06-20 12:00:00 -07001177 }
1178 if err != nil {
1179 c.sendAlert(alertInternalError)
1180 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
1181 }
Adam Langley95c29f32014-06-20 12:00:00 -07001182
David Benjamin83c0bc92014-08-04 01:23:53 -04001183 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001184 c.writeRecord(recordTypeHandshake, certVerify.marshal())
1185 }
David Benjamin82261be2016-07-07 14:32:50 -07001186 // flushHandshake will be called in sendFinished.
Adam Langley95c29f32014-06-20 12:00:00 -07001187
David Benjamine098ec22014-08-27 23:13:20 -04001188 hs.finishedHash.discardHandshakeBuffer()
1189
Adam Langley95c29f32014-06-20 12:00:00 -07001190 return nil
1191}
1192
David Benjamin75051442016-07-01 18:58:51 -04001193func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
1194 c := hs.c
1195
1196 if len(certMsg.certificates) == 0 {
1197 c.sendAlert(alertIllegalParameter)
1198 return errors.New("tls: no certificates sent")
1199 }
1200
1201 certs := make([]*x509.Certificate, len(certMsg.certificates))
Steven Valdeza833c352016-11-01 13:39:36 -04001202 for i, certEntry := range certMsg.certificates {
1203 cert, err := x509.ParseCertificate(certEntry.data)
David Benjamin75051442016-07-01 18:58:51 -04001204 if err != nil {
1205 c.sendAlert(alertBadCertificate)
1206 return errors.New("tls: failed to parse certificate from server: " + err.Error())
1207 }
1208 certs[i] = cert
1209 }
1210
1211 if !c.config.InsecureSkipVerify {
1212 opts := x509.VerifyOptions{
1213 Roots: c.config.RootCAs,
1214 CurrentTime: c.config.time(),
1215 DNSName: c.config.ServerName,
1216 Intermediates: x509.NewCertPool(),
1217 }
1218
1219 for i, cert := range certs {
1220 if i == 0 {
1221 continue
1222 }
1223 opts.Intermediates.AddCert(cert)
1224 }
1225 var err error
1226 c.verifiedChains, err = certs[0].Verify(opts)
1227 if err != nil {
1228 c.sendAlert(alertBadCertificate)
1229 return err
1230 }
1231 }
1232
David Benjamind768c5d2017-03-28 18:28:44 -05001233 publicKey := getCertificatePublicKey(certs[0])
1234 switch publicKey.(type) {
1235 case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
David Benjamin75051442016-07-01 18:58:51 -04001236 break
1237 default:
1238 c.sendAlert(alertUnsupportedCertificate)
David Benjamind768c5d2017-03-28 18:28:44 -05001239 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", publicKey)
David Benjamin75051442016-07-01 18:58:51 -04001240 }
1241
1242 c.peerCertificates = certs
1243 return nil
1244}
1245
Adam Langley95c29f32014-06-20 12:00:00 -07001246func (hs *clientHandshakeState) establishKeys() error {
1247 c := hs.c
1248
1249 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
Nick Harper1fd39d82016-06-14 18:14:35 -07001250 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 -07001251 var clientCipher, serverCipher interface{}
1252 var clientHash, serverHash macFunction
1253 if hs.suite.cipher != nil {
1254 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
1255 clientHash = hs.suite.mac(c.vers, clientMAC)
1256 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
1257 serverHash = hs.suite.mac(c.vers, serverMAC)
1258 } else {
Nick Harper1fd39d82016-06-14 18:14:35 -07001259 clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
1260 serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
Adam Langley95c29f32014-06-20 12:00:00 -07001261 }
1262
1263 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
1264 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
1265 return nil
1266}
1267
David Benjamin75101402016-07-01 13:40:23 -04001268func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
1269 c := hs.c
1270
David Benjamin8d315d72016-07-18 01:03:18 +02001271 if c.vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001272 if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
1273 return errors.New("tls: renegotiation extension missing")
1274 }
David Benjamin75101402016-07-01 13:40:23 -04001275
Nick Harperb41d2e42016-07-01 17:50:32 -04001276 if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
1277 var expectedRenegInfo []byte
1278 expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
1279 expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
1280 if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
1281 c.sendAlert(alertHandshakeFailure)
1282 return fmt.Errorf("tls: renegotiation mismatch")
1283 }
David Benjamin75101402016-07-01 13:40:23 -04001284 }
David Benjamincea0ab42016-07-14 12:33:14 -04001285 } else if serverExtensions.secureRenegotiation != nil {
1286 return errors.New("tls: renegotiation info sent in TLS 1.3")
David Benjamin75101402016-07-01 13:40:23 -04001287 }
1288
1289 if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
1290 if serverExtensions.customExtension != *expected {
1291 return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
1292 }
1293 }
1294
1295 clientDidNPN := hs.hello.nextProtoNeg
1296 clientDidALPN := len(hs.hello.alpnProtocols) > 0
1297 serverHasNPN := serverExtensions.nextProtoNeg
1298 serverHasALPN := len(serverExtensions.alpnProtocol) > 0
1299
1300 if !clientDidNPN && serverHasNPN {
1301 c.sendAlert(alertHandshakeFailure)
1302 return errors.New("server advertised unrequested NPN extension")
1303 }
1304
1305 if !clientDidALPN && serverHasALPN {
1306 c.sendAlert(alertHandshakeFailure)
1307 return errors.New("server advertised unrequested ALPN extension")
1308 }
1309
1310 if serverHasNPN && serverHasALPN {
1311 c.sendAlert(alertHandshakeFailure)
1312 return errors.New("server advertised both NPN and ALPN extensions")
1313 }
1314
1315 if serverHasALPN {
1316 c.clientProtocol = serverExtensions.alpnProtocol
1317 c.clientProtocolFallback = false
1318 c.usedALPN = true
1319 }
1320
David Benjamin8d315d72016-07-18 01:03:18 +02001321 if serverHasNPN && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001322 c.sendAlert(alertHandshakeFailure)
1323 return errors.New("server advertised NPN over TLS 1.3")
1324 }
1325
David Benjamin75101402016-07-01 13:40:23 -04001326 if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
1327 c.sendAlert(alertHandshakeFailure)
1328 return errors.New("server advertised unrequested Channel ID extension")
1329 }
1330
David Benjamin8d315d72016-07-18 01:03:18 +02001331 if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
David Benjamine9077652016-07-13 21:02:08 -04001332 return errors.New("tls: server advertised extended master secret over TLS 1.3")
1333 }
1334
David Benjamin8d315d72016-07-18 01:03:18 +02001335 if serverExtensions.ticketSupported && c.vers >= VersionTLS13 {
Steven Valdez143e8b32016-07-11 13:19:03 -04001336 return errors.New("tls: server advertised ticket extension over TLS 1.3")
1337 }
1338
Steven Valdeza833c352016-11-01 13:39:36 -04001339 if serverExtensions.ocspStapling && c.vers >= VersionTLS13 {
1340 return errors.New("tls: server advertised OCSP in ServerHello over TLS 1.3")
1341 }
1342
David Benjamin53210cb2016-11-16 09:01:48 +09001343 if serverExtensions.ocspStapling && c.config.Bugs.NoOCSPStapling {
1344 return errors.New("tls: server advertised unrequested OCSP extension")
1345 }
1346
Steven Valdeza833c352016-11-01 13:39:36 -04001347 if len(serverExtensions.sctList) > 0 && c.vers >= VersionTLS13 {
1348 return errors.New("tls: server advertised SCTs in ServerHello over TLS 1.3")
1349 }
1350
David Benjamin53210cb2016-11-16 09:01:48 +09001351 if len(serverExtensions.sctList) > 0 && c.config.Bugs.NoSignedCertificateTimestamps {
1352 return errors.New("tls: server advertised unrequested SCTs")
1353 }
1354
David Benjamin75101402016-07-01 13:40:23 -04001355 if serverExtensions.srtpProtectionProfile != 0 {
1356 if serverExtensions.srtpMasterKeyIdentifier != "" {
1357 return errors.New("tls: server selected SRTP MKI value")
1358 }
1359
1360 found := false
1361 for _, p := range c.config.SRTPProtectionProfiles {
1362 if p == serverExtensions.srtpProtectionProfile {
1363 found = true
1364 break
1365 }
1366 }
1367 if !found {
1368 return errors.New("tls: server advertised unsupported SRTP profile")
1369 }
1370
1371 c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
1372 }
1373
Steven Valdez2d850622017-01-11 11:34:52 -05001374 if c.vers >= VersionTLS13 && c.didResume {
1375 if c.config.Bugs.ExpectEarlyDataAccepted && !serverExtensions.hasEarlyData {
1376 c.sendAlert(alertHandshakeFailure)
1377 return errors.New("tls: server did not accept early data when expected")
1378 }
1379
1380 if !c.config.Bugs.ExpectEarlyDataAccepted && serverExtensions.hasEarlyData {
1381 c.sendAlert(alertHandshakeFailure)
1382 return errors.New("tls: server accepted early data when not expected")
1383 }
1384 }
1385
David Benjamin75101402016-07-01 13:40:23 -04001386 return nil
1387}
1388
Adam Langley95c29f32014-06-20 12:00:00 -07001389func (hs *clientHandshakeState) serverResumedSession() bool {
1390 // If the server responded with the same sessionId then it means the
1391 // sessionTicket is being used to resume a TLS session.
David Benjamind4c349b2017-02-09 14:07:17 -05001392 //
1393 // Note that, if hs.hello.sessionId is a non-nil empty array, this will
1394 // accept an empty session ID from the server as resumption. See
1395 // EmptyTicketSessionID.
Adam Langley95c29f32014-06-20 12:00:00 -07001396 return hs.session != nil && hs.hello.sessionId != nil &&
1397 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
1398}
1399
1400func (hs *clientHandshakeState) processServerHello() (bool, error) {
1401 c := hs.c
1402
Adam Langley95c29f32014-06-20 12:00:00 -07001403 if hs.serverResumedSession() {
David Benjamin4b27d9f2015-05-12 22:42:52 -04001404 // For test purposes, assert that the server never accepts the
1405 // resumption offer on renegotiation.
1406 if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
1407 return false, errors.New("tls: server resumed session on renegotiation")
1408 }
1409
Nick Harperb3d51be2016-07-01 11:43:18 -04001410 if hs.serverHello.extensions.sctList != nil {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001411 return false, errors.New("tls: server sent SCT extension on session resumption")
1412 }
1413
Nick Harperb3d51be2016-07-01 11:43:18 -04001414 if hs.serverHello.extensions.ocspStapling {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001415 return false, errors.New("tls: server sent OCSP extension on session resumption")
1416 }
1417
Adam Langley95c29f32014-06-20 12:00:00 -07001418 // Restore masterSecret and peerCerts from previous state
1419 hs.masterSecret = hs.session.masterSecret
1420 c.peerCertificates = hs.session.serverCertificates
Adam Langley75712922014-10-10 16:23:43 -07001421 c.extendedMasterSecret = hs.session.extendedMasterSecret
Paul Lietar62be8ac2015-09-16 10:03:30 +01001422 c.sctList = hs.session.sctList
1423 c.ocspResponse = hs.session.ocspResponse
David Benjamine098ec22014-08-27 23:13:20 -04001424 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -07001425 return true, nil
1426 }
Paul Lietar62be8ac2015-09-16 10:03:30 +01001427
Nick Harperb3d51be2016-07-01 11:43:18 -04001428 if hs.serverHello.extensions.sctList != nil {
1429 c.sctList = hs.serverHello.extensions.sctList
Paul Lietar62be8ac2015-09-16 10:03:30 +01001430 }
1431
Adam Langley95c29f32014-06-20 12:00:00 -07001432 return false, nil
1433}
1434
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001435func (hs *clientHandshakeState) readFinished(out []byte) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001436 c := hs.c
1437
1438 c.readRecord(recordTypeChangeCipherSpec)
1439 if err := c.in.error(); err != nil {
1440 return err
1441 }
1442
1443 msg, err := c.readHandshake()
1444 if err != nil {
1445 return err
1446 }
1447 serverFinished, ok := msg.(*finishedMsg)
1448 if !ok {
1449 c.sendAlert(alertUnexpectedMessage)
1450 return unexpectedMessageError(serverFinished, msg)
1451 }
1452
David Benjaminf3ec83d2014-07-21 22:42:34 -04001453 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
1454 verify := hs.finishedHash.serverSum(hs.masterSecret)
1455 if len(verify) != len(serverFinished.verifyData) ||
1456 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
1457 c.sendAlert(alertHandshakeFailure)
1458 return errors.New("tls: server's Finished message was incorrect")
1459 }
Adam Langley95c29f32014-06-20 12:00:00 -07001460 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001461 c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001462 copy(out, serverFinished.verifyData)
David Benjamin83c0bc92014-08-04 01:23:53 -04001463 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001464 return nil
1465}
1466
1467func (hs *clientHandshakeState) readSessionTicket() error {
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001468 c := hs.c
1469
1470 // Create a session with no server identifier. Either a
1471 // session ID or session ticket will be attached.
1472 session := &ClientSessionState{
1473 vers: c.vers,
1474 cipherSuite: hs.suite.id,
1475 masterSecret: hs.masterSecret,
Nick Harperc9846112016-10-17 15:05:35 -07001476 handshakeHash: hs.finishedHash.Sum(),
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001477 serverCertificates: c.peerCertificates,
Paul Lietar62be8ac2015-09-16 10:03:30 +01001478 sctList: c.sctList,
1479 ocspResponse: c.ocspResponse,
Nick Harper0b3625b2016-07-25 16:16:28 -07001480 ticketExpiration: c.config.time().Add(time.Duration(7 * 24 * time.Hour)),
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001481 }
1482
Nick Harperb3d51be2016-07-01 11:43:18 -04001483 if !hs.serverHello.extensions.ticketSupported {
David Benjamind98452d2015-06-16 14:16:23 -04001484 if c.config.Bugs.ExpectNewTicket {
1485 return errors.New("tls: expected new ticket")
1486 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001487 if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
1488 session.sessionId = hs.serverHello.sessionId
1489 hs.session = session
1490 }
Adam Langley95c29f32014-06-20 12:00:00 -07001491 return nil
1492 }
1493
David Benjaminc7ce9772015-10-09 19:32:41 -04001494 if c.vers == VersionSSL30 {
1495 return errors.New("tls: negotiated session tickets in SSL 3.0")
1496 }
1497
Adam Langley95c29f32014-06-20 12:00:00 -07001498 msg, err := c.readHandshake()
1499 if err != nil {
1500 return err
1501 }
1502 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
1503 if !ok {
1504 c.sendAlert(alertUnexpectedMessage)
1505 return unexpectedMessageError(sessionTicketMsg, msg)
1506 }
Adam Langley95c29f32014-06-20 12:00:00 -07001507
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001508 session.sessionTicket = sessionTicketMsg.ticket
1509 hs.session = session
Adam Langley95c29f32014-06-20 12:00:00 -07001510
David Benjamind30a9902014-08-24 01:44:23 -04001511 hs.writeServerHash(sessionTicketMsg.marshal())
1512
Adam Langley95c29f32014-06-20 12:00:00 -07001513 return nil
1514}
1515
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001516func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001517 c := hs.c
1518
David Benjamin0b8d5da2016-07-15 00:39:56 -04001519 var postCCSMsgs [][]byte
David Benjamin83c0bc92014-08-04 01:23:53 -04001520 seqno := hs.c.sendHandshakeSeq
Nick Harperb3d51be2016-07-01 11:43:18 -04001521 if hs.serverHello.extensions.nextProtoNeg {
Adam Langley95c29f32014-06-20 12:00:00 -07001522 nextProto := new(nextProtoMsg)
Nick Harperb3d51be2016-07-01 11:43:18 -04001523 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
Adam Langley95c29f32014-06-20 12:00:00 -07001524 nextProto.proto = proto
1525 c.clientProtocol = proto
1526 c.clientProtocolFallback = fallback
1527
David Benjamin86271ee2014-07-21 16:14:03 -04001528 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -04001529 hs.writeHash(nextProtoBytes, seqno)
1530 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001531 postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
Adam Langley95c29f32014-06-20 12:00:00 -07001532 }
1533
Nick Harperb3d51be2016-07-01 11:43:18 -04001534 if hs.serverHello.extensions.channelIDRequested {
David Benjamind30a9902014-08-24 01:44:23 -04001535 var resumeHash []byte
1536 if isResume {
1537 resumeHash = hs.session.handshakeHash
1538 }
Nick Harper60a85cb2016-09-23 16:25:11 -07001539 channelIDMsgBytes, err := hs.writeChannelIDMessage(hs.finishedHash.hashForChannelID(resumeHash))
David Benjamind30a9902014-08-24 01:44:23 -04001540 if err != nil {
1541 return err
1542 }
David Benjamin24599a82016-06-30 18:56:53 -04001543 hs.writeHash(channelIDMsgBytes, seqno)
David Benjamind30a9902014-08-24 01:44:23 -04001544 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001545 postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
David Benjamind30a9902014-08-24 01:44:23 -04001546 }
1547
Adam Langley95c29f32014-06-20 12:00:00 -07001548 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -04001549 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
1550 finished.verifyData = hs.finishedHash.clientSum(nil)
1551 } else {
1552 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
1553 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001554 copy(out, finished.verifyData)
David Benjamin513f0ea2015-04-02 19:33:31 -04001555 if c.config.Bugs.BadFinished {
1556 finished.verifyData[0]++
1557 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001558 c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
David Benjamin83f90402015-01-27 01:09:43 -05001559 hs.finishedBytes = finished.marshal()
1560 hs.writeHash(hs.finishedBytes, seqno)
David Benjamin0b8d5da2016-07-15 00:39:56 -04001561 postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
David Benjamin86271ee2014-07-21 16:14:03 -04001562
1563 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001564 c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
1565 postCCSMsgs[0] = postCCSMsgs[0][5:]
David Benjamin61672812016-07-14 23:10:43 -04001566 } else if c.config.Bugs.SendUnencryptedFinished {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001567 c.writeRecord(recordTypeHandshake, postCCSMsgs[0])
1568 postCCSMsgs = postCCSMsgs[1:]
David Benjamin86271ee2014-07-21 16:14:03 -04001569 }
David Benjamin582ba042016-07-07 12:33:25 -07001570 c.flushHandshake()
David Benjamin86271ee2014-07-21 16:14:03 -04001571
1572 if !c.config.Bugs.SkipChangeCipherSpec &&
1573 c.config.Bugs.EarlyChangeCipherSpec == 0 {
David Benjamin8411b242015-11-26 12:07:28 -05001574 ccs := []byte{1}
1575 if c.config.Bugs.BadChangeCipherSpec != nil {
1576 ccs = c.config.Bugs.BadChangeCipherSpec
1577 }
1578 c.writeRecord(recordTypeChangeCipherSpec, ccs)
David Benjamin86271ee2014-07-21 16:14:03 -04001579 }
1580
David Benjamin4189bd92015-01-25 23:52:39 -05001581 if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
1582 c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
1583 }
David Benjamindc3da932015-03-12 15:09:02 -04001584 if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
1585 c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
1586 return errors.New("tls: simulating post-CCS alert")
1587 }
David Benjamin4189bd92015-01-25 23:52:39 -05001588
David Benjamin0b8d5da2016-07-15 00:39:56 -04001589 if !c.config.Bugs.SkipFinished {
1590 for _, msg := range postCCSMsgs {
1591 c.writeRecord(recordTypeHandshake, msg)
1592 }
David Benjamin02edcd02016-07-27 17:40:37 -04001593
1594 if c.config.Bugs.SendExtraFinished {
1595 c.writeRecord(recordTypeHandshake, finished.marshal())
1596 }
1597
David Benjamin582ba042016-07-07 12:33:25 -07001598 c.flushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -05001599 }
Adam Langley95c29f32014-06-20 12:00:00 -07001600 return nil
1601}
1602
Nick Harper60a85cb2016-09-23 16:25:11 -07001603func (hs *clientHandshakeState) writeChannelIDMessage(channelIDHash []byte) ([]byte, error) {
1604 c := hs.c
1605 channelIDMsg := new(channelIDMsg)
1606 if c.config.ChannelID.Curve != elliptic.P256() {
1607 return nil, fmt.Errorf("tls: Channel ID is not on P-256.")
1608 }
1609 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, channelIDHash)
1610 if err != nil {
1611 return nil, err
1612 }
1613 channelID := make([]byte, 128)
1614 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
1615 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
1616 writeIntPadded(channelID[64:96], r)
1617 writeIntPadded(channelID[96:128], s)
1618 if c.config.Bugs.InvalidChannelIDSignature {
1619 channelID[64] ^= 1
1620 }
1621 channelIDMsg.channelID = channelID
1622
1623 c.channelID = &c.config.ChannelID.PublicKey
1624
1625 return channelIDMsg.marshal(), nil
1626}
1627
David Benjamin83c0bc92014-08-04 01:23:53 -04001628func (hs *clientHandshakeState) writeClientHash(msg []byte) {
1629 // writeClientHash is called before writeRecord.
1630 hs.writeHash(msg, hs.c.sendHandshakeSeq)
1631}
1632
1633func (hs *clientHandshakeState) writeServerHash(msg []byte) {
1634 // writeServerHash is called after readHandshake.
1635 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
1636}
1637
1638func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
1639 if hs.c.isDTLS {
1640 // This is somewhat hacky. DTLS hashes a slightly different format.
1641 // First, the TLS header.
1642 hs.finishedHash.Write(msg[:4])
1643 // Then the sequence number and reassembled fragment offset (always 0).
1644 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
1645 // Then the reassembled fragment (always equal to the message length).
1646 hs.finishedHash.Write(msg[1:4])
1647 // And then the message body.
1648 hs.finishedHash.Write(msg[4:])
1649 } else {
1650 hs.finishedHash.Write(msg)
1651 }
1652}
1653
David Benjamina6f82632016-07-01 18:44:02 -04001654// selectClientCertificate selects a certificate for use with the given
1655// certificate, or none if none match. It may return a particular certificate or
1656// nil on success, or an error on internal error.
1657func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
1658 // RFC 4346 on the certificateAuthorities field:
1659 // A list of the distinguished names of acceptable certificate
1660 // authorities. These distinguished names may specify a desired
1661 // distinguished name for a root CA or for a subordinate CA; thus, this
1662 // message can be used to describe both known roots and a desired
1663 // authorization space. If the certificate_authorities list is empty
1664 // then the client MAY send any certificate of the appropriate
1665 // ClientCertificateType, unless there is some external arrangement to
1666 // the contrary.
1667
1668 var rsaAvail, ecdsaAvail bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001669 if !certReq.hasRequestContext {
1670 for _, certType := range certReq.certificateTypes {
1671 switch certType {
1672 case CertTypeRSASign:
1673 rsaAvail = true
1674 case CertTypeECDSASign:
1675 ecdsaAvail = true
1676 }
David Benjamina6f82632016-07-01 18:44:02 -04001677 }
1678 }
1679
1680 // We need to search our list of client certs for one
1681 // where SignatureAlgorithm is RSA and the Issuer is in
1682 // certReq.certificateAuthorities
1683findCert:
1684 for i, chain := range c.config.Certificates {
Nick Harperb41d2e42016-07-01 17:50:32 -04001685 if !certReq.hasRequestContext && !rsaAvail && !ecdsaAvail {
David Benjamina6f82632016-07-01 18:44:02 -04001686 continue
1687 }
1688
1689 // Ensure the private key supports one of the advertised
1690 // signature algorithms.
1691 if certReq.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -07001692 if _, err := selectSignatureAlgorithm(c.vers, chain.PrivateKey, c.config, certReq.signatureAlgorithms); err != nil {
David Benjamina6f82632016-07-01 18:44:02 -04001693 continue
1694 }
1695 }
1696
1697 for j, cert := range chain.Certificate {
1698 x509Cert := chain.Leaf
1699 // parse the certificate if this isn't the leaf
1700 // node, or if chain.Leaf was nil
1701 if j != 0 || x509Cert == nil {
1702 var err error
1703 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
1704 c.sendAlert(alertInternalError)
1705 return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
1706 }
1707 }
1708
Nick Harperb41d2e42016-07-01 17:50:32 -04001709 if !certReq.hasRequestContext {
1710 switch {
1711 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
1712 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
David Benjamind768c5d2017-03-28 18:28:44 -05001713 case ecdsaAvail && isEd25519Certificate(x509Cert):
Nick Harperb41d2e42016-07-01 17:50:32 -04001714 default:
1715 continue findCert
1716 }
David Benjamina6f82632016-07-01 18:44:02 -04001717 }
1718
Adam Langley2ff79332017-02-28 13:45:39 -08001719 if expected := c.config.Bugs.ExpectCertificateReqNames; expected != nil {
1720 if !eqByteSlices(expected, certReq.certificateAuthorities) {
1721 return nil, fmt.Errorf("tls: CertificateRequest names differed, got %#v but expected %#v", certReq.certificateAuthorities, expected)
David Benjamina6f82632016-07-01 18:44:02 -04001722 }
1723 }
Adam Langley2ff79332017-02-28 13:45:39 -08001724
1725 return &chain, nil
David Benjamina6f82632016-07-01 18:44:02 -04001726 }
1727 }
1728
1729 return nil, nil
1730}
1731
Adam Langley95c29f32014-06-20 12:00:00 -07001732// clientSessionCacheKey returns a key used to cache sessionTickets that could
1733// be used to resume previously negotiated TLS sessions with a server.
1734func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
1735 if len(config.ServerName) > 0 {
1736 return config.ServerName
1737 }
1738 return serverAddr.String()
1739}
1740
David Benjaminfa055a22014-09-15 16:51:51 -04001741// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
1742// given list of possible protocols and a list of the preference order. The
1743// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -07001744// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -04001745func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
1746 for _, s := range preferenceProtos {
1747 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -07001748 if s == c {
1749 return s, false
1750 }
1751 }
1752 }
1753
David Benjaminfa055a22014-09-15 16:51:51 -04001754 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -07001755}
David Benjamind30a9902014-08-24 01:44:23 -04001756
1757// writeIntPadded writes x into b, padded up with leading zeros as
1758// needed.
1759func writeIntPadded(b []byte, x *big.Int) {
1760 for i := range b {
1761 b[i] = 0
1762 }
1763 xb := x.Bytes()
1764 copy(b[len(b)-len(xb):], xb)
1765}
Steven Valdeza833c352016-11-01 13:39:36 -04001766
1767func generatePSKBinders(hello *clientHelloMsg, pskCipherSuite *cipherSuite, psk, transcript []byte, config *Config) {
1768 if config.Bugs.SendNoPSKBinder {
1769 return
1770 }
1771
1772 binderLen := pskCipherSuite.hash().Size()
1773 if config.Bugs.SendShortPSKBinder {
1774 binderLen--
1775 }
1776
David Benjaminaedf3032016-12-01 16:47:56 -05001777 numBinders := 1
1778 if config.Bugs.SendExtraPSKBinder {
1779 numBinders++
1780 }
1781
Steven Valdeza833c352016-11-01 13:39:36 -04001782 // Fill hello.pskBinders with appropriate length arrays of zeros so the
1783 // length prefixes are correct when computing the binder over the truncated
1784 // ClientHello message.
David Benjaminaedf3032016-12-01 16:47:56 -05001785 hello.pskBinders = make([][]byte, numBinders)
1786 for i := range hello.pskBinders {
Steven Valdeza833c352016-11-01 13:39:36 -04001787 hello.pskBinders[i] = make([]byte, binderLen)
1788 }
1789
1790 helloBytes := hello.marshal()
1791 binderSize := len(hello.pskBinders)*(binderLen+1) + 2
1792 truncatedHello := helloBytes[:len(helloBytes)-binderSize]
1793 binder := computePSKBinder(psk, resumptionPSKBinderLabel, pskCipherSuite, transcript, truncatedHello)
1794 if config.Bugs.SendShortPSKBinder {
1795 binder = binder[:binderLen]
1796 }
1797 if config.Bugs.SendInvalidPSKBinder {
1798 binder[0] ^= 1
1799 }
1800
1801 for i := range hello.pskBinders {
1802 hello.pskBinders[i] = binder
1803 }
1804
1805 hello.raw = nil
1806}