blob: 291fb752fb8219f0d41a8bc4003a77ffb816fa10 [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 {
143 hello.keyShares = nil
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 Benjaminfe8eb9a2014-11-17 03:19:02 -0500223 if session.sessionTicket != nil {
224 hello.sessionTicket = session.sessionTicket
225 if c.config.Bugs.CorruptTicket {
226 hello.sessionTicket = make([]byte, len(session.sessionTicket))
227 copy(hello.sessionTicket, session.sessionTicket)
228 if len(hello.sessionTicket) > 0 {
229 offset := 40
230 if offset > len(hello.sessionTicket) {
231 offset = len(hello.sessionTicket) - 1
232 }
233 hello.sessionTicket[offset] ^= 0x40
Adam Langley38311732014-10-16 19:04:35 -0700234 }
Adam Langley38311732014-10-16 19:04:35 -0700235 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500236 // A random session ID is used to detect when the
237 // server accepted the ticket and is resuming a session
238 // (see RFC 5077).
239 sessionIdLen := 16
240 if c.config.Bugs.OversizedSessionId {
241 sessionIdLen = 33
242 }
243 hello.sessionId = make([]byte, sessionIdLen)
244 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
245 c.sendAlert(alertInternalError)
246 return errors.New("tls: short read from Rand: " + err.Error())
247 }
248 } else {
249 hello.sessionId = session.sessionId
Adam Langley95c29f32014-06-20 12:00:00 -0700250 }
251 }
252
David Benjamind86c7672014-08-02 04:07:12 -0400253 var helloBytes []byte
254 if c.config.Bugs.SendV2ClientHello {
David Benjamin94d701b2014-11-30 13:54:41 -0500255 // Test that the peer left-pads random.
256 hello.random[0] = 0
David Benjamind86c7672014-08-02 04:07:12 -0400257 v2Hello := &v2ClientHelloMsg{
258 vers: hello.vers,
259 cipherSuites: hello.cipherSuites,
260 // No session resumption for V2ClientHello.
261 sessionId: nil,
David Benjamin94d701b2014-11-30 13:54:41 -0500262 challenge: hello.random[1:],
David Benjamind86c7672014-08-02 04:07:12 -0400263 }
264 helloBytes = v2Hello.marshal()
265 c.writeV2Record(helloBytes)
266 } else {
267 helloBytes = hello.marshal()
David Benjamin7964b182016-07-14 23:36:30 -0400268 if c.config.Bugs.PartialClientFinishedWithClientHello {
269 // Include one byte of Finished. We can compute it
270 // without completing the handshake. This assumes we
271 // negotiate TLS 1.3 with no HelloRetryRequest or
272 // CertificateRequest.
273 toWrite := make([]byte, 0, len(helloBytes)+1)
274 toWrite = append(toWrite, helloBytes...)
275 toWrite = append(toWrite, typeFinished)
276 c.writeRecord(recordTypeHandshake, toWrite)
277 } else {
278 c.writeRecord(recordTypeHandshake, helloBytes)
279 }
David Benjamind86c7672014-08-02 04:07:12 -0400280 }
David Benjamin582ba042016-07-07 12:33:25 -0700281 c.flushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700282
David Benjamin83f90402015-01-27 01:09:43 -0500283 if err := c.simulatePacketLoss(nil); err != nil {
284 return err
285 }
Adam Langley95c29f32014-06-20 12:00:00 -0700286 msg, err := c.readHandshake()
287 if err != nil {
288 return err
289 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400290
291 if c.isDTLS {
292 helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
293 if ok {
David Benjamin8bc38f52014-08-16 12:07:27 -0400294 if helloVerifyRequest.vers != VersionTLS10 {
295 // Per RFC 6347, the version field in
296 // HelloVerifyRequest SHOULD be always DTLS
297 // 1.0. Enforce this for testing purposes.
298 return errors.New("dtls: bad HelloVerifyRequest version")
299 }
300
David Benjamin83c0bc92014-08-04 01:23:53 -0400301 hello.raw = nil
302 hello.cookie = helloVerifyRequest.cookie
303 helloBytes = hello.marshal()
304 c.writeRecord(recordTypeHandshake, helloBytes)
David Benjamin582ba042016-07-07 12:33:25 -0700305 c.flushHandshake()
David Benjamin83c0bc92014-08-04 01:23:53 -0400306
David Benjamin83f90402015-01-27 01:09:43 -0500307 if err := c.simulatePacketLoss(nil); err != nil {
308 return err
309 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400310 msg, err = c.readHandshake()
311 if err != nil {
312 return err
313 }
314 }
315 }
316
Nick Harperdcfbc672016-07-16 17:47:31 +0200317 var serverVersion uint16
318 switch m := msg.(type) {
319 case *helloRetryRequestMsg:
320 serverVersion = m.vers
321 case *serverHelloMsg:
322 serverVersion = m.vers
323 default:
324 c.sendAlert(alertUnexpectedMessage)
325 return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg)
326 }
327
328 var ok bool
329 c.vers, ok = c.config.mutualVersion(serverVersion, c.isDTLS)
330 if !ok {
331 c.sendAlert(alertProtocolVersion)
332 return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers)
333 }
334 c.haveVers = true
335
336 helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
337 var secondHelloBytes []byte
338 if haveHelloRetryRequest {
339 var hrrCurveFound bool
340 group := helloRetryRequest.selectedGroup
341 for _, curveID := range hello.supportedCurves {
342 if group == curveID {
343 hrrCurveFound = true
344 break
345 }
346 }
347 if !hrrCurveFound || keyShares[group] != nil {
348 c.sendAlert(alertHandshakeFailure)
349 return errors.New("tls: received invalid HelloRetryRequest")
350 }
351 curve, ok := curveForCurveID(group)
352 if !ok {
353 return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
354 }
355 publicKey, err := curve.offer(c.config.rand())
356 if err != nil {
357 return err
358 }
359 keyShares[group] = curve
360 hello.keyShares = append(hello.keyShares, keyShareEntry{
361 group: group,
362 keyExchange: publicKey,
363 })
364
365 hello.hasEarlyData = false
366 hello.earlyDataContext = nil
367 hello.raw = nil
368
369 secondHelloBytes = hello.marshal()
370 c.writeRecord(recordTypeHandshake, secondHelloBytes)
371 c.flushHandshake()
372
373 msg, err = c.readHandshake()
374 if err != nil {
375 return err
376 }
377 }
378
Adam Langley95c29f32014-06-20 12:00:00 -0700379 serverHello, ok := msg.(*serverHelloMsg)
380 if !ok {
381 c.sendAlert(alertUnexpectedMessage)
382 return unexpectedMessageError(serverHello, msg)
383 }
384
Nick Harperdcfbc672016-07-16 17:47:31 +0200385 if c.vers != serverHello.vers {
Adam Langley95c29f32014-06-20 12:00:00 -0700386 c.sendAlert(alertProtocolVersion)
Nick Harperdcfbc672016-07-16 17:47:31 +0200387 return fmt.Errorf("tls: server sent non-matching version %x vs %x", serverHello.vers, c.vers)
Adam Langley95c29f32014-06-20 12:00:00 -0700388 }
Adam Langley95c29f32014-06-20 12:00:00 -0700389
Nick Harper85f20c22016-07-04 10:11:59 -0700390 // Check for downgrade signals in the server random, per
David Benjamin1f61f0d2016-07-10 12:20:35 -0400391 // draft-ietf-tls-tls13-14, section 6.3.1.2.
Nick Harper85f20c22016-07-04 10:11:59 -0700392 if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400393 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS13) {
Nick Harper85f20c22016-07-04 10:11:59 -0700394 c.sendAlert(alertProtocolVersion)
395 return errors.New("tls: downgrade from TLS 1.3 detected")
396 }
397 }
398 if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 {
David Benjamin1f61f0d2016-07-10 12:20:35 -0400399 if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS12) {
Nick Harper85f20c22016-07-04 10:11:59 -0700400 c.sendAlert(alertProtocolVersion)
401 return errors.New("tls: downgrade from TLS 1.2 detected")
402 }
403 }
404
Adam Langley95c29f32014-06-20 12:00:00 -0700405 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
406 if suite == nil {
407 c.sendAlert(alertHandshakeFailure)
408 return fmt.Errorf("tls: server selected an unsupported cipher suite")
409 }
410
Nick Harperdcfbc672016-07-16 17:47:31 +0200411 if haveHelloRetryRequest && (helloRetryRequest.cipherSuite != serverHello.cipherSuite || helloRetryRequest.selectedGroup != serverHello.keyShare.group) {
412 c.sendAlert(alertHandshakeFailure)
413 return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
414 }
415
Adam Langley95c29f32014-06-20 12:00:00 -0700416 hs := &clientHandshakeState{
417 c: c,
418 serverHello: serverHello,
419 hello: hello,
420 suite: suite,
421 finishedHash: newFinishedHash(c.vers, suite),
Nick Harperb41d2e42016-07-01 17:50:32 -0400422 keyShares: keyShares,
Adam Langley95c29f32014-06-20 12:00:00 -0700423 session: session,
424 }
425
David Benjamin83c0bc92014-08-04 01:23:53 -0400426 hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
Nick Harperdcfbc672016-07-16 17:47:31 +0200427 if haveHelloRetryRequest {
428 hs.writeServerHash(helloRetryRequest.marshal())
429 hs.writeClientHash(secondHelloBytes)
430 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400431 hs.writeServerHash(hs.serverHello.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700432
David Benjamin8d315d72016-07-18 01:03:18 +0200433 if c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -0400434 if err := hs.doTLS13Handshake(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700435 return err
436 }
437 } else {
Nick Harperb41d2e42016-07-01 17:50:32 -0400438 if c.config.Bugs.EarlyChangeCipherSpec > 0 {
439 hs.establishKeys()
440 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
441 }
442
443 if hs.serverHello.compressionMethod != compressionNone {
444 c.sendAlert(alertUnexpectedMessage)
445 return errors.New("tls: server selected unsupported compression format")
446 }
447
448 err = hs.processServerExtensions(&serverHello.extensions)
449 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700450 return err
451 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400452
453 isResume, err := hs.processServerHello()
454 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700455 return err
456 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400457
458 if isResume {
459 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
460 if err := hs.establishKeys(); err != nil {
461 return err
462 }
463 }
464 if err := hs.readSessionTicket(); err != nil {
465 return err
466 }
467 if err := hs.readFinished(c.firstFinished[:]); err != nil {
468 return err
469 }
470 if err := hs.sendFinished(nil, isResume); err != nil {
471 return err
472 }
473 } else {
474 if err := hs.doFullHandshake(); err != nil {
475 return err
476 }
477 if err := hs.establishKeys(); err != nil {
478 return err
479 }
480 if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
481 return err
482 }
483 // Most retransmits are triggered by a timeout, but the final
484 // leg of the handshake is retransmited upon re-receiving a
485 // Finished.
486 if err := c.simulatePacketLoss(func() {
487 c.writeRecord(recordTypeHandshake, hs.finishedBytes)
488 c.flushHandshake()
489 }); err != nil {
490 return err
491 }
492 if err := hs.readSessionTicket(); err != nil {
493 return err
494 }
495 if err := hs.readFinished(nil); err != nil {
496 return err
497 }
Adam Langley95c29f32014-06-20 12:00:00 -0700498 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400499
500 if sessionCache != nil && hs.session != nil && session != hs.session {
501 if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
502 return errors.New("tls: new session used session IDs instead of tickets")
503 }
504 sessionCache.Put(cacheKey, hs.session)
David Benjamin83f90402015-01-27 01:09:43 -0500505 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400506
507 c.didResume = isResume
David Benjamin97a0a082016-07-13 17:57:35 -0400508 c.exporterSecret = hs.masterSecret
Adam Langley95c29f32014-06-20 12:00:00 -0700509 }
510
Adam Langley95c29f32014-06-20 12:00:00 -0700511 c.handshakeComplete = true
David Benjaminc565ebb2015-04-03 04:06:36 -0400512 c.cipherSuite = suite
513 copy(c.clientRandom[:], hs.hello.random)
514 copy(c.serverRandom[:], hs.serverHello.random)
Paul Lietar4fac72e2015-09-09 13:44:55 +0100515
Adam Langley95c29f32014-06-20 12:00:00 -0700516 return nil
517}
518
Nick Harperb41d2e42016-07-01 17:50:32 -0400519func (hs *clientHandshakeState) doTLS13Handshake() error {
520 c := hs.c
521
522 // Once the PRF hash is known, TLS 1.3 does not require a handshake
523 // buffer.
524 hs.finishedHash.discardHandshakeBuffer()
525
526 zeroSecret := hs.finishedHash.zeroSecret()
527
528 // Resolve PSK and compute the early secret.
529 //
530 // TODO(davidben): This will need to be handled slightly earlier once
531 // 0-RTT is implemented.
532 var psk []byte
533 if hs.suite.flags&suitePSK != 0 {
534 if !hs.serverHello.hasPSKIdentity {
535 c.sendAlert(alertMissingExtension)
536 return errors.New("tls: server omitted the PSK identity extension")
537 }
538
539 // TODO(davidben): Support PSK ciphers and PSK resumption. Set
540 // the resumption context appropriately if resuming.
541 return errors.New("tls: PSK ciphers not implemented for TLS 1.3")
542 } else {
543 if hs.serverHello.hasPSKIdentity {
544 c.sendAlert(alertUnsupportedExtension)
545 return errors.New("tls: server sent unexpected PSK identity")
546 }
547
548 psk = zeroSecret
549 hs.finishedHash.setResumptionContext(zeroSecret)
550 }
551
552 earlySecret := hs.finishedHash.extractKey(zeroSecret, psk)
553
554 // Resolve ECDHE and compute the handshake secret.
555 var ecdheSecret []byte
Steven Valdez143e8b32016-07-11 13:19:03 -0400556 if hs.suite.flags&suiteECDHE != 0 && !c.config.Bugs.MissingKeyShare {
Nick Harperb41d2e42016-07-01 17:50:32 -0400557 if !hs.serverHello.hasKeyShare {
558 c.sendAlert(alertMissingExtension)
559 return errors.New("tls: server omitted the key share extension")
560 }
561
562 curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
563 if !ok {
564 c.sendAlert(alertHandshakeFailure)
565 return errors.New("tls: server selected an unsupported group")
566 }
567
568 var err error
569 ecdheSecret, err = curve.finish(hs.serverHello.keyShare.keyExchange)
570 if err != nil {
571 return err
572 }
573 } else {
574 if hs.serverHello.hasKeyShare {
575 c.sendAlert(alertUnsupportedExtension)
576 return errors.New("tls: server sent unexpected key share extension")
577 }
578
579 ecdheSecret = zeroSecret
580 }
581
582 // Compute the handshake secret.
583 handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
584
585 // Switch to handshake traffic keys.
586 handshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, handshakeTrafficLabel)
587 c.out.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, clientWrite), c.vers)
588 c.in.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, serverWrite), c.vers)
589
590 msg, err := c.readHandshake()
591 if err != nil {
592 return err
593 }
594
595 encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
596 if !ok {
597 c.sendAlert(alertUnexpectedMessage)
598 return unexpectedMessageError(encryptedExtensions, msg)
599 }
600 hs.writeServerHash(encryptedExtensions.marshal())
601
602 err = hs.processServerExtensions(&encryptedExtensions.extensions)
603 if err != nil {
604 return err
605 }
606
607 var chainToSend *Certificate
David Benjamin8d343b42016-07-09 14:26:01 -0700608 var certReq *certificateRequestMsg
David Benjamin44b33bc2016-07-01 22:40:23 -0400609 if hs.suite.flags&suitePSK != 0 {
610 if encryptedExtensions.extensions.ocspResponse != nil {
611 c.sendAlert(alertUnsupportedExtension)
612 return errors.New("tls: server sent OCSP response without a certificate")
613 }
614 if encryptedExtensions.extensions.sctList != nil {
615 c.sendAlert(alertUnsupportedExtension)
616 return errors.New("tls: server sent SCT list without a certificate")
617 }
618 } else {
619 c.ocspResponse = encryptedExtensions.extensions.ocspResponse
620 c.sctList = encryptedExtensions.extensions.sctList
Nick Harperb41d2e42016-07-01 17:50:32 -0400621
622 msg, err := c.readHandshake()
623 if err != nil {
624 return err
625 }
626
David Benjamin8d343b42016-07-09 14:26:01 -0700627 var ok bool
628 certReq, ok = msg.(*certificateRequestMsg)
Nick Harperb41d2e42016-07-01 17:50:32 -0400629 if ok {
David Benjaminb62d2872016-07-18 14:55:02 +0200630 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
631 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
632 }
633
Nick Harperb41d2e42016-07-01 17:50:32 -0400634 hs.writeServerHash(certReq.marshal())
Nick Harperb41d2e42016-07-01 17:50:32 -0400635
636 chainToSend, err = selectClientCertificate(c, certReq)
637 if err != nil {
638 return err
639 }
640
641 msg, err = c.readHandshake()
642 if err != nil {
643 return err
644 }
645 }
646
647 certMsg, ok := msg.(*certificateMsg)
648 if !ok {
649 c.sendAlert(alertUnexpectedMessage)
650 return unexpectedMessageError(certMsg, msg)
651 }
652 hs.writeServerHash(certMsg.marshal())
653
654 if err := hs.verifyCertificates(certMsg); err != nil {
655 return err
656 }
657 leaf := c.peerCertificates[0]
658
659 msg, err = c.readHandshake()
660 if err != nil {
661 return err
662 }
663 certVerifyMsg, ok := msg.(*certificateVerifyMsg)
664 if !ok {
665 c.sendAlert(alertUnexpectedMessage)
666 return unexpectedMessageError(certVerifyMsg, msg)
667 }
668
David Benjaminf74ec792016-07-13 21:18:49 -0400669 c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
Nick Harperb41d2e42016-07-01 17:50:32 -0400670 input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
David Benjamin1fb125c2016-07-08 18:52:12 -0700671 err = verifyMessage(c.vers, leaf.PublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
Nick Harperb41d2e42016-07-01 17:50:32 -0400672 if err != nil {
673 return err
674 }
675
676 hs.writeServerHash(certVerifyMsg.marshal())
677 }
678
679 msg, err = c.readHandshake()
680 if err != nil {
681 return err
682 }
683 serverFinished, ok := msg.(*finishedMsg)
684 if !ok {
685 c.sendAlert(alertUnexpectedMessage)
686 return unexpectedMessageError(serverFinished, msg)
687 }
688
689 verify := hs.finishedHash.serverSum(handshakeTrafficSecret)
690 if len(verify) != len(serverFinished.verifyData) ||
691 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
692 c.sendAlert(alertHandshakeFailure)
693 return errors.New("tls: server's Finished message was incorrect")
694 }
695
696 hs.writeServerHash(serverFinished.marshal())
697
698 // The various secrets do not incorporate the client's final leg, so
699 // derive them now before updating the handshake context.
700 masterSecret := hs.finishedHash.extractKey(handshakeSecret, zeroSecret)
701 trafficSecret := hs.finishedHash.deriveSecret(masterSecret, applicationTrafficLabel)
702
Steven Valdez0ee2e112016-07-15 06:51:15 -0400703 if certReq != nil && !c.config.Bugs.SkipClientCertificate {
David Benjamin8d343b42016-07-09 14:26:01 -0700704 certMsg := &certificateMsg{
705 hasRequestContext: true,
706 requestContext: certReq.requestContext,
707 }
708 if chainToSend != nil {
709 certMsg.certificates = chainToSend.Certificate
710 }
711 hs.writeClientHash(certMsg.marshal())
712 c.writeRecord(recordTypeHandshake, certMsg.marshal())
713
714 if chainToSend != nil {
715 certVerify := &certificateVerifyMsg{
716 hasSignatureAlgorithm: true,
717 }
718
719 // Determine the hash to sign.
720 privKey := chainToSend.PrivateKey
721
722 var err error
723 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
724 if err != nil {
725 c.sendAlert(alertInternalError)
726 return err
727 }
728
729 input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
730 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
731 if err != nil {
732 c.sendAlert(alertInternalError)
733 return err
734 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400735 if c.config.Bugs.SendSignatureAlgorithm != 0 {
736 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
737 }
David Benjamin8d343b42016-07-09 14:26:01 -0700738
739 hs.writeClientHash(certVerify.marshal())
740 c.writeRecord(recordTypeHandshake, certVerify.marshal())
741 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400742 }
743
744 // Send a client Finished message.
745 finished := new(finishedMsg)
746 finished.verifyData = hs.finishedHash.clientSum(handshakeTrafficSecret)
747 if c.config.Bugs.BadFinished {
748 finished.verifyData[0]++
749 }
David Benjamin97a0a082016-07-13 17:57:35 -0400750 hs.writeClientHash(finished.marshal())
David Benjamin7964b182016-07-14 23:36:30 -0400751 if c.config.Bugs.PartialClientFinishedWithClientHello {
752 // The first byte has already been sent.
753 c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
754 } else {
755 c.writeRecord(recordTypeHandshake, finished.marshal())
756 }
David Benjaminee51a222016-07-07 18:34:12 -0700757 c.flushHandshake()
Nick Harperb41d2e42016-07-01 17:50:32 -0400758
759 // Switch to application data keys.
760 c.out.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, trafficSecret, applicationPhase, clientWrite), c.vers)
761 c.in.updateKeys(deriveTrafficAEAD(c.vers, hs.suite, trafficSecret, applicationPhase, serverWrite), c.vers)
762
Nick Harperb41d2e42016-07-01 17:50:32 -0400763 // TODO(davidben): Derive and save the resumption master secret for receiving tickets.
764 // TODO(davidben): Save the traffic secret for KeyUpdate.
David Benjamin97a0a082016-07-13 17:57:35 -0400765 c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
Nick Harperb41d2e42016-07-01 17:50:32 -0400766 return nil
767}
768
Adam Langley95c29f32014-06-20 12:00:00 -0700769func (hs *clientHandshakeState) doFullHandshake() error {
770 c := hs.c
771
David Benjamin48cae082014-10-27 01:06:24 -0400772 var leaf *x509.Certificate
773 if hs.suite.flags&suitePSK == 0 {
774 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700775 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700776 return err
777 }
Adam Langley95c29f32014-06-20 12:00:00 -0700778
David Benjamin48cae082014-10-27 01:06:24 -0400779 certMsg, ok := msg.(*certificateMsg)
David Benjamin75051442016-07-01 18:58:51 -0400780 if !ok {
David Benjamin48cae082014-10-27 01:06:24 -0400781 c.sendAlert(alertUnexpectedMessage)
782 return unexpectedMessageError(certMsg, msg)
783 }
784 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700785
David Benjamin75051442016-07-01 18:58:51 -0400786 if err := hs.verifyCertificates(certMsg); err != nil {
787 return err
David Benjamin48cae082014-10-27 01:06:24 -0400788 }
David Benjamin75051442016-07-01 18:58:51 -0400789 leaf = c.peerCertificates[0]
David Benjamin48cae082014-10-27 01:06:24 -0400790 }
Adam Langley95c29f32014-06-20 12:00:00 -0700791
Nick Harperb3d51be2016-07-01 11:43:18 -0400792 if hs.serverHello.extensions.ocspStapling {
David Benjamin48cae082014-10-27 01:06:24 -0400793 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700794 if err != nil {
795 return err
796 }
797 cs, ok := msg.(*certificateStatusMsg)
798 if !ok {
799 c.sendAlert(alertUnexpectedMessage)
800 return unexpectedMessageError(cs, msg)
801 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400802 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700803
804 if cs.statusType == statusTypeOCSP {
805 c.ocspResponse = cs.response
806 }
807 }
808
David Benjamin48cae082014-10-27 01:06:24 -0400809 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700810 if err != nil {
811 return err
812 }
813
814 keyAgreement := hs.suite.ka(c.vers)
815
816 skx, ok := msg.(*serverKeyExchangeMsg)
817 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -0400818 hs.writeServerHash(skx.marshal())
David Benjamin48cae082014-10-27 01:06:24 -0400819 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
Adam Langley95c29f32014-06-20 12:00:00 -0700820 if err != nil {
821 c.sendAlert(alertUnexpectedMessage)
822 return err
823 }
824
Nick Harper60edffd2016-06-21 15:19:24 -0700825 c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()
826
Adam Langley95c29f32014-06-20 12:00:00 -0700827 msg, err = c.readHandshake()
828 if err != nil {
829 return err
830 }
831 }
832
833 var chainToSend *Certificate
834 var certRequested bool
835 certReq, ok := msg.(*certificateRequestMsg)
836 if ok {
837 certRequested = true
David Benjamin7a41d372016-07-09 11:21:54 -0700838 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
839 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
840 }
Adam Langley95c29f32014-06-20 12:00:00 -0700841
David Benjamin83c0bc92014-08-04 01:23:53 -0400842 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700843
David Benjamina6f82632016-07-01 18:44:02 -0400844 chainToSend, err = selectClientCertificate(c, certReq)
845 if err != nil {
846 return err
Adam Langley95c29f32014-06-20 12:00:00 -0700847 }
848
849 msg, err = c.readHandshake()
850 if err != nil {
851 return err
852 }
853 }
854
855 shd, ok := msg.(*serverHelloDoneMsg)
856 if !ok {
857 c.sendAlert(alertUnexpectedMessage)
858 return unexpectedMessageError(shd, msg)
859 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400860 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700861
862 // If the server requested a certificate then we have to send a
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500863 // Certificate message in TLS, even if it's empty because we don't have
864 // a certificate to send. In SSL 3.0, skip the message and send a
865 // no_certificate warning alert.
Adam Langley95c29f32014-06-20 12:00:00 -0700866 if certRequested {
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500867 if c.vers == VersionSSL30 && chainToSend == nil {
868 c.sendAlert(alertNoCertficate)
869 } else if !c.config.Bugs.SkipClientCertificate {
870 certMsg := new(certificateMsg)
871 if chainToSend != nil {
872 certMsg.certificates = chainToSend.Certificate
873 }
874 hs.writeClientHash(certMsg.marshal())
875 c.writeRecord(recordTypeHandshake, certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700876 }
Adam Langley95c29f32014-06-20 12:00:00 -0700877 }
878
David Benjamin48cae082014-10-27 01:06:24 -0400879 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
Adam Langley95c29f32014-06-20 12:00:00 -0700880 if err != nil {
881 c.sendAlert(alertInternalError)
882 return err
883 }
884 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400885 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -0400886 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -0400887 }
Adam Langley95c29f32014-06-20 12:00:00 -0700888 c.writeRecord(recordTypeHandshake, ckx.marshal())
889 }
890
Nick Harperb3d51be2016-07-01 11:43:18 -0400891 if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
Adam Langley75712922014-10-10 16:23:43 -0700892 hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
893 c.extendedMasterSecret = true
894 } else {
895 if c.config.Bugs.RequireExtendedMasterSecret {
896 return errors.New("tls: extended master secret required but not supported by peer")
897 }
898 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
899 }
David Benjamine098ec22014-08-27 23:13:20 -0400900
Adam Langley95c29f32014-06-20 12:00:00 -0700901 if chainToSend != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700902 certVerify := &certificateVerifyMsg{
Nick Harper60edffd2016-06-21 15:19:24 -0700903 hasSignatureAlgorithm: c.vers >= VersionTLS12,
Adam Langley95c29f32014-06-20 12:00:00 -0700904 }
905
David Benjamin72dc7832015-03-16 17:49:43 -0400906 // Determine the hash to sign.
Nick Harper60edffd2016-06-21 15:19:24 -0700907 privKey := c.config.Certificates[0].PrivateKey
David Benjamin72dc7832015-03-16 17:49:43 -0400908
Nick Harper60edffd2016-06-21 15:19:24 -0700909 if certVerify.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -0700910 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
Nick Harper60edffd2016-06-21 15:19:24 -0700911 if err != nil {
912 c.sendAlert(alertInternalError)
913 return err
Adam Langley95c29f32014-06-20 12:00:00 -0700914 }
Nick Harper60edffd2016-06-21 15:19:24 -0700915 }
916
917 if c.vers > VersionSSL30 {
David Benjamin5208fd42016-07-13 21:43:25 -0400918 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
David Benjamina95e9f32016-07-08 16:28:04 -0700919 if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
920 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
921 }
Nick Harper60edffd2016-06-21 15:19:24 -0700922 } else {
923 // SSL 3.0's client certificate construction is
924 // incompatible with signatureAlgorithm.
925 rsaKey, ok := privKey.(*rsa.PrivateKey)
926 if !ok {
927 err = errors.New("unsupported signature type for client certificate")
928 } else {
929 digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
David Benjamin5208fd42016-07-13 21:43:25 -0400930 if c.config.Bugs.InvalidSignature {
Nick Harper60edffd2016-06-21 15:19:24 -0700931 digest[0] ^= 0x80
932 }
933 certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
934 }
Adam Langley95c29f32014-06-20 12:00:00 -0700935 }
936 if err != nil {
937 c.sendAlert(alertInternalError)
938 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
939 }
Adam Langley95c29f32014-06-20 12:00:00 -0700940
David Benjamin83c0bc92014-08-04 01:23:53 -0400941 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700942 c.writeRecord(recordTypeHandshake, certVerify.marshal())
943 }
David Benjamin82261be2016-07-07 14:32:50 -0700944 // flushHandshake will be called in sendFinished.
Adam Langley95c29f32014-06-20 12:00:00 -0700945
David Benjamine098ec22014-08-27 23:13:20 -0400946 hs.finishedHash.discardHandshakeBuffer()
947
Adam Langley95c29f32014-06-20 12:00:00 -0700948 return nil
949}
950
David Benjamin75051442016-07-01 18:58:51 -0400951func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
952 c := hs.c
953
954 if len(certMsg.certificates) == 0 {
955 c.sendAlert(alertIllegalParameter)
956 return errors.New("tls: no certificates sent")
957 }
958
959 certs := make([]*x509.Certificate, len(certMsg.certificates))
960 for i, asn1Data := range certMsg.certificates {
961 cert, err := x509.ParseCertificate(asn1Data)
962 if err != nil {
963 c.sendAlert(alertBadCertificate)
964 return errors.New("tls: failed to parse certificate from server: " + err.Error())
965 }
966 certs[i] = cert
967 }
968
969 if !c.config.InsecureSkipVerify {
970 opts := x509.VerifyOptions{
971 Roots: c.config.RootCAs,
972 CurrentTime: c.config.time(),
973 DNSName: c.config.ServerName,
974 Intermediates: x509.NewCertPool(),
975 }
976
977 for i, cert := range certs {
978 if i == 0 {
979 continue
980 }
981 opts.Intermediates.AddCert(cert)
982 }
983 var err error
984 c.verifiedChains, err = certs[0].Verify(opts)
985 if err != nil {
986 c.sendAlert(alertBadCertificate)
987 return err
988 }
989 }
990
991 switch certs[0].PublicKey.(type) {
992 case *rsa.PublicKey, *ecdsa.PublicKey:
993 break
994 default:
995 c.sendAlert(alertUnsupportedCertificate)
996 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
997 }
998
999 c.peerCertificates = certs
1000 return nil
1001}
1002
Adam Langley95c29f32014-06-20 12:00:00 -07001003func (hs *clientHandshakeState) establishKeys() error {
1004 c := hs.c
1005
1006 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
Nick Harper1fd39d82016-06-14 18:14:35 -07001007 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 -07001008 var clientCipher, serverCipher interface{}
1009 var clientHash, serverHash macFunction
1010 if hs.suite.cipher != nil {
1011 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
1012 clientHash = hs.suite.mac(c.vers, clientMAC)
1013 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
1014 serverHash = hs.suite.mac(c.vers, serverMAC)
1015 } else {
Nick Harper1fd39d82016-06-14 18:14:35 -07001016 clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
1017 serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
Adam Langley95c29f32014-06-20 12:00:00 -07001018 }
1019
1020 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
1021 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
1022 return nil
1023}
1024
David Benjamin75101402016-07-01 13:40:23 -04001025func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
1026 c := hs.c
1027
David Benjamin8d315d72016-07-18 01:03:18 +02001028 if c.vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001029 if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
1030 return errors.New("tls: renegotiation extension missing")
1031 }
David Benjamin75101402016-07-01 13:40:23 -04001032
Nick Harperb41d2e42016-07-01 17:50:32 -04001033 if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
1034 var expectedRenegInfo []byte
1035 expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
1036 expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
1037 if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
1038 c.sendAlert(alertHandshakeFailure)
1039 return fmt.Errorf("tls: renegotiation mismatch")
1040 }
David Benjamin75101402016-07-01 13:40:23 -04001041 }
David Benjamincea0ab42016-07-14 12:33:14 -04001042 } else if serverExtensions.secureRenegotiation != nil {
1043 return errors.New("tls: renegotiation info sent in TLS 1.3")
David Benjamin75101402016-07-01 13:40:23 -04001044 }
1045
1046 if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
1047 if serverExtensions.customExtension != *expected {
1048 return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
1049 }
1050 }
1051
1052 clientDidNPN := hs.hello.nextProtoNeg
1053 clientDidALPN := len(hs.hello.alpnProtocols) > 0
1054 serverHasNPN := serverExtensions.nextProtoNeg
1055 serverHasALPN := len(serverExtensions.alpnProtocol) > 0
1056
1057 if !clientDidNPN && serverHasNPN {
1058 c.sendAlert(alertHandshakeFailure)
1059 return errors.New("server advertised unrequested NPN extension")
1060 }
1061
1062 if !clientDidALPN && serverHasALPN {
1063 c.sendAlert(alertHandshakeFailure)
1064 return errors.New("server advertised unrequested ALPN extension")
1065 }
1066
1067 if serverHasNPN && serverHasALPN {
1068 c.sendAlert(alertHandshakeFailure)
1069 return errors.New("server advertised both NPN and ALPN extensions")
1070 }
1071
1072 if serverHasALPN {
1073 c.clientProtocol = serverExtensions.alpnProtocol
1074 c.clientProtocolFallback = false
1075 c.usedALPN = true
1076 }
1077
David Benjamin8d315d72016-07-18 01:03:18 +02001078 if serverHasNPN && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001079 c.sendAlert(alertHandshakeFailure)
1080 return errors.New("server advertised NPN over TLS 1.3")
1081 }
1082
David Benjamin75101402016-07-01 13:40:23 -04001083 if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
1084 c.sendAlert(alertHandshakeFailure)
1085 return errors.New("server advertised unrequested Channel ID extension")
1086 }
1087
David Benjamin8d315d72016-07-18 01:03:18 +02001088 if serverExtensions.channelIDRequested && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001089 c.sendAlert(alertHandshakeFailure)
1090 return errors.New("server advertised Channel ID over TLS 1.3")
1091 }
1092
David Benjamin8d315d72016-07-18 01:03:18 +02001093 if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
David Benjamine9077652016-07-13 21:02:08 -04001094 return errors.New("tls: server advertised extended master secret over TLS 1.3")
1095 }
1096
David Benjamin8d315d72016-07-18 01:03:18 +02001097 if serverExtensions.ticketSupported && c.vers >= VersionTLS13 {
Steven Valdez143e8b32016-07-11 13:19:03 -04001098 return errors.New("tls: server advertised ticket extension over TLS 1.3")
1099 }
1100
David Benjamin75101402016-07-01 13:40:23 -04001101 if serverExtensions.srtpProtectionProfile != 0 {
1102 if serverExtensions.srtpMasterKeyIdentifier != "" {
1103 return errors.New("tls: server selected SRTP MKI value")
1104 }
1105
1106 found := false
1107 for _, p := range c.config.SRTPProtectionProfiles {
1108 if p == serverExtensions.srtpProtectionProfile {
1109 found = true
1110 break
1111 }
1112 }
1113 if !found {
1114 return errors.New("tls: server advertised unsupported SRTP profile")
1115 }
1116
1117 c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
1118 }
1119
1120 return nil
1121}
1122
Adam Langley95c29f32014-06-20 12:00:00 -07001123func (hs *clientHandshakeState) serverResumedSession() bool {
1124 // If the server responded with the same sessionId then it means the
1125 // sessionTicket is being used to resume a TLS session.
1126 return hs.session != nil && hs.hello.sessionId != nil &&
1127 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
1128}
1129
1130func (hs *clientHandshakeState) processServerHello() (bool, error) {
1131 c := hs.c
1132
Adam Langley95c29f32014-06-20 12:00:00 -07001133 if hs.serverResumedSession() {
David Benjamin4b27d9f2015-05-12 22:42:52 -04001134 // For test purposes, assert that the server never accepts the
1135 // resumption offer on renegotiation.
1136 if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
1137 return false, errors.New("tls: server resumed session on renegotiation")
1138 }
1139
Nick Harperb3d51be2016-07-01 11:43:18 -04001140 if hs.serverHello.extensions.sctList != nil {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001141 return false, errors.New("tls: server sent SCT extension on session resumption")
1142 }
1143
Nick Harperb3d51be2016-07-01 11:43:18 -04001144 if hs.serverHello.extensions.ocspStapling {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001145 return false, errors.New("tls: server sent OCSP extension on session resumption")
1146 }
1147
Adam Langley95c29f32014-06-20 12:00:00 -07001148 // Restore masterSecret and peerCerts from previous state
1149 hs.masterSecret = hs.session.masterSecret
1150 c.peerCertificates = hs.session.serverCertificates
Adam Langley75712922014-10-10 16:23:43 -07001151 c.extendedMasterSecret = hs.session.extendedMasterSecret
Paul Lietar62be8ac2015-09-16 10:03:30 +01001152 c.sctList = hs.session.sctList
1153 c.ocspResponse = hs.session.ocspResponse
David Benjamine098ec22014-08-27 23:13:20 -04001154 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -07001155 return true, nil
1156 }
Paul Lietar62be8ac2015-09-16 10:03:30 +01001157
Nick Harperb3d51be2016-07-01 11:43:18 -04001158 if hs.serverHello.extensions.sctList != nil {
1159 c.sctList = hs.serverHello.extensions.sctList
Paul Lietar62be8ac2015-09-16 10:03:30 +01001160 }
1161
Adam Langley95c29f32014-06-20 12:00:00 -07001162 return false, nil
1163}
1164
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001165func (hs *clientHandshakeState) readFinished(out []byte) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001166 c := hs.c
1167
1168 c.readRecord(recordTypeChangeCipherSpec)
1169 if err := c.in.error(); err != nil {
1170 return err
1171 }
1172
1173 msg, err := c.readHandshake()
1174 if err != nil {
1175 return err
1176 }
1177 serverFinished, ok := msg.(*finishedMsg)
1178 if !ok {
1179 c.sendAlert(alertUnexpectedMessage)
1180 return unexpectedMessageError(serverFinished, msg)
1181 }
1182
David Benjaminf3ec83d2014-07-21 22:42:34 -04001183 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
1184 verify := hs.finishedHash.serverSum(hs.masterSecret)
1185 if len(verify) != len(serverFinished.verifyData) ||
1186 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
1187 c.sendAlert(alertHandshakeFailure)
1188 return errors.New("tls: server's Finished message was incorrect")
1189 }
Adam Langley95c29f32014-06-20 12:00:00 -07001190 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001191 c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001192 copy(out, serverFinished.verifyData)
David Benjamin83c0bc92014-08-04 01:23:53 -04001193 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001194 return nil
1195}
1196
1197func (hs *clientHandshakeState) readSessionTicket() error {
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001198 c := hs.c
1199
1200 // Create a session with no server identifier. Either a
1201 // session ID or session ticket will be attached.
1202 session := &ClientSessionState{
1203 vers: c.vers,
1204 cipherSuite: hs.suite.id,
1205 masterSecret: hs.masterSecret,
1206 handshakeHash: hs.finishedHash.server.Sum(nil),
1207 serverCertificates: c.peerCertificates,
Paul Lietar62be8ac2015-09-16 10:03:30 +01001208 sctList: c.sctList,
1209 ocspResponse: c.ocspResponse,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001210 }
1211
Nick Harperb3d51be2016-07-01 11:43:18 -04001212 if !hs.serverHello.extensions.ticketSupported {
David Benjamind98452d2015-06-16 14:16:23 -04001213 if c.config.Bugs.ExpectNewTicket {
1214 return errors.New("tls: expected new ticket")
1215 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001216 if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
1217 session.sessionId = hs.serverHello.sessionId
1218 hs.session = session
1219 }
Adam Langley95c29f32014-06-20 12:00:00 -07001220 return nil
1221 }
1222
David Benjaminc7ce9772015-10-09 19:32:41 -04001223 if c.vers == VersionSSL30 {
1224 return errors.New("tls: negotiated session tickets in SSL 3.0")
1225 }
1226
Adam Langley95c29f32014-06-20 12:00:00 -07001227 msg, err := c.readHandshake()
1228 if err != nil {
1229 return err
1230 }
1231 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
1232 if !ok {
1233 c.sendAlert(alertUnexpectedMessage)
1234 return unexpectedMessageError(sessionTicketMsg, msg)
1235 }
Adam Langley95c29f32014-06-20 12:00:00 -07001236
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001237 session.sessionTicket = sessionTicketMsg.ticket
1238 hs.session = session
Adam Langley95c29f32014-06-20 12:00:00 -07001239
David Benjamind30a9902014-08-24 01:44:23 -04001240 hs.writeServerHash(sessionTicketMsg.marshal())
1241
Adam Langley95c29f32014-06-20 12:00:00 -07001242 return nil
1243}
1244
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001245func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001246 c := hs.c
1247
David Benjamin0b8d5da2016-07-15 00:39:56 -04001248 var postCCSMsgs [][]byte
David Benjamin83c0bc92014-08-04 01:23:53 -04001249 seqno := hs.c.sendHandshakeSeq
Nick Harperb3d51be2016-07-01 11:43:18 -04001250 if hs.serverHello.extensions.nextProtoNeg {
Adam Langley95c29f32014-06-20 12:00:00 -07001251 nextProto := new(nextProtoMsg)
Nick Harperb3d51be2016-07-01 11:43:18 -04001252 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
Adam Langley95c29f32014-06-20 12:00:00 -07001253 nextProto.proto = proto
1254 c.clientProtocol = proto
1255 c.clientProtocolFallback = fallback
1256
David Benjamin86271ee2014-07-21 16:14:03 -04001257 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -04001258 hs.writeHash(nextProtoBytes, seqno)
1259 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001260 postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
Adam Langley95c29f32014-06-20 12:00:00 -07001261 }
1262
Nick Harperb3d51be2016-07-01 11:43:18 -04001263 if hs.serverHello.extensions.channelIDRequested {
David Benjamin24599a82016-06-30 18:56:53 -04001264 channelIDMsg := new(channelIDMsg)
David Benjamind30a9902014-08-24 01:44:23 -04001265 if c.config.ChannelID.Curve != elliptic.P256() {
1266 return fmt.Errorf("tls: Channel ID is not on P-256.")
1267 }
1268 var resumeHash []byte
1269 if isResume {
1270 resumeHash = hs.session.handshakeHash
1271 }
1272 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
1273 if err != nil {
1274 return err
1275 }
1276 channelID := make([]byte, 128)
1277 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
1278 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
1279 writeIntPadded(channelID[64:96], r)
1280 writeIntPadded(channelID[96:128], s)
David Benjamin24599a82016-06-30 18:56:53 -04001281 channelIDMsg.channelID = channelID
David Benjamind30a9902014-08-24 01:44:23 -04001282
1283 c.channelID = &c.config.ChannelID.PublicKey
1284
David Benjamin24599a82016-06-30 18:56:53 -04001285 channelIDMsgBytes := channelIDMsg.marshal()
1286 hs.writeHash(channelIDMsgBytes, seqno)
David Benjamind30a9902014-08-24 01:44:23 -04001287 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001288 postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
David Benjamind30a9902014-08-24 01:44:23 -04001289 }
1290
Adam Langley95c29f32014-06-20 12:00:00 -07001291 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -04001292 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
1293 finished.verifyData = hs.finishedHash.clientSum(nil)
1294 } else {
1295 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
1296 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001297 copy(out, finished.verifyData)
David Benjamin513f0ea2015-04-02 19:33:31 -04001298 if c.config.Bugs.BadFinished {
1299 finished.verifyData[0]++
1300 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001301 c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
David Benjamin83f90402015-01-27 01:09:43 -05001302 hs.finishedBytes = finished.marshal()
1303 hs.writeHash(hs.finishedBytes, seqno)
David Benjamin0b8d5da2016-07-15 00:39:56 -04001304 postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
David Benjamin86271ee2014-07-21 16:14:03 -04001305
1306 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001307 c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
1308 postCCSMsgs[0] = postCCSMsgs[0][5:]
David Benjamin61672812016-07-14 23:10:43 -04001309 } else if c.config.Bugs.SendUnencryptedFinished {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001310 c.writeRecord(recordTypeHandshake, postCCSMsgs[0])
1311 postCCSMsgs = postCCSMsgs[1:]
David Benjamin86271ee2014-07-21 16:14:03 -04001312 }
David Benjamin582ba042016-07-07 12:33:25 -07001313 c.flushHandshake()
David Benjamin86271ee2014-07-21 16:14:03 -04001314
1315 if !c.config.Bugs.SkipChangeCipherSpec &&
1316 c.config.Bugs.EarlyChangeCipherSpec == 0 {
David Benjamin8411b242015-11-26 12:07:28 -05001317 ccs := []byte{1}
1318 if c.config.Bugs.BadChangeCipherSpec != nil {
1319 ccs = c.config.Bugs.BadChangeCipherSpec
1320 }
1321 c.writeRecord(recordTypeChangeCipherSpec, ccs)
David Benjamin86271ee2014-07-21 16:14:03 -04001322 }
1323
David Benjamin4189bd92015-01-25 23:52:39 -05001324 if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
1325 c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
1326 }
David Benjamindc3da932015-03-12 15:09:02 -04001327 if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
1328 c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
1329 return errors.New("tls: simulating post-CCS alert")
1330 }
David Benjamin4189bd92015-01-25 23:52:39 -05001331
David Benjamin0b8d5da2016-07-15 00:39:56 -04001332 if !c.config.Bugs.SkipFinished {
1333 for _, msg := range postCCSMsgs {
1334 c.writeRecord(recordTypeHandshake, msg)
1335 }
David Benjamin582ba042016-07-07 12:33:25 -07001336 c.flushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -05001337 }
Adam Langley95c29f32014-06-20 12:00:00 -07001338 return nil
1339}
1340
David Benjamin83c0bc92014-08-04 01:23:53 -04001341func (hs *clientHandshakeState) writeClientHash(msg []byte) {
1342 // writeClientHash is called before writeRecord.
1343 hs.writeHash(msg, hs.c.sendHandshakeSeq)
1344}
1345
1346func (hs *clientHandshakeState) writeServerHash(msg []byte) {
1347 // writeServerHash is called after readHandshake.
1348 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
1349}
1350
1351func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
1352 if hs.c.isDTLS {
1353 // This is somewhat hacky. DTLS hashes a slightly different format.
1354 // First, the TLS header.
1355 hs.finishedHash.Write(msg[:4])
1356 // Then the sequence number and reassembled fragment offset (always 0).
1357 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
1358 // Then the reassembled fragment (always equal to the message length).
1359 hs.finishedHash.Write(msg[1:4])
1360 // And then the message body.
1361 hs.finishedHash.Write(msg[4:])
1362 } else {
1363 hs.finishedHash.Write(msg)
1364 }
1365}
1366
David Benjamina6f82632016-07-01 18:44:02 -04001367// selectClientCertificate selects a certificate for use with the given
1368// certificate, or none if none match. It may return a particular certificate or
1369// nil on success, or an error on internal error.
1370func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
1371 // RFC 4346 on the certificateAuthorities field:
1372 // A list of the distinguished names of acceptable certificate
1373 // authorities. These distinguished names may specify a desired
1374 // distinguished name for a root CA or for a subordinate CA; thus, this
1375 // message can be used to describe both known roots and a desired
1376 // authorization space. If the certificate_authorities list is empty
1377 // then the client MAY send any certificate of the appropriate
1378 // ClientCertificateType, unless there is some external arrangement to
1379 // the contrary.
1380
1381 var rsaAvail, ecdsaAvail bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001382 if !certReq.hasRequestContext {
1383 for _, certType := range certReq.certificateTypes {
1384 switch certType {
1385 case CertTypeRSASign:
1386 rsaAvail = true
1387 case CertTypeECDSASign:
1388 ecdsaAvail = true
1389 }
David Benjamina6f82632016-07-01 18:44:02 -04001390 }
1391 }
1392
1393 // We need to search our list of client certs for one
1394 // where SignatureAlgorithm is RSA and the Issuer is in
1395 // certReq.certificateAuthorities
1396findCert:
1397 for i, chain := range c.config.Certificates {
Nick Harperb41d2e42016-07-01 17:50:32 -04001398 if !certReq.hasRequestContext && !rsaAvail && !ecdsaAvail {
David Benjamina6f82632016-07-01 18:44:02 -04001399 continue
1400 }
1401
1402 // Ensure the private key supports one of the advertised
1403 // signature algorithms.
1404 if certReq.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -07001405 if _, err := selectSignatureAlgorithm(c.vers, chain.PrivateKey, c.config, certReq.signatureAlgorithms); err != nil {
David Benjamina6f82632016-07-01 18:44:02 -04001406 continue
1407 }
1408 }
1409
1410 for j, cert := range chain.Certificate {
1411 x509Cert := chain.Leaf
1412 // parse the certificate if this isn't the leaf
1413 // node, or if chain.Leaf was nil
1414 if j != 0 || x509Cert == nil {
1415 var err error
1416 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
1417 c.sendAlert(alertInternalError)
1418 return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
1419 }
1420 }
1421
Nick Harperb41d2e42016-07-01 17:50:32 -04001422 if !certReq.hasRequestContext {
1423 switch {
1424 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
1425 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
1426 default:
1427 continue findCert
1428 }
David Benjamina6f82632016-07-01 18:44:02 -04001429 }
1430
1431 if len(certReq.certificateAuthorities) == 0 {
1432 // They gave us an empty list, so just take the
1433 // first certificate of valid type from
1434 // c.config.Certificates.
1435 return &chain, nil
1436 }
1437
1438 for _, ca := range certReq.certificateAuthorities {
1439 if bytes.Equal(x509Cert.RawIssuer, ca) {
1440 return &chain, nil
1441 }
1442 }
1443 }
1444 }
1445
1446 return nil, nil
1447}
1448
Adam Langley95c29f32014-06-20 12:00:00 -07001449// clientSessionCacheKey returns a key used to cache sessionTickets that could
1450// be used to resume previously negotiated TLS sessions with a server.
1451func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
1452 if len(config.ServerName) > 0 {
1453 return config.ServerName
1454 }
1455 return serverAddr.String()
1456}
1457
David Benjaminfa055a22014-09-15 16:51:51 -04001458// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
1459// given list of possible protocols and a list of the preference order. The
1460// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -07001461// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -04001462func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
1463 for _, s := range preferenceProtos {
1464 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -07001465 if s == c {
1466 return s, false
1467 }
1468 }
1469 }
1470
David Benjaminfa055a22014-09-15 16:51:51 -04001471 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -07001472}
David Benjamind30a9902014-08-24 01:44:23 -04001473
1474// writeIntPadded writes x into b, padded up with leading zeros as
1475// needed.
1476func writeIntPadded(b []byte, x *big.Int) {
1477 for i := range b {
1478 b[i] = 0
1479 }
1480 xb := x.Bytes()
1481 copy(b[len(b)-len(xb):], xb)
1482}