blob: b32be0e8fbd0bd9dc5ce6f121c05842379a9116b [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"
21)
22
23type clientHandshakeState struct {
David Benjamin83f90402015-01-27 01:09:43 -050024 c *Conn
25 serverHello *serverHelloMsg
26 hello *clientHelloMsg
27 suite *cipherSuite
28 finishedHash finishedHash
Nick Harperb41d2e42016-07-01 17:50:32 -040029 keyShares map[CurveID]ecdhCurve
David Benjamin83f90402015-01-27 01:09:43 -050030 masterSecret []byte
31 session *ClientSessionState
32 finishedBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070033}
34
35func (c *Conn) clientHandshake() error {
36 if c.config == nil {
37 c.config = defaultConfig()
38 }
39
40 if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
41 return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
42 }
43
David Benjamin83c0bc92014-08-04 01:23:53 -040044 c.sendHandshakeSeq = 0
45 c.recvHandshakeSeq = 0
46
David Benjaminfa055a22014-09-15 16:51:51 -040047 nextProtosLength := 0
48 for _, proto := range c.config.NextProtos {
Adam Langleyefb0e162015-07-09 11:35:04 -070049 if l := len(proto); l > 255 {
David Benjaminfa055a22014-09-15 16:51:51 -040050 return errors.New("tls: invalid NextProtos value")
51 } else {
52 nextProtosLength += 1 + l
53 }
54 }
55 if nextProtosLength > 0xffff {
56 return errors.New("tls: NextProtos values too large")
57 }
58
Adam Langley95c29f32014-06-20 12:00:00 -070059 hello := &clientHelloMsg{
David Benjaminca6c8262014-11-15 19:06:08 -050060 isDTLS: c.isDTLS,
David Benjamincecee272016-06-30 13:33:47 -040061 vers: c.config.maxVersion(c.isDTLS),
David Benjaminca6c8262014-11-15 19:06:08 -050062 compressionMethods: []uint8{compressionNone},
63 random: make([]byte, 32),
64 ocspStapling: true,
Paul Lietar4fac72e2015-09-09 13:44:55 +010065 sctListSupported: true,
David Benjaminca6c8262014-11-15 19:06:08 -050066 serverName: c.config.ServerName,
67 supportedCurves: c.config.curvePreferences(),
68 supportedPoints: []uint8{pointFormatUncompressed},
69 nextProtoNeg: len(c.config.NextProtos) > 0,
70 secureRenegotiation: []byte{},
71 alpnProtocols: c.config.NextProtos,
72 duplicateExtension: c.config.Bugs.DuplicateExtension,
73 channelIDSupported: c.config.ChannelID != nil,
74 npnLast: c.config.Bugs.SwapNPNAndALPN,
David Benjamincecee272016-06-30 13:33:47 -040075 extendedMasterSecret: c.config.maxVersion(c.isDTLS) >= VersionTLS10,
David Benjaminca6c8262014-11-15 19:06:08 -050076 srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
77 srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
Adam Langley09505632015-07-30 18:10:13 -070078 customExtension: c.config.Bugs.CustomExtension,
Adam Langley95c29f32014-06-20 12:00:00 -070079 }
80
David Benjamin98e882e2014-08-08 13:24:34 -040081 if c.config.Bugs.SendClientVersion != 0 {
82 hello.vers = c.config.Bugs.SendClientVersion
83 }
84
Adam Langley75712922014-10-10 16:23:43 -070085 if c.config.Bugs.NoExtendedMasterSecret {
86 hello.extendedMasterSecret = false
87 }
88
David Benjamin55a43642015-04-20 14:45:55 -040089 if c.config.Bugs.NoSupportedCurves {
90 hello.supportedCurves = nil
91 }
92
Adam Langley2ae77d22014-10-28 17:29:33 -070093 if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
94 if c.config.Bugs.BadRenegotiationInfo {
95 hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
96 hello.secureRenegotiation[0] ^= 0x80
97 } else {
98 hello.secureRenegotiation = c.clientVerify
99 }
100 }
101
David Benjamin3e052de2015-11-25 20:10:31 -0500102 if c.noRenegotiationInfo() {
David Benjaminca6554b2014-11-08 12:31:52 -0500103 hello.secureRenegotiation = nil
104 }
105
Nick Harperb41d2e42016-07-01 17:50:32 -0400106 var keyShares map[CurveID]ecdhCurve
David Benjamin8d315d72016-07-18 01:03:18 +0200107 if hello.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400108 keyShares = make(map[CurveID]ecdhCurve)
Nick Harperdcfbc672016-07-16 17:47:31 +0200109 hello.hasKeyShares = true
110 curvesToSend := c.config.defaultCurves()
Nick Harperb41d2e42016-07-01 17:50:32 -0400111 for _, curveID := range hello.supportedCurves {
Nick Harperdcfbc672016-07-16 17:47:31 +0200112 if !curvesToSend[curveID] {
113 continue
114 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400115 curve, ok := curveForCurveID(curveID)
116 if !ok {
117 continue
118 }
119 publicKey, err := curve.offer(c.config.rand())
120 if err != nil {
121 return err
122 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400123
124 if c.config.Bugs.SendCurve != 0 {
125 curveID = c.config.Bugs.SendCurve
126 }
127 if c.config.Bugs.InvalidECDHPoint {
128 publicKey[0] ^= 0xff
129 }
130
Nick Harperb41d2e42016-07-01 17:50:32 -0400131 hello.keyShares = append(hello.keyShares, keyShareEntry{
132 group: curveID,
133 keyExchange: publicKey,
134 })
135 keyShares[curveID] = curve
Steven Valdez143e8b32016-07-11 13:19:03 -0400136
137 if c.config.Bugs.DuplicateKeyShares {
138 hello.keyShares = append(hello.keyShares, hello.keyShares[len(hello.keyShares)-1])
139 }
140 }
141
142 if c.config.Bugs.MissingKeyShare {
Steven Valdez5440fe02016-07-18 12:40:30 -0400143 hello.hasKeyShares = false
Nick Harperb41d2e42016-07-01 17:50:32 -0400144 }
145 }
146
Adam Langley95c29f32014-06-20 12:00:00 -0700147 possibleCipherSuites := c.config.cipherSuites()
148 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
149
150NextCipherSuite:
151 for _, suiteId := range possibleCipherSuites {
152 for _, suite := range cipherSuites {
153 if suite.id != suiteId {
154 continue
155 }
David Benjamin0407e762016-06-17 16:41:18 -0400156 if !c.config.Bugs.EnableAllCiphers {
157 // Don't advertise TLS 1.2-only cipher suites unless
158 // we're attempting TLS 1.2.
159 if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
160 continue
161 }
162 // Don't advertise non-DTLS cipher suites in DTLS.
163 if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
164 continue
165 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400166 }
Adam Langley95c29f32014-06-20 12:00:00 -0700167 hello.cipherSuites = append(hello.cipherSuites, suiteId)
168 continue NextCipherSuite
169 }
170 }
171
Adam Langley5021b222015-06-12 18:27:58 -0700172 if c.config.Bugs.SendRenegotiationSCSV {
173 hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
174 }
175
David Benjaminbef270a2014-08-02 04:22:02 -0400176 if c.config.Bugs.SendFallbackSCSV {
177 hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
178 }
179
Adam Langley95c29f32014-06-20 12:00:00 -0700180 _, err := io.ReadFull(c.config.rand(), hello.random)
181 if err != nil {
182 c.sendAlert(alertInternalError)
183 return errors.New("tls: short read from Rand: " + err.Error())
184 }
185
Nick Harper60edffd2016-06-21 15:19:24 -0700186 if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAlgorithms {
David Benjamin7a41d372016-07-09 11:21:54 -0700187 hello.signatureAlgorithms = c.config.verifySignatureAlgorithms()
Adam Langley95c29f32014-06-20 12:00:00 -0700188 }
189
190 var session *ClientSessionState
191 var cacheKey string
192 sessionCache := c.config.ClientSessionCache
Adam Langley95c29f32014-06-20 12:00:00 -0700193
194 if sessionCache != nil {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500195 hello.ticketSupported = !c.config.SessionTicketsDisabled
Adam Langley95c29f32014-06-20 12:00:00 -0700196
197 // Try to resume a previously negotiated TLS session, if
198 // available.
199 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
200 candidateSession, ok := sessionCache.Get(cacheKey)
201 if ok {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500202 ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
203
Adam Langley95c29f32014-06-20 12:00:00 -0700204 // Check that the ciphersuite/version used for the
205 // previous session are still valid.
206 cipherSuiteOk := false
207 for _, id := range hello.cipherSuites {
208 if id == candidateSession.cipherSuite {
209 cipherSuiteOk = true
210 break
211 }
212 }
213
David Benjamincecee272016-06-30 13:33:47 -0400214 versOk := candidateSession.vers >= c.config.minVersion(c.isDTLS) &&
215 candidateSession.vers <= c.config.maxVersion(c.isDTLS)
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500216 if ticketOk && versOk && cipherSuiteOk {
Adam Langley95c29f32014-06-20 12:00:00 -0700217 session = candidateSession
218 }
219 }
220 }
221
222 if session != nil {
David Benjamind5a4ecb2016-07-18 01:17:13 +0200223 ticket := session.sessionTicket
224 if c.config.Bugs.CorruptTicket && len(ticket) > 0 {
225 ticket = make([]byte, len(session.sessionTicket))
226 copy(ticket, session.sessionTicket)
227 offset := 40
228 if offset >= len(ticket) {
229 offset = len(ticket) - 1
Adam Langley38311732014-10-16 19:04:35 -0700230 }
David Benjamind5a4ecb2016-07-18 01:17:13 +0200231 ticket[offset] ^= 0x40
232 }
233
234 if session.vers >= VersionTLS13 {
235 // TODO(davidben): Offer TLS 1.3 tickets.
236 } else if ticket != nil {
237 hello.sessionTicket = ticket
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500238 // A random session ID is used to detect when the
239 // server accepted the ticket and is resuming a session
240 // (see RFC 5077).
241 sessionIdLen := 16
242 if c.config.Bugs.OversizedSessionId {
243 sessionIdLen = 33
244 }
245 hello.sessionId = make([]byte, sessionIdLen)
246 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
247 c.sendAlert(alertInternalError)
248 return errors.New("tls: short read from Rand: " + err.Error())
249 }
250 } else {
251 hello.sessionId = session.sessionId
Adam Langley95c29f32014-06-20 12:00:00 -0700252 }
253 }
254
David Benjamind86c7672014-08-02 04:07:12 -0400255 var helloBytes []byte
256 if c.config.Bugs.SendV2ClientHello {
David Benjamin94d701b2014-11-30 13:54:41 -0500257 // Test that the peer left-pads random.
258 hello.random[0] = 0
David Benjamind86c7672014-08-02 04:07:12 -0400259 v2Hello := &v2ClientHelloMsg{
260 vers: hello.vers,
261 cipherSuites: hello.cipherSuites,
262 // No session resumption for V2ClientHello.
263 sessionId: nil,
David Benjamin94d701b2014-11-30 13:54:41 -0500264 challenge: hello.random[1:],
David Benjamind86c7672014-08-02 04:07:12 -0400265 }
266 helloBytes = v2Hello.marshal()
267 c.writeV2Record(helloBytes)
268 } else {
269 helloBytes = hello.marshal()
David Benjamin7964b182016-07-14 23:36:30 -0400270 if c.config.Bugs.PartialClientFinishedWithClientHello {
271 // Include one byte of Finished. We can compute it
272 // without completing the handshake. This assumes we
273 // negotiate TLS 1.3 with no HelloRetryRequest or
274 // CertificateRequest.
275 toWrite := make([]byte, 0, len(helloBytes)+1)
276 toWrite = append(toWrite, helloBytes...)
277 toWrite = append(toWrite, typeFinished)
278 c.writeRecord(recordTypeHandshake, toWrite)
279 } else {
280 c.writeRecord(recordTypeHandshake, helloBytes)
281 }
David Benjamind86c7672014-08-02 04:07:12 -0400282 }
David Benjamin582ba042016-07-07 12:33:25 -0700283 c.flushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700284
David Benjamin83f90402015-01-27 01:09:43 -0500285 if err := c.simulatePacketLoss(nil); err != nil {
286 return err
287 }
Adam Langley95c29f32014-06-20 12:00:00 -0700288 msg, err := c.readHandshake()
289 if err != nil {
290 return err
291 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400292
293 if c.isDTLS {
294 helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
295 if ok {
David Benjamin8bc38f52014-08-16 12:07:27 -0400296 if helloVerifyRequest.vers != VersionTLS10 {
297 // Per RFC 6347, the version field in
298 // HelloVerifyRequest SHOULD be always DTLS
299 // 1.0. Enforce this for testing purposes.
300 return errors.New("dtls: bad HelloVerifyRequest version")
301 }
302
David Benjamin83c0bc92014-08-04 01:23:53 -0400303 hello.raw = nil
304 hello.cookie = helloVerifyRequest.cookie
305 helloBytes = hello.marshal()
306 c.writeRecord(recordTypeHandshake, helloBytes)
David Benjamin582ba042016-07-07 12:33:25 -0700307 c.flushHandshake()
David Benjamin83c0bc92014-08-04 01:23:53 -0400308
David Benjamin83f90402015-01-27 01:09:43 -0500309 if err := c.simulatePacketLoss(nil); err != nil {
310 return err
311 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400312 msg, err = c.readHandshake()
313 if err != nil {
314 return err
315 }
316 }
317 }
318
Nick Harperdcfbc672016-07-16 17:47:31 +0200319 var serverVersion uint16
320 switch m := msg.(type) {
321 case *helloRetryRequestMsg:
322 serverVersion = m.vers
323 case *serverHelloMsg:
324 serverVersion = m.vers
325 default:
326 c.sendAlert(alertUnexpectedMessage)
327 return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg)
328 }
329
330 var ok bool
331 c.vers, ok = c.config.mutualVersion(serverVersion, c.isDTLS)
332 if !ok {
333 c.sendAlert(alertProtocolVersion)
334 return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers)
335 }
336 c.haveVers = true
337
338 helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
339 var secondHelloBytes []byte
340 if haveHelloRetryRequest {
341 var hrrCurveFound bool
Steven Valdez5440fe02016-07-18 12:40:30 -0400342 if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
343 helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
344 }
Nick Harperdcfbc672016-07-16 17:47:31 +0200345 group := helloRetryRequest.selectedGroup
346 for _, curveID := range hello.supportedCurves {
347 if group == curveID {
348 hrrCurveFound = true
349 break
350 }
351 }
352 if !hrrCurveFound || keyShares[group] != nil {
353 c.sendAlert(alertHandshakeFailure)
354 return errors.New("tls: received invalid HelloRetryRequest")
355 }
356 curve, ok := curveForCurveID(group)
357 if !ok {
358 return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
359 }
360 publicKey, err := curve.offer(c.config.rand())
361 if err != nil {
362 return err
363 }
364 keyShares[group] = curve
365 hello.keyShares = append(hello.keyShares, keyShareEntry{
366 group: group,
367 keyExchange: publicKey,
368 })
369
Steven Valdez5440fe02016-07-18 12:40:30 -0400370 if c.config.Bugs.SecondClientHelloMissingKeyShare {
371 hello.hasKeyShares = false
372 }
373
Nick Harperdcfbc672016-07-16 17:47:31 +0200374 hello.hasEarlyData = false
375 hello.earlyDataContext = nil
376 hello.raw = nil
377
378 secondHelloBytes = hello.marshal()
379 c.writeRecord(recordTypeHandshake, secondHelloBytes)
380 c.flushHandshake()
381
382 msg, err = c.readHandshake()
383 if err != nil {
384 return err
385 }
386 }
387
Adam Langley95c29f32014-06-20 12:00:00 -0700388 serverHello, ok := msg.(*serverHelloMsg)
389 if !ok {
390 c.sendAlert(alertUnexpectedMessage)
391 return unexpectedMessageError(serverHello, msg)
392 }
393
Nick Harperdcfbc672016-07-16 17:47:31 +0200394 if c.vers != serverHello.vers {
Adam Langley95c29f32014-06-20 12:00:00 -0700395 c.sendAlert(alertProtocolVersion)
Nick Harperdcfbc672016-07-16 17:47:31 +0200396 return fmt.Errorf("tls: server sent non-matching version %x vs %x", serverHello.vers, c.vers)
Adam Langley95c29f32014-06-20 12:00:00 -0700397 }
Adam Langley95c29f32014-06-20 12:00:00 -0700398
Nick Harper85f20c22016-07-04 10:11:59 -0700399 // Check for downgrade signals in the server random, per
David Benjamin1f61f0d2016-07-10 12:20:35 -0400400 // draft-ietf-tls-tls13-14, section 6.3.1.2.
Nick Harper85f20c22016-07-04 10:11:59 -0700401 if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400402 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS13) {
Nick Harper85f20c22016-07-04 10:11:59 -0700403 c.sendAlert(alertProtocolVersion)
404 return errors.New("tls: downgrade from TLS 1.3 detected")
405 }
406 }
407 if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400408 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS12) {
Nick Harper85f20c22016-07-04 10:11:59 -0700409 c.sendAlert(alertProtocolVersion)
410 return errors.New("tls: downgrade from TLS 1.2 detected")
411 }
412 }
413
Adam Langley95c29f32014-06-20 12:00:00 -0700414 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
415 if suite == nil {
416 c.sendAlert(alertHandshakeFailure)
417 return fmt.Errorf("tls: server selected an unsupported cipher suite")
418 }
419
Nick Harperdcfbc672016-07-16 17:47:31 +0200420 if haveHelloRetryRequest && (helloRetryRequest.cipherSuite != serverHello.cipherSuite || helloRetryRequest.selectedGroup != serverHello.keyShare.group) {
421 c.sendAlert(alertHandshakeFailure)
422 return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
423 }
424
Adam Langley95c29f32014-06-20 12:00:00 -0700425 hs := &clientHandshakeState{
426 c: c,
427 serverHello: serverHello,
428 hello: hello,
429 suite: suite,
430 finishedHash: newFinishedHash(c.vers, suite),
Nick Harperb41d2e42016-07-01 17:50:32 -0400431 keyShares: keyShares,
Adam Langley95c29f32014-06-20 12:00:00 -0700432 session: session,
433 }
434
David Benjamin83c0bc92014-08-04 01:23:53 -0400435 hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
Nick Harperdcfbc672016-07-16 17:47:31 +0200436 if haveHelloRetryRequest {
437 hs.writeServerHash(helloRetryRequest.marshal())
438 hs.writeClientHash(secondHelloBytes)
439 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400440 hs.writeServerHash(hs.serverHello.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700441
David Benjamin8d315d72016-07-18 01:03:18 +0200442 if c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400443 if err := hs.doTLS13Handshake(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700444 return err
445 }
446 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400447 if c.config.Bugs.EarlyChangeCipherSpec > 0 {
448 hs.establishKeys()
449 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
450 }
451
452 if hs.serverHello.compressionMethod != compressionNone {
453 c.sendAlert(alertUnexpectedMessage)
454 return errors.New("tls: server selected unsupported compression format")
455 }
456
457 err = hs.processServerExtensions(&serverHello.extensions)
458 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700459 return err
460 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400461
462 isResume, err := hs.processServerHello()
463 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700464 return err
465 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400466
467 if isResume {
468 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
469 if err := hs.establishKeys(); err != nil {
470 return err
471 }
472 }
473 if err := hs.readSessionTicket(); err != nil {
474 return err
475 }
476 if err := hs.readFinished(c.firstFinished[:]); err != nil {
477 return err
478 }
479 if err := hs.sendFinished(nil, isResume); err != nil {
480 return err
481 }
482 } else {
483 if err := hs.doFullHandshake(); err != nil {
484 return err
485 }
486 if err := hs.establishKeys(); err != nil {
487 return err
488 }
489 if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
490 return err
491 }
492 // Most retransmits are triggered by a timeout, but the final
493 // leg of the handshake is retransmited upon re-receiving a
494 // Finished.
495 if err := c.simulatePacketLoss(func() {
496 c.writeRecord(recordTypeHandshake, hs.finishedBytes)
497 c.flushHandshake()
498 }); err != nil {
499 return err
500 }
501 if err := hs.readSessionTicket(); err != nil {
502 return err
503 }
504 if err := hs.readFinished(nil); err != nil {
505 return err
506 }
Adam Langley95c29f32014-06-20 12:00:00 -0700507 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400508
509 if sessionCache != nil && hs.session != nil && session != hs.session {
510 if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
511 return errors.New("tls: new session used session IDs instead of tickets")
512 }
513 sessionCache.Put(cacheKey, hs.session)
David Benjamin83f90402015-01-27 01:09:43 -0500514 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400515
516 c.didResume = isResume
David Benjamin97a0a082016-07-13 17:57:35 -0400517 c.exporterSecret = hs.masterSecret
Adam Langley95c29f32014-06-20 12:00:00 -0700518 }
519
Adam Langley95c29f32014-06-20 12:00:00 -0700520 c.handshakeComplete = true
David Benjaminc565ebb2015-04-03 04:06:36 -0400521 c.cipherSuite = suite
522 copy(c.clientRandom[:], hs.hello.random)
523 copy(c.serverRandom[:], hs.serverHello.random)
Paul Lietar4fac72e2015-09-09 13:44:55 +0100524
Adam Langley95c29f32014-06-20 12:00:00 -0700525 return nil
526}
527
Nick Harperb41d2e42016-07-01 17:50:32 -0400528func (hs *clientHandshakeState) doTLS13Handshake() error {
529 c := hs.c
530
531 // Once the PRF hash is known, TLS 1.3 does not require a handshake
532 // buffer.
533 hs.finishedHash.discardHandshakeBuffer()
534
535 zeroSecret := hs.finishedHash.zeroSecret()
536
537 // Resolve PSK and compute the early secret.
538 //
539 // TODO(davidben): This will need to be handled slightly earlier once
540 // 0-RTT is implemented.
541 var psk []byte
542 if hs.suite.flags&suitePSK != 0 {
543 if !hs.serverHello.hasPSKIdentity {
544 c.sendAlert(alertMissingExtension)
545 return errors.New("tls: server omitted the PSK identity extension")
546 }
547
548 // TODO(davidben): Support PSK ciphers and PSK resumption. Set
549 // the resumption context appropriately if resuming.
550 return errors.New("tls: PSK ciphers not implemented for TLS 1.3")
551 } else {
552 if hs.serverHello.hasPSKIdentity {
553 c.sendAlert(alertUnsupportedExtension)
554 return errors.New("tls: server sent unexpected PSK identity")
555 }
556
557 psk = zeroSecret
558 hs.finishedHash.setResumptionContext(zeroSecret)
559 }
560
561 earlySecret := hs.finishedHash.extractKey(zeroSecret, psk)
562
563 // Resolve ECDHE and compute the handshake secret.
564 var ecdheSecret []byte
Steven Valdez5440fe02016-07-18 12:40:30 -0400565 if hs.suite.flags&suiteECDHE != 0 && !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
Nick Harperb41d2e42016-07-01 17:50:32 -0400566 if !hs.serverHello.hasKeyShare {
567 c.sendAlert(alertMissingExtension)
568 return errors.New("tls: server omitted the key share extension")
569 }
570
571 curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
572 if !ok {
573 c.sendAlert(alertHandshakeFailure)
574 return errors.New("tls: server selected an unsupported group")
575 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400576 c.curveID = hs.serverHello.keyShare.group
Nick Harperb41d2e42016-07-01 17:50:32 -0400577
578 var err error
579 ecdheSecret, err = curve.finish(hs.serverHello.keyShare.keyExchange)
580 if err != nil {
581 return err
582 }
583 } else {
584 if hs.serverHello.hasKeyShare {
585 c.sendAlert(alertUnsupportedExtension)
586 return errors.New("tls: server sent unexpected key share extension")
587 }
588
589 ecdheSecret = zeroSecret
590 }
591
592 // Compute the handshake secret.
593 handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
594
595 // Switch to handshake traffic keys.
596 handshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, handshakeTrafficLabel)
David Benjamin21c00282016-07-18 21:56:23 +0200597 c.out.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, clientWrite)
598 c.in.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, serverWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400599
600 msg, err := c.readHandshake()
601 if err != nil {
602 return err
603 }
604
605 encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
606 if !ok {
607 c.sendAlert(alertUnexpectedMessage)
608 return unexpectedMessageError(encryptedExtensions, msg)
609 }
610 hs.writeServerHash(encryptedExtensions.marshal())
611
612 err = hs.processServerExtensions(&encryptedExtensions.extensions)
613 if err != nil {
614 return err
615 }
616
617 var chainToSend *Certificate
David Benjamin8d343b42016-07-09 14:26:01 -0700618 var certReq *certificateRequestMsg
David Benjamin44b33bc2016-07-01 22:40:23 -0400619 if hs.suite.flags&suitePSK != 0 {
620 if encryptedExtensions.extensions.ocspResponse != nil {
621 c.sendAlert(alertUnsupportedExtension)
622 return errors.New("tls: server sent OCSP response without a certificate")
623 }
624 if encryptedExtensions.extensions.sctList != nil {
625 c.sendAlert(alertUnsupportedExtension)
626 return errors.New("tls: server sent SCT list without a certificate")
627 }
628 } else {
629 c.ocspResponse = encryptedExtensions.extensions.ocspResponse
630 c.sctList = encryptedExtensions.extensions.sctList
Nick Harperb41d2e42016-07-01 17:50:32 -0400631
632 msg, err := c.readHandshake()
633 if err != nil {
634 return err
635 }
636
David Benjamin8d343b42016-07-09 14:26:01 -0700637 var ok bool
638 certReq, ok = msg.(*certificateRequestMsg)
Nick Harperb41d2e42016-07-01 17:50:32 -0400639 if ok {
David Benjaminb62d2872016-07-18 14:55:02 +0200640 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
641 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
642 }
643
Nick Harperb41d2e42016-07-01 17:50:32 -0400644 hs.writeServerHash(certReq.marshal())
Nick Harperb41d2e42016-07-01 17:50:32 -0400645
646 chainToSend, err = selectClientCertificate(c, certReq)
647 if err != nil {
648 return err
649 }
650
651 msg, err = c.readHandshake()
652 if err != nil {
653 return err
654 }
655 }
656
657 certMsg, ok := msg.(*certificateMsg)
658 if !ok {
659 c.sendAlert(alertUnexpectedMessage)
660 return unexpectedMessageError(certMsg, msg)
661 }
662 hs.writeServerHash(certMsg.marshal())
663
664 if err := hs.verifyCertificates(certMsg); err != nil {
665 return err
666 }
667 leaf := c.peerCertificates[0]
668
669 msg, err = c.readHandshake()
670 if err != nil {
671 return err
672 }
673 certVerifyMsg, ok := msg.(*certificateVerifyMsg)
674 if !ok {
675 c.sendAlert(alertUnexpectedMessage)
676 return unexpectedMessageError(certVerifyMsg, msg)
677 }
678
David Benjaminf74ec792016-07-13 21:18:49 -0400679 c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
Nick Harperb41d2e42016-07-01 17:50:32 -0400680 input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
David Benjamin1fb125c2016-07-08 18:52:12 -0700681 err = verifyMessage(c.vers, leaf.PublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
Nick Harperb41d2e42016-07-01 17:50:32 -0400682 if err != nil {
683 return err
684 }
685
686 hs.writeServerHash(certVerifyMsg.marshal())
687 }
688
689 msg, err = c.readHandshake()
690 if err != nil {
691 return err
692 }
693 serverFinished, ok := msg.(*finishedMsg)
694 if !ok {
695 c.sendAlert(alertUnexpectedMessage)
696 return unexpectedMessageError(serverFinished, msg)
697 }
698
699 verify := hs.finishedHash.serverSum(handshakeTrafficSecret)
700 if len(verify) != len(serverFinished.verifyData) ||
701 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
702 c.sendAlert(alertHandshakeFailure)
703 return errors.New("tls: server's Finished message was incorrect")
704 }
705
706 hs.writeServerHash(serverFinished.marshal())
707
708 // The various secrets do not incorporate the client's final leg, so
709 // derive them now before updating the handshake context.
710 masterSecret := hs.finishedHash.extractKey(handshakeSecret, zeroSecret)
711 trafficSecret := hs.finishedHash.deriveSecret(masterSecret, applicationTrafficLabel)
712
Steven Valdez0ee2e112016-07-15 06:51:15 -0400713 if certReq != nil && !c.config.Bugs.SkipClientCertificate {
David Benjamin8d343b42016-07-09 14:26:01 -0700714 certMsg := &certificateMsg{
715 hasRequestContext: true,
716 requestContext: certReq.requestContext,
717 }
718 if chainToSend != nil {
719 certMsg.certificates = chainToSend.Certificate
720 }
721 hs.writeClientHash(certMsg.marshal())
722 c.writeRecord(recordTypeHandshake, certMsg.marshal())
723
724 if chainToSend != nil {
725 certVerify := &certificateVerifyMsg{
726 hasSignatureAlgorithm: true,
727 }
728
729 // Determine the hash to sign.
730 privKey := chainToSend.PrivateKey
731
732 var err error
733 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
734 if err != nil {
735 c.sendAlert(alertInternalError)
736 return err
737 }
738
739 input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
740 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
741 if err != nil {
742 c.sendAlert(alertInternalError)
743 return err
744 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400745 if c.config.Bugs.SendSignatureAlgorithm != 0 {
746 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
747 }
David Benjamin8d343b42016-07-09 14:26:01 -0700748
749 hs.writeClientHash(certVerify.marshal())
750 c.writeRecord(recordTypeHandshake, certVerify.marshal())
751 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400752 }
753
754 // Send a client Finished message.
755 finished := new(finishedMsg)
756 finished.verifyData = hs.finishedHash.clientSum(handshakeTrafficSecret)
757 if c.config.Bugs.BadFinished {
758 finished.verifyData[0]++
759 }
David Benjamin97a0a082016-07-13 17:57:35 -0400760 hs.writeClientHash(finished.marshal())
David Benjamin7964b182016-07-14 23:36:30 -0400761 if c.config.Bugs.PartialClientFinishedWithClientHello {
762 // The first byte has already been sent.
763 c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
764 } else {
765 c.writeRecord(recordTypeHandshake, finished.marshal())
766 }
David Benjaminee51a222016-07-07 18:34:12 -0700767 c.flushHandshake()
Nick Harperb41d2e42016-07-01 17:50:32 -0400768
769 // Switch to application data keys.
David Benjamin21c00282016-07-18 21:56:23 +0200770 c.out.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, clientWrite)
771 c.in.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, serverWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400772
David Benjamin97a0a082016-07-13 17:57:35 -0400773 c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
David Benjamind5a4ecb2016-07-18 01:17:13 +0200774 c.resumptionSecret = hs.finishedHash.deriveSecret(masterSecret, resumptionLabel)
Nick Harperb41d2e42016-07-01 17:50:32 -0400775 return nil
776}
777
Adam Langley95c29f32014-06-20 12:00:00 -0700778func (hs *clientHandshakeState) doFullHandshake() error {
779 c := hs.c
780
David Benjamin48cae082014-10-27 01:06:24 -0400781 var leaf *x509.Certificate
782 if hs.suite.flags&suitePSK == 0 {
783 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700784 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700785 return err
786 }
Adam Langley95c29f32014-06-20 12:00:00 -0700787
David Benjamin48cae082014-10-27 01:06:24 -0400788 certMsg, ok := msg.(*certificateMsg)
David Benjamin75051442016-07-01 18:58:51 -0400789 if !ok {
David Benjamin48cae082014-10-27 01:06:24 -0400790 c.sendAlert(alertUnexpectedMessage)
791 return unexpectedMessageError(certMsg, msg)
792 }
793 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700794
David Benjamin75051442016-07-01 18:58:51 -0400795 if err := hs.verifyCertificates(certMsg); err != nil {
796 return err
David Benjamin48cae082014-10-27 01:06:24 -0400797 }
David Benjamin75051442016-07-01 18:58:51 -0400798 leaf = c.peerCertificates[0]
David Benjamin48cae082014-10-27 01:06:24 -0400799 }
Adam Langley95c29f32014-06-20 12:00:00 -0700800
Nick Harperb3d51be2016-07-01 11:43:18 -0400801 if hs.serverHello.extensions.ocspStapling {
David Benjamin48cae082014-10-27 01:06:24 -0400802 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700803 if err != nil {
804 return err
805 }
806 cs, ok := msg.(*certificateStatusMsg)
807 if !ok {
808 c.sendAlert(alertUnexpectedMessage)
809 return unexpectedMessageError(cs, msg)
810 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400811 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700812
813 if cs.statusType == statusTypeOCSP {
814 c.ocspResponse = cs.response
815 }
816 }
817
David Benjamin48cae082014-10-27 01:06:24 -0400818 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700819 if err != nil {
820 return err
821 }
822
823 keyAgreement := hs.suite.ka(c.vers)
824
825 skx, ok := msg.(*serverKeyExchangeMsg)
826 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -0400827 hs.writeServerHash(skx.marshal())
David Benjamin48cae082014-10-27 01:06:24 -0400828 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
Adam Langley95c29f32014-06-20 12:00:00 -0700829 if err != nil {
830 c.sendAlert(alertUnexpectedMessage)
831 return err
832 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400833 if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
834 c.curveID = ecdhe.curveID
835 }
Adam Langley95c29f32014-06-20 12:00:00 -0700836
Nick Harper60edffd2016-06-21 15:19:24 -0700837 c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()
838
Adam Langley95c29f32014-06-20 12:00:00 -0700839 msg, err = c.readHandshake()
840 if err != nil {
841 return err
842 }
843 }
844
845 var chainToSend *Certificate
846 var certRequested bool
847 certReq, ok := msg.(*certificateRequestMsg)
848 if ok {
849 certRequested = true
David Benjamin7a41d372016-07-09 11:21:54 -0700850 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
851 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
852 }
Adam Langley95c29f32014-06-20 12:00:00 -0700853
David Benjamin83c0bc92014-08-04 01:23:53 -0400854 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700855
David Benjamina6f82632016-07-01 18:44:02 -0400856 chainToSend, err = selectClientCertificate(c, certReq)
857 if err != nil {
858 return err
Adam Langley95c29f32014-06-20 12:00:00 -0700859 }
860
861 msg, err = c.readHandshake()
862 if err != nil {
863 return err
864 }
865 }
866
867 shd, ok := msg.(*serverHelloDoneMsg)
868 if !ok {
869 c.sendAlert(alertUnexpectedMessage)
870 return unexpectedMessageError(shd, msg)
871 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400872 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700873
874 // If the server requested a certificate then we have to send a
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500875 // Certificate message in TLS, even if it's empty because we don't have
876 // a certificate to send. In SSL 3.0, skip the message and send a
877 // no_certificate warning alert.
Adam Langley95c29f32014-06-20 12:00:00 -0700878 if certRequested {
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500879 if c.vers == VersionSSL30 && chainToSend == nil {
880 c.sendAlert(alertNoCertficate)
881 } else if !c.config.Bugs.SkipClientCertificate {
882 certMsg := new(certificateMsg)
883 if chainToSend != nil {
884 certMsg.certificates = chainToSend.Certificate
885 }
886 hs.writeClientHash(certMsg.marshal())
887 c.writeRecord(recordTypeHandshake, certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700888 }
Adam Langley95c29f32014-06-20 12:00:00 -0700889 }
890
David Benjamin48cae082014-10-27 01:06:24 -0400891 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
Adam Langley95c29f32014-06-20 12:00:00 -0700892 if err != nil {
893 c.sendAlert(alertInternalError)
894 return err
895 }
896 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400897 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -0400898 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -0400899 }
Adam Langley95c29f32014-06-20 12:00:00 -0700900 c.writeRecord(recordTypeHandshake, ckx.marshal())
901 }
902
Nick Harperb3d51be2016-07-01 11:43:18 -0400903 if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
Adam Langley75712922014-10-10 16:23:43 -0700904 hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
905 c.extendedMasterSecret = true
906 } else {
907 if c.config.Bugs.RequireExtendedMasterSecret {
908 return errors.New("tls: extended master secret required but not supported by peer")
909 }
910 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
911 }
David Benjamine098ec22014-08-27 23:13:20 -0400912
Adam Langley95c29f32014-06-20 12:00:00 -0700913 if chainToSend != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700914 certVerify := &certificateVerifyMsg{
Nick Harper60edffd2016-06-21 15:19:24 -0700915 hasSignatureAlgorithm: c.vers >= VersionTLS12,
Adam Langley95c29f32014-06-20 12:00:00 -0700916 }
917
David Benjamin72dc7832015-03-16 17:49:43 -0400918 // Determine the hash to sign.
Nick Harper60edffd2016-06-21 15:19:24 -0700919 privKey := c.config.Certificates[0].PrivateKey
David Benjamin72dc7832015-03-16 17:49:43 -0400920
Nick Harper60edffd2016-06-21 15:19:24 -0700921 if certVerify.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -0700922 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
Nick Harper60edffd2016-06-21 15:19:24 -0700923 if err != nil {
924 c.sendAlert(alertInternalError)
925 return err
Adam Langley95c29f32014-06-20 12:00:00 -0700926 }
Nick Harper60edffd2016-06-21 15:19:24 -0700927 }
928
929 if c.vers > VersionSSL30 {
David Benjamin5208fd42016-07-13 21:43:25 -0400930 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
David Benjamina95e9f32016-07-08 16:28:04 -0700931 if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
932 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
933 }
Nick Harper60edffd2016-06-21 15:19:24 -0700934 } else {
935 // SSL 3.0's client certificate construction is
936 // incompatible with signatureAlgorithm.
937 rsaKey, ok := privKey.(*rsa.PrivateKey)
938 if !ok {
939 err = errors.New("unsupported signature type for client certificate")
940 } else {
941 digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
David Benjamin5208fd42016-07-13 21:43:25 -0400942 if c.config.Bugs.InvalidSignature {
Nick Harper60edffd2016-06-21 15:19:24 -0700943 digest[0] ^= 0x80
944 }
945 certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
946 }
Adam Langley95c29f32014-06-20 12:00:00 -0700947 }
948 if err != nil {
949 c.sendAlert(alertInternalError)
950 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
951 }
Adam Langley95c29f32014-06-20 12:00:00 -0700952
David Benjamin83c0bc92014-08-04 01:23:53 -0400953 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700954 c.writeRecord(recordTypeHandshake, certVerify.marshal())
955 }
David Benjamin82261be2016-07-07 14:32:50 -0700956 // flushHandshake will be called in sendFinished.
Adam Langley95c29f32014-06-20 12:00:00 -0700957
David Benjamine098ec22014-08-27 23:13:20 -0400958 hs.finishedHash.discardHandshakeBuffer()
959
Adam Langley95c29f32014-06-20 12:00:00 -0700960 return nil
961}
962
David Benjamin75051442016-07-01 18:58:51 -0400963func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
964 c := hs.c
965
966 if len(certMsg.certificates) == 0 {
967 c.sendAlert(alertIllegalParameter)
968 return errors.New("tls: no certificates sent")
969 }
970
971 certs := make([]*x509.Certificate, len(certMsg.certificates))
972 for i, asn1Data := range certMsg.certificates {
973 cert, err := x509.ParseCertificate(asn1Data)
974 if err != nil {
975 c.sendAlert(alertBadCertificate)
976 return errors.New("tls: failed to parse certificate from server: " + err.Error())
977 }
978 certs[i] = cert
979 }
980
981 if !c.config.InsecureSkipVerify {
982 opts := x509.VerifyOptions{
983 Roots: c.config.RootCAs,
984 CurrentTime: c.config.time(),
985 DNSName: c.config.ServerName,
986 Intermediates: x509.NewCertPool(),
987 }
988
989 for i, cert := range certs {
990 if i == 0 {
991 continue
992 }
993 opts.Intermediates.AddCert(cert)
994 }
995 var err error
996 c.verifiedChains, err = certs[0].Verify(opts)
997 if err != nil {
998 c.sendAlert(alertBadCertificate)
999 return err
1000 }
1001 }
1002
1003 switch certs[0].PublicKey.(type) {
1004 case *rsa.PublicKey, *ecdsa.PublicKey:
1005 break
1006 default:
1007 c.sendAlert(alertUnsupportedCertificate)
1008 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
1009 }
1010
1011 c.peerCertificates = certs
1012 return nil
1013}
1014
Adam Langley95c29f32014-06-20 12:00:00 -07001015func (hs *clientHandshakeState) establishKeys() error {
1016 c := hs.c
1017
1018 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
Nick Harper1fd39d82016-06-14 18:14:35 -07001019 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 -07001020 var clientCipher, serverCipher interface{}
1021 var clientHash, serverHash macFunction
1022 if hs.suite.cipher != nil {
1023 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
1024 clientHash = hs.suite.mac(c.vers, clientMAC)
1025 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
1026 serverHash = hs.suite.mac(c.vers, serverMAC)
1027 } else {
Nick Harper1fd39d82016-06-14 18:14:35 -07001028 clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
1029 serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
Adam Langley95c29f32014-06-20 12:00:00 -07001030 }
1031
1032 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
1033 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
1034 return nil
1035}
1036
David Benjamin75101402016-07-01 13:40:23 -04001037func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
1038 c := hs.c
1039
David Benjamin8d315d72016-07-18 01:03:18 +02001040 if c.vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001041 if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
1042 return errors.New("tls: renegotiation extension missing")
1043 }
David Benjamin75101402016-07-01 13:40:23 -04001044
Nick Harperb41d2e42016-07-01 17:50:32 -04001045 if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
1046 var expectedRenegInfo []byte
1047 expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
1048 expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
1049 if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
1050 c.sendAlert(alertHandshakeFailure)
1051 return fmt.Errorf("tls: renegotiation mismatch")
1052 }
David Benjamin75101402016-07-01 13:40:23 -04001053 }
David Benjamincea0ab42016-07-14 12:33:14 -04001054 } else if serverExtensions.secureRenegotiation != nil {
1055 return errors.New("tls: renegotiation info sent in TLS 1.3")
David Benjamin75101402016-07-01 13:40:23 -04001056 }
1057
1058 if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
1059 if serverExtensions.customExtension != *expected {
1060 return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
1061 }
1062 }
1063
1064 clientDidNPN := hs.hello.nextProtoNeg
1065 clientDidALPN := len(hs.hello.alpnProtocols) > 0
1066 serverHasNPN := serverExtensions.nextProtoNeg
1067 serverHasALPN := len(serverExtensions.alpnProtocol) > 0
1068
1069 if !clientDidNPN && serverHasNPN {
1070 c.sendAlert(alertHandshakeFailure)
1071 return errors.New("server advertised unrequested NPN extension")
1072 }
1073
1074 if !clientDidALPN && serverHasALPN {
1075 c.sendAlert(alertHandshakeFailure)
1076 return errors.New("server advertised unrequested ALPN extension")
1077 }
1078
1079 if serverHasNPN && serverHasALPN {
1080 c.sendAlert(alertHandshakeFailure)
1081 return errors.New("server advertised both NPN and ALPN extensions")
1082 }
1083
1084 if serverHasALPN {
1085 c.clientProtocol = serverExtensions.alpnProtocol
1086 c.clientProtocolFallback = false
1087 c.usedALPN = true
1088 }
1089
David Benjamin8d315d72016-07-18 01:03:18 +02001090 if serverHasNPN && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001091 c.sendAlert(alertHandshakeFailure)
1092 return errors.New("server advertised NPN over TLS 1.3")
1093 }
1094
David Benjamin75101402016-07-01 13:40:23 -04001095 if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
1096 c.sendAlert(alertHandshakeFailure)
1097 return errors.New("server advertised unrequested Channel ID extension")
1098 }
1099
David Benjamin8d315d72016-07-18 01:03:18 +02001100 if serverExtensions.channelIDRequested && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001101 c.sendAlert(alertHandshakeFailure)
1102 return errors.New("server advertised Channel ID over TLS 1.3")
1103 }
1104
David Benjamin8d315d72016-07-18 01:03:18 +02001105 if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
David Benjamine9077652016-07-13 21:02:08 -04001106 return errors.New("tls: server advertised extended master secret over TLS 1.3")
1107 }
1108
David Benjamin8d315d72016-07-18 01:03:18 +02001109 if serverExtensions.ticketSupported && c.vers >= VersionTLS13 {
Steven Valdez143e8b32016-07-11 13:19:03 -04001110 return errors.New("tls: server advertised ticket extension over TLS 1.3")
1111 }
1112
David Benjamin75101402016-07-01 13:40:23 -04001113 if serverExtensions.srtpProtectionProfile != 0 {
1114 if serverExtensions.srtpMasterKeyIdentifier != "" {
1115 return errors.New("tls: server selected SRTP MKI value")
1116 }
1117
1118 found := false
1119 for _, p := range c.config.SRTPProtectionProfiles {
1120 if p == serverExtensions.srtpProtectionProfile {
1121 found = true
1122 break
1123 }
1124 }
1125 if !found {
1126 return errors.New("tls: server advertised unsupported SRTP profile")
1127 }
1128
1129 c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
1130 }
1131
1132 return nil
1133}
1134
Adam Langley95c29f32014-06-20 12:00:00 -07001135func (hs *clientHandshakeState) serverResumedSession() bool {
1136 // If the server responded with the same sessionId then it means the
1137 // sessionTicket is being used to resume a TLS session.
1138 return hs.session != nil && hs.hello.sessionId != nil &&
1139 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
1140}
1141
1142func (hs *clientHandshakeState) processServerHello() (bool, error) {
1143 c := hs.c
1144
Adam Langley95c29f32014-06-20 12:00:00 -07001145 if hs.serverResumedSession() {
David Benjamin4b27d9f2015-05-12 22:42:52 -04001146 // For test purposes, assert that the server never accepts the
1147 // resumption offer on renegotiation.
1148 if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
1149 return false, errors.New("tls: server resumed session on renegotiation")
1150 }
1151
Nick Harperb3d51be2016-07-01 11:43:18 -04001152 if hs.serverHello.extensions.sctList != nil {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001153 return false, errors.New("tls: server sent SCT extension on session resumption")
1154 }
1155
Nick Harperb3d51be2016-07-01 11:43:18 -04001156 if hs.serverHello.extensions.ocspStapling {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001157 return false, errors.New("tls: server sent OCSP extension on session resumption")
1158 }
1159
Adam Langley95c29f32014-06-20 12:00:00 -07001160 // Restore masterSecret and peerCerts from previous state
1161 hs.masterSecret = hs.session.masterSecret
1162 c.peerCertificates = hs.session.serverCertificates
Adam Langley75712922014-10-10 16:23:43 -07001163 c.extendedMasterSecret = hs.session.extendedMasterSecret
Paul Lietar62be8ac2015-09-16 10:03:30 +01001164 c.sctList = hs.session.sctList
1165 c.ocspResponse = hs.session.ocspResponse
David Benjamine098ec22014-08-27 23:13:20 -04001166 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -07001167 return true, nil
1168 }
Paul Lietar62be8ac2015-09-16 10:03:30 +01001169
Nick Harperb3d51be2016-07-01 11:43:18 -04001170 if hs.serverHello.extensions.sctList != nil {
1171 c.sctList = hs.serverHello.extensions.sctList
Paul Lietar62be8ac2015-09-16 10:03:30 +01001172 }
1173
Adam Langley95c29f32014-06-20 12:00:00 -07001174 return false, nil
1175}
1176
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001177func (hs *clientHandshakeState) readFinished(out []byte) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001178 c := hs.c
1179
1180 c.readRecord(recordTypeChangeCipherSpec)
1181 if err := c.in.error(); err != nil {
1182 return err
1183 }
1184
1185 msg, err := c.readHandshake()
1186 if err != nil {
1187 return err
1188 }
1189 serverFinished, ok := msg.(*finishedMsg)
1190 if !ok {
1191 c.sendAlert(alertUnexpectedMessage)
1192 return unexpectedMessageError(serverFinished, msg)
1193 }
1194
David Benjaminf3ec83d2014-07-21 22:42:34 -04001195 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
1196 verify := hs.finishedHash.serverSum(hs.masterSecret)
1197 if len(verify) != len(serverFinished.verifyData) ||
1198 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
1199 c.sendAlert(alertHandshakeFailure)
1200 return errors.New("tls: server's Finished message was incorrect")
1201 }
Adam Langley95c29f32014-06-20 12:00:00 -07001202 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001203 c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001204 copy(out, serverFinished.verifyData)
David Benjamin83c0bc92014-08-04 01:23:53 -04001205 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001206 return nil
1207}
1208
1209func (hs *clientHandshakeState) readSessionTicket() error {
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001210 c := hs.c
1211
1212 // Create a session with no server identifier. Either a
1213 // session ID or session ticket will be attached.
1214 session := &ClientSessionState{
1215 vers: c.vers,
1216 cipherSuite: hs.suite.id,
1217 masterSecret: hs.masterSecret,
1218 handshakeHash: hs.finishedHash.server.Sum(nil),
1219 serverCertificates: c.peerCertificates,
Paul Lietar62be8ac2015-09-16 10:03:30 +01001220 sctList: c.sctList,
1221 ocspResponse: c.ocspResponse,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001222 }
1223
Nick Harperb3d51be2016-07-01 11:43:18 -04001224 if !hs.serverHello.extensions.ticketSupported {
David Benjamind98452d2015-06-16 14:16:23 -04001225 if c.config.Bugs.ExpectNewTicket {
1226 return errors.New("tls: expected new ticket")
1227 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001228 if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
1229 session.sessionId = hs.serverHello.sessionId
1230 hs.session = session
1231 }
Adam Langley95c29f32014-06-20 12:00:00 -07001232 return nil
1233 }
1234
David Benjaminc7ce9772015-10-09 19:32:41 -04001235 if c.vers == VersionSSL30 {
1236 return errors.New("tls: negotiated session tickets in SSL 3.0")
1237 }
1238
Adam Langley95c29f32014-06-20 12:00:00 -07001239 msg, err := c.readHandshake()
1240 if err != nil {
1241 return err
1242 }
1243 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
1244 if !ok {
1245 c.sendAlert(alertUnexpectedMessage)
1246 return unexpectedMessageError(sessionTicketMsg, msg)
1247 }
Adam Langley95c29f32014-06-20 12:00:00 -07001248
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001249 session.sessionTicket = sessionTicketMsg.ticket
1250 hs.session = session
Adam Langley95c29f32014-06-20 12:00:00 -07001251
David Benjamind30a9902014-08-24 01:44:23 -04001252 hs.writeServerHash(sessionTicketMsg.marshal())
1253
Adam Langley95c29f32014-06-20 12:00:00 -07001254 return nil
1255}
1256
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001257func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001258 c := hs.c
1259
David Benjamin0b8d5da2016-07-15 00:39:56 -04001260 var postCCSMsgs [][]byte
David Benjamin83c0bc92014-08-04 01:23:53 -04001261 seqno := hs.c.sendHandshakeSeq
Nick Harperb3d51be2016-07-01 11:43:18 -04001262 if hs.serverHello.extensions.nextProtoNeg {
Adam Langley95c29f32014-06-20 12:00:00 -07001263 nextProto := new(nextProtoMsg)
Nick Harperb3d51be2016-07-01 11:43:18 -04001264 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
Adam Langley95c29f32014-06-20 12:00:00 -07001265 nextProto.proto = proto
1266 c.clientProtocol = proto
1267 c.clientProtocolFallback = fallback
1268
David Benjamin86271ee2014-07-21 16:14:03 -04001269 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -04001270 hs.writeHash(nextProtoBytes, seqno)
1271 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001272 postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
Adam Langley95c29f32014-06-20 12:00:00 -07001273 }
1274
Nick Harperb3d51be2016-07-01 11:43:18 -04001275 if hs.serverHello.extensions.channelIDRequested {
David Benjamin24599a82016-06-30 18:56:53 -04001276 channelIDMsg := new(channelIDMsg)
David Benjamind30a9902014-08-24 01:44:23 -04001277 if c.config.ChannelID.Curve != elliptic.P256() {
1278 return fmt.Errorf("tls: Channel ID is not on P-256.")
1279 }
1280 var resumeHash []byte
1281 if isResume {
1282 resumeHash = hs.session.handshakeHash
1283 }
1284 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
1285 if err != nil {
1286 return err
1287 }
1288 channelID := make([]byte, 128)
1289 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
1290 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
1291 writeIntPadded(channelID[64:96], r)
1292 writeIntPadded(channelID[96:128], s)
David Benjamin24599a82016-06-30 18:56:53 -04001293 channelIDMsg.channelID = channelID
David Benjamind30a9902014-08-24 01:44:23 -04001294
1295 c.channelID = &c.config.ChannelID.PublicKey
1296
David Benjamin24599a82016-06-30 18:56:53 -04001297 channelIDMsgBytes := channelIDMsg.marshal()
1298 hs.writeHash(channelIDMsgBytes, seqno)
David Benjamind30a9902014-08-24 01:44:23 -04001299 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001300 postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
David Benjamind30a9902014-08-24 01:44:23 -04001301 }
1302
Adam Langley95c29f32014-06-20 12:00:00 -07001303 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -04001304 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
1305 finished.verifyData = hs.finishedHash.clientSum(nil)
1306 } else {
1307 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
1308 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001309 copy(out, finished.verifyData)
David Benjamin513f0ea2015-04-02 19:33:31 -04001310 if c.config.Bugs.BadFinished {
1311 finished.verifyData[0]++
1312 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001313 c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
David Benjamin83f90402015-01-27 01:09:43 -05001314 hs.finishedBytes = finished.marshal()
1315 hs.writeHash(hs.finishedBytes, seqno)
David Benjamin0b8d5da2016-07-15 00:39:56 -04001316 postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
David Benjamin86271ee2014-07-21 16:14:03 -04001317
1318 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001319 c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
1320 postCCSMsgs[0] = postCCSMsgs[0][5:]
David Benjamin61672812016-07-14 23:10:43 -04001321 } else if c.config.Bugs.SendUnencryptedFinished {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001322 c.writeRecord(recordTypeHandshake, postCCSMsgs[0])
1323 postCCSMsgs = postCCSMsgs[1:]
David Benjamin86271ee2014-07-21 16:14:03 -04001324 }
David Benjamin582ba042016-07-07 12:33:25 -07001325 c.flushHandshake()
David Benjamin86271ee2014-07-21 16:14:03 -04001326
1327 if !c.config.Bugs.SkipChangeCipherSpec &&
1328 c.config.Bugs.EarlyChangeCipherSpec == 0 {
David Benjamin8411b242015-11-26 12:07:28 -05001329 ccs := []byte{1}
1330 if c.config.Bugs.BadChangeCipherSpec != nil {
1331 ccs = c.config.Bugs.BadChangeCipherSpec
1332 }
1333 c.writeRecord(recordTypeChangeCipherSpec, ccs)
David Benjamin86271ee2014-07-21 16:14:03 -04001334 }
1335
David Benjamin4189bd92015-01-25 23:52:39 -05001336 if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
1337 c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
1338 }
David Benjamindc3da932015-03-12 15:09:02 -04001339 if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
1340 c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
1341 return errors.New("tls: simulating post-CCS alert")
1342 }
David Benjamin4189bd92015-01-25 23:52:39 -05001343
David Benjamin0b8d5da2016-07-15 00:39:56 -04001344 if !c.config.Bugs.SkipFinished {
1345 for _, msg := range postCCSMsgs {
1346 c.writeRecord(recordTypeHandshake, msg)
1347 }
David Benjamin582ba042016-07-07 12:33:25 -07001348 c.flushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -05001349 }
Adam Langley95c29f32014-06-20 12:00:00 -07001350 return nil
1351}
1352
David Benjamin83c0bc92014-08-04 01:23:53 -04001353func (hs *clientHandshakeState) writeClientHash(msg []byte) {
1354 // writeClientHash is called before writeRecord.
1355 hs.writeHash(msg, hs.c.sendHandshakeSeq)
1356}
1357
1358func (hs *clientHandshakeState) writeServerHash(msg []byte) {
1359 // writeServerHash is called after readHandshake.
1360 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
1361}
1362
1363func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
1364 if hs.c.isDTLS {
1365 // This is somewhat hacky. DTLS hashes a slightly different format.
1366 // First, the TLS header.
1367 hs.finishedHash.Write(msg[:4])
1368 // Then the sequence number and reassembled fragment offset (always 0).
1369 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
1370 // Then the reassembled fragment (always equal to the message length).
1371 hs.finishedHash.Write(msg[1:4])
1372 // And then the message body.
1373 hs.finishedHash.Write(msg[4:])
1374 } else {
1375 hs.finishedHash.Write(msg)
1376 }
1377}
1378
David Benjamina6f82632016-07-01 18:44:02 -04001379// selectClientCertificate selects a certificate for use with the given
1380// certificate, or none if none match. It may return a particular certificate or
1381// nil on success, or an error on internal error.
1382func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
1383 // RFC 4346 on the certificateAuthorities field:
1384 // A list of the distinguished names of acceptable certificate
1385 // authorities. These distinguished names may specify a desired
1386 // distinguished name for a root CA or for a subordinate CA; thus, this
1387 // message can be used to describe both known roots and a desired
1388 // authorization space. If the certificate_authorities list is empty
1389 // then the client MAY send any certificate of the appropriate
1390 // ClientCertificateType, unless there is some external arrangement to
1391 // the contrary.
1392
1393 var rsaAvail, ecdsaAvail bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001394 if !certReq.hasRequestContext {
1395 for _, certType := range certReq.certificateTypes {
1396 switch certType {
1397 case CertTypeRSASign:
1398 rsaAvail = true
1399 case CertTypeECDSASign:
1400 ecdsaAvail = true
1401 }
David Benjamina6f82632016-07-01 18:44:02 -04001402 }
1403 }
1404
1405 // We need to search our list of client certs for one
1406 // where SignatureAlgorithm is RSA and the Issuer is in
1407 // certReq.certificateAuthorities
1408findCert:
1409 for i, chain := range c.config.Certificates {
Nick Harperb41d2e42016-07-01 17:50:32 -04001410 if !certReq.hasRequestContext && !rsaAvail && !ecdsaAvail {
David Benjamina6f82632016-07-01 18:44:02 -04001411 continue
1412 }
1413
1414 // Ensure the private key supports one of the advertised
1415 // signature algorithms.
1416 if certReq.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -07001417 if _, err := selectSignatureAlgorithm(c.vers, chain.PrivateKey, c.config, certReq.signatureAlgorithms); err != nil {
David Benjamina6f82632016-07-01 18:44:02 -04001418 continue
1419 }
1420 }
1421
1422 for j, cert := range chain.Certificate {
1423 x509Cert := chain.Leaf
1424 // parse the certificate if this isn't the leaf
1425 // node, or if chain.Leaf was nil
1426 if j != 0 || x509Cert == nil {
1427 var err error
1428 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
1429 c.sendAlert(alertInternalError)
1430 return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
1431 }
1432 }
1433
Nick Harperb41d2e42016-07-01 17:50:32 -04001434 if !certReq.hasRequestContext {
1435 switch {
1436 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
1437 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
1438 default:
1439 continue findCert
1440 }
David Benjamina6f82632016-07-01 18:44:02 -04001441 }
1442
1443 if len(certReq.certificateAuthorities) == 0 {
1444 // They gave us an empty list, so just take the
1445 // first certificate of valid type from
1446 // c.config.Certificates.
1447 return &chain, nil
1448 }
1449
1450 for _, ca := range certReq.certificateAuthorities {
1451 if bytes.Equal(x509Cert.RawIssuer, ca) {
1452 return &chain, nil
1453 }
1454 }
1455 }
1456 }
1457
1458 return nil, nil
1459}
1460
Adam Langley95c29f32014-06-20 12:00:00 -07001461// clientSessionCacheKey returns a key used to cache sessionTickets that could
1462// be used to resume previously negotiated TLS sessions with a server.
1463func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
1464 if len(config.ServerName) > 0 {
1465 return config.ServerName
1466 }
1467 return serverAddr.String()
1468}
1469
David Benjaminfa055a22014-09-15 16:51:51 -04001470// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
1471// given list of possible protocols and a list of the preference order. The
1472// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -07001473// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -04001474func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
1475 for _, s := range preferenceProtos {
1476 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -07001477 if s == c {
1478 return s, false
1479 }
1480 }
1481 }
1482
David Benjaminfa055a22014-09-15 16:51:51 -04001483 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -07001484}
David Benjamind30a9902014-08-24 01:44:23 -04001485
1486// writeIntPadded writes x into b, padded up with leading zeros as
1487// needed.
1488func writeIntPadded(b []byte, x *big.Int) {
1489 for i := range b {
1490 b[i] = 0
1491 }
1492 xb := x.Bytes()
1493 copy(b[len(b)-len(xb):], xb)
1494}