blob: 36bd7e436c55f90a7910464deaeae2996df7950c [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() {
David Benjamin02edcd02016-07-27 17:40:37 -0400496 c.sendHandshakeSeq--
Nick Harperb41d2e42016-07-01 17:50:32 -0400497 c.writeRecord(recordTypeHandshake, hs.finishedBytes)
498 c.flushHandshake()
499 }); err != nil {
500 return err
501 }
502 if err := hs.readSessionTicket(); err != nil {
503 return err
504 }
505 if err := hs.readFinished(nil); err != nil {
506 return err
507 }
Adam Langley95c29f32014-06-20 12:00:00 -0700508 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400509
510 if sessionCache != nil && hs.session != nil && session != hs.session {
511 if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
512 return errors.New("tls: new session used session IDs instead of tickets")
513 }
514 sessionCache.Put(cacheKey, hs.session)
David Benjamin83f90402015-01-27 01:09:43 -0500515 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400516
517 c.didResume = isResume
David Benjamin97a0a082016-07-13 17:57:35 -0400518 c.exporterSecret = hs.masterSecret
Adam Langley95c29f32014-06-20 12:00:00 -0700519 }
520
Adam Langley95c29f32014-06-20 12:00:00 -0700521 c.handshakeComplete = true
David Benjaminc565ebb2015-04-03 04:06:36 -0400522 c.cipherSuite = suite
523 copy(c.clientRandom[:], hs.hello.random)
524 copy(c.serverRandom[:], hs.serverHello.random)
Paul Lietar4fac72e2015-09-09 13:44:55 +0100525
Adam Langley95c29f32014-06-20 12:00:00 -0700526 return nil
527}
528
Nick Harperb41d2e42016-07-01 17:50:32 -0400529func (hs *clientHandshakeState) doTLS13Handshake() error {
530 c := hs.c
531
532 // Once the PRF hash is known, TLS 1.3 does not require a handshake
533 // buffer.
534 hs.finishedHash.discardHandshakeBuffer()
535
536 zeroSecret := hs.finishedHash.zeroSecret()
537
538 // Resolve PSK and compute the early secret.
539 //
540 // TODO(davidben): This will need to be handled slightly earlier once
541 // 0-RTT is implemented.
542 var psk []byte
543 if hs.suite.flags&suitePSK != 0 {
544 if !hs.serverHello.hasPSKIdentity {
545 c.sendAlert(alertMissingExtension)
546 return errors.New("tls: server omitted the PSK identity extension")
547 }
548
549 // TODO(davidben): Support PSK ciphers and PSK resumption. Set
550 // the resumption context appropriately if resuming.
551 return errors.New("tls: PSK ciphers not implemented for TLS 1.3")
552 } else {
553 if hs.serverHello.hasPSKIdentity {
554 c.sendAlert(alertUnsupportedExtension)
555 return errors.New("tls: server sent unexpected PSK identity")
556 }
557
558 psk = zeroSecret
559 hs.finishedHash.setResumptionContext(zeroSecret)
560 }
561
562 earlySecret := hs.finishedHash.extractKey(zeroSecret, psk)
563
564 // Resolve ECDHE and compute the handshake secret.
565 var ecdheSecret []byte
Steven Valdez5440fe02016-07-18 12:40:30 -0400566 if hs.suite.flags&suiteECDHE != 0 && !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
Nick Harperb41d2e42016-07-01 17:50:32 -0400567 if !hs.serverHello.hasKeyShare {
568 c.sendAlert(alertMissingExtension)
569 return errors.New("tls: server omitted the key share extension")
570 }
571
572 curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
573 if !ok {
574 c.sendAlert(alertHandshakeFailure)
575 return errors.New("tls: server selected an unsupported group")
576 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400577 c.curveID = hs.serverHello.keyShare.group
Nick Harperb41d2e42016-07-01 17:50:32 -0400578
579 var err error
580 ecdheSecret, err = curve.finish(hs.serverHello.keyShare.keyExchange)
581 if err != nil {
582 return err
583 }
584 } else {
585 if hs.serverHello.hasKeyShare {
586 c.sendAlert(alertUnsupportedExtension)
587 return errors.New("tls: server sent unexpected key share extension")
588 }
589
590 ecdheSecret = zeroSecret
591 }
592
593 // Compute the handshake secret.
594 handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
595
596 // Switch to handshake traffic keys.
597 handshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, handshakeTrafficLabel)
David Benjamin21c00282016-07-18 21:56:23 +0200598 c.out.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, clientWrite)
599 c.in.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, serverWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400600
601 msg, err := c.readHandshake()
602 if err != nil {
603 return err
604 }
605
606 encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
607 if !ok {
608 c.sendAlert(alertUnexpectedMessage)
609 return unexpectedMessageError(encryptedExtensions, msg)
610 }
611 hs.writeServerHash(encryptedExtensions.marshal())
612
613 err = hs.processServerExtensions(&encryptedExtensions.extensions)
614 if err != nil {
615 return err
616 }
617
618 var chainToSend *Certificate
David Benjamin8d343b42016-07-09 14:26:01 -0700619 var certReq *certificateRequestMsg
David Benjamin44b33bc2016-07-01 22:40:23 -0400620 if hs.suite.flags&suitePSK != 0 {
621 if encryptedExtensions.extensions.ocspResponse != nil {
622 c.sendAlert(alertUnsupportedExtension)
623 return errors.New("tls: server sent OCSP response without a certificate")
624 }
625 if encryptedExtensions.extensions.sctList != nil {
626 c.sendAlert(alertUnsupportedExtension)
627 return errors.New("tls: server sent SCT list without a certificate")
628 }
629 } else {
630 c.ocspResponse = encryptedExtensions.extensions.ocspResponse
631 c.sctList = encryptedExtensions.extensions.sctList
Nick Harperb41d2e42016-07-01 17:50:32 -0400632
633 msg, err := c.readHandshake()
634 if err != nil {
635 return err
636 }
637
David Benjamin8d343b42016-07-09 14:26:01 -0700638 var ok bool
639 certReq, ok = msg.(*certificateRequestMsg)
Nick Harperb41d2e42016-07-01 17:50:32 -0400640 if ok {
David Benjaminb62d2872016-07-18 14:55:02 +0200641 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
642 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
643 }
644
Nick Harperb41d2e42016-07-01 17:50:32 -0400645 hs.writeServerHash(certReq.marshal())
Nick Harperb41d2e42016-07-01 17:50:32 -0400646
647 chainToSend, err = selectClientCertificate(c, certReq)
648 if err != nil {
649 return err
650 }
651
652 msg, err = c.readHandshake()
653 if err != nil {
654 return err
655 }
656 }
657
658 certMsg, ok := msg.(*certificateMsg)
659 if !ok {
660 c.sendAlert(alertUnexpectedMessage)
661 return unexpectedMessageError(certMsg, msg)
662 }
663 hs.writeServerHash(certMsg.marshal())
664
665 if err := hs.verifyCertificates(certMsg); err != nil {
666 return err
667 }
668 leaf := c.peerCertificates[0]
669
670 msg, err = c.readHandshake()
671 if err != nil {
672 return err
673 }
674 certVerifyMsg, ok := msg.(*certificateVerifyMsg)
675 if !ok {
676 c.sendAlert(alertUnexpectedMessage)
677 return unexpectedMessageError(certVerifyMsg, msg)
678 }
679
David Benjaminf74ec792016-07-13 21:18:49 -0400680 c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
Nick Harperb41d2e42016-07-01 17:50:32 -0400681 input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
David Benjamin1fb125c2016-07-08 18:52:12 -0700682 err = verifyMessage(c.vers, leaf.PublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
Nick Harperb41d2e42016-07-01 17:50:32 -0400683 if err != nil {
684 return err
685 }
686
687 hs.writeServerHash(certVerifyMsg.marshal())
688 }
689
690 msg, err = c.readHandshake()
691 if err != nil {
692 return err
693 }
694 serverFinished, ok := msg.(*finishedMsg)
695 if !ok {
696 c.sendAlert(alertUnexpectedMessage)
697 return unexpectedMessageError(serverFinished, msg)
698 }
699
700 verify := hs.finishedHash.serverSum(handshakeTrafficSecret)
701 if len(verify) != len(serverFinished.verifyData) ||
702 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
703 c.sendAlert(alertHandshakeFailure)
704 return errors.New("tls: server's Finished message was incorrect")
705 }
706
707 hs.writeServerHash(serverFinished.marshal())
708
709 // The various secrets do not incorporate the client's final leg, so
710 // derive them now before updating the handshake context.
711 masterSecret := hs.finishedHash.extractKey(handshakeSecret, zeroSecret)
712 trafficSecret := hs.finishedHash.deriveSecret(masterSecret, applicationTrafficLabel)
713
Steven Valdez0ee2e112016-07-15 06:51:15 -0400714 if certReq != nil && !c.config.Bugs.SkipClientCertificate {
David Benjamin8d343b42016-07-09 14:26:01 -0700715 certMsg := &certificateMsg{
716 hasRequestContext: true,
717 requestContext: certReq.requestContext,
718 }
719 if chainToSend != nil {
720 certMsg.certificates = chainToSend.Certificate
721 }
722 hs.writeClientHash(certMsg.marshal())
723 c.writeRecord(recordTypeHandshake, certMsg.marshal())
724
725 if chainToSend != nil {
726 certVerify := &certificateVerifyMsg{
727 hasSignatureAlgorithm: true,
728 }
729
730 // Determine the hash to sign.
731 privKey := chainToSend.PrivateKey
732
733 var err error
734 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
735 if err != nil {
736 c.sendAlert(alertInternalError)
737 return err
738 }
739
740 input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
741 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
742 if err != nil {
743 c.sendAlert(alertInternalError)
744 return err
745 }
Steven Valdez0ee2e112016-07-15 06:51:15 -0400746 if c.config.Bugs.SendSignatureAlgorithm != 0 {
747 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
748 }
David Benjamin8d343b42016-07-09 14:26:01 -0700749
750 hs.writeClientHash(certVerify.marshal())
751 c.writeRecord(recordTypeHandshake, certVerify.marshal())
752 }
Nick Harperb41d2e42016-07-01 17:50:32 -0400753 }
754
755 // Send a client Finished message.
756 finished := new(finishedMsg)
757 finished.verifyData = hs.finishedHash.clientSum(handshakeTrafficSecret)
758 if c.config.Bugs.BadFinished {
759 finished.verifyData[0]++
760 }
David Benjamin97a0a082016-07-13 17:57:35 -0400761 hs.writeClientHash(finished.marshal())
David Benjamin7964b182016-07-14 23:36:30 -0400762 if c.config.Bugs.PartialClientFinishedWithClientHello {
763 // The first byte has already been sent.
764 c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
765 } else {
766 c.writeRecord(recordTypeHandshake, finished.marshal())
767 }
David Benjamin02edcd02016-07-27 17:40:37 -0400768 if c.config.Bugs.SendExtraFinished {
769 c.writeRecord(recordTypeHandshake, finished.marshal())
770 }
David Benjaminee51a222016-07-07 18:34:12 -0700771 c.flushHandshake()
Nick Harperb41d2e42016-07-01 17:50:32 -0400772
773 // Switch to application data keys.
David Benjamin21c00282016-07-18 21:56:23 +0200774 c.out.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, clientWrite)
775 c.in.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, serverWrite)
Nick Harperb41d2e42016-07-01 17:50:32 -0400776
David Benjamin97a0a082016-07-13 17:57:35 -0400777 c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
David Benjamind5a4ecb2016-07-18 01:17:13 +0200778 c.resumptionSecret = hs.finishedHash.deriveSecret(masterSecret, resumptionLabel)
Nick Harperb41d2e42016-07-01 17:50:32 -0400779 return nil
780}
781
Adam Langley95c29f32014-06-20 12:00:00 -0700782func (hs *clientHandshakeState) doFullHandshake() error {
783 c := hs.c
784
David Benjamin48cae082014-10-27 01:06:24 -0400785 var leaf *x509.Certificate
786 if hs.suite.flags&suitePSK == 0 {
787 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700788 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700789 return err
790 }
Adam Langley95c29f32014-06-20 12:00:00 -0700791
David Benjamin48cae082014-10-27 01:06:24 -0400792 certMsg, ok := msg.(*certificateMsg)
David Benjamin75051442016-07-01 18:58:51 -0400793 if !ok {
David Benjamin48cae082014-10-27 01:06:24 -0400794 c.sendAlert(alertUnexpectedMessage)
795 return unexpectedMessageError(certMsg, msg)
796 }
797 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700798
David Benjamin75051442016-07-01 18:58:51 -0400799 if err := hs.verifyCertificates(certMsg); err != nil {
800 return err
David Benjamin48cae082014-10-27 01:06:24 -0400801 }
David Benjamin75051442016-07-01 18:58:51 -0400802 leaf = c.peerCertificates[0]
David Benjamin48cae082014-10-27 01:06:24 -0400803 }
Adam Langley95c29f32014-06-20 12:00:00 -0700804
Nick Harperb3d51be2016-07-01 11:43:18 -0400805 if hs.serverHello.extensions.ocspStapling {
David Benjamin48cae082014-10-27 01:06:24 -0400806 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700807 if err != nil {
808 return err
809 }
810 cs, ok := msg.(*certificateStatusMsg)
811 if !ok {
812 c.sendAlert(alertUnexpectedMessage)
813 return unexpectedMessageError(cs, msg)
814 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400815 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700816
817 if cs.statusType == statusTypeOCSP {
818 c.ocspResponse = cs.response
819 }
820 }
821
David Benjamin48cae082014-10-27 01:06:24 -0400822 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700823 if err != nil {
824 return err
825 }
826
827 keyAgreement := hs.suite.ka(c.vers)
828
829 skx, ok := msg.(*serverKeyExchangeMsg)
830 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -0400831 hs.writeServerHash(skx.marshal())
David Benjamin48cae082014-10-27 01:06:24 -0400832 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
Adam Langley95c29f32014-06-20 12:00:00 -0700833 if err != nil {
834 c.sendAlert(alertUnexpectedMessage)
835 return err
836 }
Steven Valdez5440fe02016-07-18 12:40:30 -0400837 if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
838 c.curveID = ecdhe.curveID
839 }
Adam Langley95c29f32014-06-20 12:00:00 -0700840
Nick Harper60edffd2016-06-21 15:19:24 -0700841 c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()
842
Adam Langley95c29f32014-06-20 12:00:00 -0700843 msg, err = c.readHandshake()
844 if err != nil {
845 return err
846 }
847 }
848
849 var chainToSend *Certificate
850 var certRequested bool
851 certReq, ok := msg.(*certificateRequestMsg)
852 if ok {
853 certRequested = true
David Benjamin7a41d372016-07-09 11:21:54 -0700854 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
855 certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
856 }
Adam Langley95c29f32014-06-20 12:00:00 -0700857
David Benjamin83c0bc92014-08-04 01:23:53 -0400858 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700859
David Benjamina6f82632016-07-01 18:44:02 -0400860 chainToSend, err = selectClientCertificate(c, certReq)
861 if err != nil {
862 return err
Adam Langley95c29f32014-06-20 12:00:00 -0700863 }
864
865 msg, err = c.readHandshake()
866 if err != nil {
867 return err
868 }
869 }
870
871 shd, ok := msg.(*serverHelloDoneMsg)
872 if !ok {
873 c.sendAlert(alertUnexpectedMessage)
874 return unexpectedMessageError(shd, msg)
875 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400876 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700877
878 // If the server requested a certificate then we have to send a
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500879 // Certificate message in TLS, even if it's empty because we don't have
880 // a certificate to send. In SSL 3.0, skip the message and send a
881 // no_certificate warning alert.
Adam Langley95c29f32014-06-20 12:00:00 -0700882 if certRequested {
David Benjamin0b7ca7d2016-03-10 15:44:22 -0500883 if c.vers == VersionSSL30 && chainToSend == nil {
884 c.sendAlert(alertNoCertficate)
885 } else if !c.config.Bugs.SkipClientCertificate {
886 certMsg := new(certificateMsg)
887 if chainToSend != nil {
888 certMsg.certificates = chainToSend.Certificate
889 }
890 hs.writeClientHash(certMsg.marshal())
891 c.writeRecord(recordTypeHandshake, certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700892 }
Adam Langley95c29f32014-06-20 12:00:00 -0700893 }
894
David Benjamin48cae082014-10-27 01:06:24 -0400895 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
Adam Langley95c29f32014-06-20 12:00:00 -0700896 if err != nil {
897 c.sendAlert(alertInternalError)
898 return err
899 }
900 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400901 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -0400902 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -0400903 }
Adam Langley95c29f32014-06-20 12:00:00 -0700904 c.writeRecord(recordTypeHandshake, ckx.marshal())
905 }
906
Nick Harperb3d51be2016-07-01 11:43:18 -0400907 if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
Adam Langley75712922014-10-10 16:23:43 -0700908 hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
909 c.extendedMasterSecret = true
910 } else {
911 if c.config.Bugs.RequireExtendedMasterSecret {
912 return errors.New("tls: extended master secret required but not supported by peer")
913 }
914 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
915 }
David Benjamine098ec22014-08-27 23:13:20 -0400916
Adam Langley95c29f32014-06-20 12:00:00 -0700917 if chainToSend != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700918 certVerify := &certificateVerifyMsg{
Nick Harper60edffd2016-06-21 15:19:24 -0700919 hasSignatureAlgorithm: c.vers >= VersionTLS12,
Adam Langley95c29f32014-06-20 12:00:00 -0700920 }
921
David Benjamin72dc7832015-03-16 17:49:43 -0400922 // Determine the hash to sign.
Nick Harper60edffd2016-06-21 15:19:24 -0700923 privKey := c.config.Certificates[0].PrivateKey
David Benjamin72dc7832015-03-16 17:49:43 -0400924
Nick Harper60edffd2016-06-21 15:19:24 -0700925 if certVerify.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -0700926 certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
Nick Harper60edffd2016-06-21 15:19:24 -0700927 if err != nil {
928 c.sendAlert(alertInternalError)
929 return err
Adam Langley95c29f32014-06-20 12:00:00 -0700930 }
Nick Harper60edffd2016-06-21 15:19:24 -0700931 }
932
933 if c.vers > VersionSSL30 {
David Benjamin5208fd42016-07-13 21:43:25 -0400934 certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
David Benjamina95e9f32016-07-08 16:28:04 -0700935 if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
936 certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
937 }
Nick Harper60edffd2016-06-21 15:19:24 -0700938 } else {
939 // SSL 3.0's client certificate construction is
940 // incompatible with signatureAlgorithm.
941 rsaKey, ok := privKey.(*rsa.PrivateKey)
942 if !ok {
943 err = errors.New("unsupported signature type for client certificate")
944 } else {
945 digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
David Benjamin5208fd42016-07-13 21:43:25 -0400946 if c.config.Bugs.InvalidSignature {
Nick Harper60edffd2016-06-21 15:19:24 -0700947 digest[0] ^= 0x80
948 }
949 certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
950 }
Adam Langley95c29f32014-06-20 12:00:00 -0700951 }
952 if err != nil {
953 c.sendAlert(alertInternalError)
954 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
955 }
Adam Langley95c29f32014-06-20 12:00:00 -0700956
David Benjamin83c0bc92014-08-04 01:23:53 -0400957 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700958 c.writeRecord(recordTypeHandshake, certVerify.marshal())
959 }
David Benjamin82261be2016-07-07 14:32:50 -0700960 // flushHandshake will be called in sendFinished.
Adam Langley95c29f32014-06-20 12:00:00 -0700961
David Benjamine098ec22014-08-27 23:13:20 -0400962 hs.finishedHash.discardHandshakeBuffer()
963
Adam Langley95c29f32014-06-20 12:00:00 -0700964 return nil
965}
966
David Benjamin75051442016-07-01 18:58:51 -0400967func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
968 c := hs.c
969
970 if len(certMsg.certificates) == 0 {
971 c.sendAlert(alertIllegalParameter)
972 return errors.New("tls: no certificates sent")
973 }
974
975 certs := make([]*x509.Certificate, len(certMsg.certificates))
976 for i, asn1Data := range certMsg.certificates {
977 cert, err := x509.ParseCertificate(asn1Data)
978 if err != nil {
979 c.sendAlert(alertBadCertificate)
980 return errors.New("tls: failed to parse certificate from server: " + err.Error())
981 }
982 certs[i] = cert
983 }
984
985 if !c.config.InsecureSkipVerify {
986 opts := x509.VerifyOptions{
987 Roots: c.config.RootCAs,
988 CurrentTime: c.config.time(),
989 DNSName: c.config.ServerName,
990 Intermediates: x509.NewCertPool(),
991 }
992
993 for i, cert := range certs {
994 if i == 0 {
995 continue
996 }
997 opts.Intermediates.AddCert(cert)
998 }
999 var err error
1000 c.verifiedChains, err = certs[0].Verify(opts)
1001 if err != nil {
1002 c.sendAlert(alertBadCertificate)
1003 return err
1004 }
1005 }
1006
1007 switch certs[0].PublicKey.(type) {
1008 case *rsa.PublicKey, *ecdsa.PublicKey:
1009 break
1010 default:
1011 c.sendAlert(alertUnsupportedCertificate)
1012 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
1013 }
1014
1015 c.peerCertificates = certs
1016 return nil
1017}
1018
Adam Langley95c29f32014-06-20 12:00:00 -07001019func (hs *clientHandshakeState) establishKeys() error {
1020 c := hs.c
1021
1022 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
Nick Harper1fd39d82016-06-14 18:14:35 -07001023 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 -07001024 var clientCipher, serverCipher interface{}
1025 var clientHash, serverHash macFunction
1026 if hs.suite.cipher != nil {
1027 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
1028 clientHash = hs.suite.mac(c.vers, clientMAC)
1029 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
1030 serverHash = hs.suite.mac(c.vers, serverMAC)
1031 } else {
Nick Harper1fd39d82016-06-14 18:14:35 -07001032 clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
1033 serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
Adam Langley95c29f32014-06-20 12:00:00 -07001034 }
1035
1036 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
1037 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
1038 return nil
1039}
1040
David Benjamin75101402016-07-01 13:40:23 -04001041func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
1042 c := hs.c
1043
David Benjamin8d315d72016-07-18 01:03:18 +02001044 if c.vers < VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001045 if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
1046 return errors.New("tls: renegotiation extension missing")
1047 }
David Benjamin75101402016-07-01 13:40:23 -04001048
Nick Harperb41d2e42016-07-01 17:50:32 -04001049 if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
1050 var expectedRenegInfo []byte
1051 expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
1052 expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
1053 if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
1054 c.sendAlert(alertHandshakeFailure)
1055 return fmt.Errorf("tls: renegotiation mismatch")
1056 }
David Benjamin75101402016-07-01 13:40:23 -04001057 }
David Benjamincea0ab42016-07-14 12:33:14 -04001058 } else if serverExtensions.secureRenegotiation != nil {
1059 return errors.New("tls: renegotiation info sent in TLS 1.3")
David Benjamin75101402016-07-01 13:40:23 -04001060 }
1061
1062 if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
1063 if serverExtensions.customExtension != *expected {
1064 return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
1065 }
1066 }
1067
1068 clientDidNPN := hs.hello.nextProtoNeg
1069 clientDidALPN := len(hs.hello.alpnProtocols) > 0
1070 serverHasNPN := serverExtensions.nextProtoNeg
1071 serverHasALPN := len(serverExtensions.alpnProtocol) > 0
1072
1073 if !clientDidNPN && serverHasNPN {
1074 c.sendAlert(alertHandshakeFailure)
1075 return errors.New("server advertised unrequested NPN extension")
1076 }
1077
1078 if !clientDidALPN && serverHasALPN {
1079 c.sendAlert(alertHandshakeFailure)
1080 return errors.New("server advertised unrequested ALPN extension")
1081 }
1082
1083 if serverHasNPN && serverHasALPN {
1084 c.sendAlert(alertHandshakeFailure)
1085 return errors.New("server advertised both NPN and ALPN extensions")
1086 }
1087
1088 if serverHasALPN {
1089 c.clientProtocol = serverExtensions.alpnProtocol
1090 c.clientProtocolFallback = false
1091 c.usedALPN = true
1092 }
1093
David Benjamin8d315d72016-07-18 01:03:18 +02001094 if serverHasNPN && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001095 c.sendAlert(alertHandshakeFailure)
1096 return errors.New("server advertised NPN over TLS 1.3")
1097 }
1098
David Benjamin75101402016-07-01 13:40:23 -04001099 if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
1100 c.sendAlert(alertHandshakeFailure)
1101 return errors.New("server advertised unrequested Channel ID extension")
1102 }
1103
David Benjamin8d315d72016-07-18 01:03:18 +02001104 if serverExtensions.channelIDRequested && c.vers >= VersionTLS13 {
Nick Harperb41d2e42016-07-01 17:50:32 -04001105 c.sendAlert(alertHandshakeFailure)
1106 return errors.New("server advertised Channel ID over TLS 1.3")
1107 }
1108
David Benjamin8d315d72016-07-18 01:03:18 +02001109 if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
David Benjamine9077652016-07-13 21:02:08 -04001110 return errors.New("tls: server advertised extended master secret over TLS 1.3")
1111 }
1112
David Benjamin8d315d72016-07-18 01:03:18 +02001113 if serverExtensions.ticketSupported && c.vers >= VersionTLS13 {
Steven Valdez143e8b32016-07-11 13:19:03 -04001114 return errors.New("tls: server advertised ticket extension over TLS 1.3")
1115 }
1116
David Benjamin75101402016-07-01 13:40:23 -04001117 if serverExtensions.srtpProtectionProfile != 0 {
1118 if serverExtensions.srtpMasterKeyIdentifier != "" {
1119 return errors.New("tls: server selected SRTP MKI value")
1120 }
1121
1122 found := false
1123 for _, p := range c.config.SRTPProtectionProfiles {
1124 if p == serverExtensions.srtpProtectionProfile {
1125 found = true
1126 break
1127 }
1128 }
1129 if !found {
1130 return errors.New("tls: server advertised unsupported SRTP profile")
1131 }
1132
1133 c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
1134 }
1135
1136 return nil
1137}
1138
Adam Langley95c29f32014-06-20 12:00:00 -07001139func (hs *clientHandshakeState) serverResumedSession() bool {
1140 // If the server responded with the same sessionId then it means the
1141 // sessionTicket is being used to resume a TLS session.
1142 return hs.session != nil && hs.hello.sessionId != nil &&
1143 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
1144}
1145
1146func (hs *clientHandshakeState) processServerHello() (bool, error) {
1147 c := hs.c
1148
Adam Langley95c29f32014-06-20 12:00:00 -07001149 if hs.serverResumedSession() {
David Benjamin4b27d9f2015-05-12 22:42:52 -04001150 // For test purposes, assert that the server never accepts the
1151 // resumption offer on renegotiation.
1152 if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
1153 return false, errors.New("tls: server resumed session on renegotiation")
1154 }
1155
Nick Harperb3d51be2016-07-01 11:43:18 -04001156 if hs.serverHello.extensions.sctList != nil {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001157 return false, errors.New("tls: server sent SCT extension on session resumption")
1158 }
1159
Nick Harperb3d51be2016-07-01 11:43:18 -04001160 if hs.serverHello.extensions.ocspStapling {
Paul Lietar62be8ac2015-09-16 10:03:30 +01001161 return false, errors.New("tls: server sent OCSP extension on session resumption")
1162 }
1163
Adam Langley95c29f32014-06-20 12:00:00 -07001164 // Restore masterSecret and peerCerts from previous state
1165 hs.masterSecret = hs.session.masterSecret
1166 c.peerCertificates = hs.session.serverCertificates
Adam Langley75712922014-10-10 16:23:43 -07001167 c.extendedMasterSecret = hs.session.extendedMasterSecret
Paul Lietar62be8ac2015-09-16 10:03:30 +01001168 c.sctList = hs.session.sctList
1169 c.ocspResponse = hs.session.ocspResponse
David Benjamine098ec22014-08-27 23:13:20 -04001170 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -07001171 return true, nil
1172 }
Paul Lietar62be8ac2015-09-16 10:03:30 +01001173
Nick Harperb3d51be2016-07-01 11:43:18 -04001174 if hs.serverHello.extensions.sctList != nil {
1175 c.sctList = hs.serverHello.extensions.sctList
Paul Lietar62be8ac2015-09-16 10:03:30 +01001176 }
1177
Adam Langley95c29f32014-06-20 12:00:00 -07001178 return false, nil
1179}
1180
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001181func (hs *clientHandshakeState) readFinished(out []byte) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001182 c := hs.c
1183
1184 c.readRecord(recordTypeChangeCipherSpec)
1185 if err := c.in.error(); err != nil {
1186 return err
1187 }
1188
1189 msg, err := c.readHandshake()
1190 if err != nil {
1191 return err
1192 }
1193 serverFinished, ok := msg.(*finishedMsg)
1194 if !ok {
1195 c.sendAlert(alertUnexpectedMessage)
1196 return unexpectedMessageError(serverFinished, msg)
1197 }
1198
David Benjaminf3ec83d2014-07-21 22:42:34 -04001199 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
1200 verify := hs.finishedHash.serverSum(hs.masterSecret)
1201 if len(verify) != len(serverFinished.verifyData) ||
1202 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
1203 c.sendAlert(alertHandshakeFailure)
1204 return errors.New("tls: server's Finished message was incorrect")
1205 }
Adam Langley95c29f32014-06-20 12:00:00 -07001206 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001207 c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001208 copy(out, serverFinished.verifyData)
David Benjamin83c0bc92014-08-04 01:23:53 -04001209 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -07001210 return nil
1211}
1212
1213func (hs *clientHandshakeState) readSessionTicket() error {
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001214 c := hs.c
1215
1216 // Create a session with no server identifier. Either a
1217 // session ID or session ticket will be attached.
1218 session := &ClientSessionState{
1219 vers: c.vers,
1220 cipherSuite: hs.suite.id,
1221 masterSecret: hs.masterSecret,
1222 handshakeHash: hs.finishedHash.server.Sum(nil),
1223 serverCertificates: c.peerCertificates,
Paul Lietar62be8ac2015-09-16 10:03:30 +01001224 sctList: c.sctList,
1225 ocspResponse: c.ocspResponse,
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001226 }
1227
Nick Harperb3d51be2016-07-01 11:43:18 -04001228 if !hs.serverHello.extensions.ticketSupported {
David Benjamind98452d2015-06-16 14:16:23 -04001229 if c.config.Bugs.ExpectNewTicket {
1230 return errors.New("tls: expected new ticket")
1231 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001232 if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
1233 session.sessionId = hs.serverHello.sessionId
1234 hs.session = session
1235 }
Adam Langley95c29f32014-06-20 12:00:00 -07001236 return nil
1237 }
1238
David Benjaminc7ce9772015-10-09 19:32:41 -04001239 if c.vers == VersionSSL30 {
1240 return errors.New("tls: negotiated session tickets in SSL 3.0")
1241 }
1242
Adam Langley95c29f32014-06-20 12:00:00 -07001243 msg, err := c.readHandshake()
1244 if err != nil {
1245 return err
1246 }
1247 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
1248 if !ok {
1249 c.sendAlert(alertUnexpectedMessage)
1250 return unexpectedMessageError(sessionTicketMsg, msg)
1251 }
Adam Langley95c29f32014-06-20 12:00:00 -07001252
David Benjaminfe8eb9a2014-11-17 03:19:02 -05001253 session.sessionTicket = sessionTicketMsg.ticket
1254 hs.session = session
Adam Langley95c29f32014-06-20 12:00:00 -07001255
David Benjamind30a9902014-08-24 01:44:23 -04001256 hs.writeServerHash(sessionTicketMsg.marshal())
1257
Adam Langley95c29f32014-06-20 12:00:00 -07001258 return nil
1259}
1260
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001261func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -07001262 c := hs.c
1263
David Benjamin0b8d5da2016-07-15 00:39:56 -04001264 var postCCSMsgs [][]byte
David Benjamin83c0bc92014-08-04 01:23:53 -04001265 seqno := hs.c.sendHandshakeSeq
Nick Harperb3d51be2016-07-01 11:43:18 -04001266 if hs.serverHello.extensions.nextProtoNeg {
Adam Langley95c29f32014-06-20 12:00:00 -07001267 nextProto := new(nextProtoMsg)
Nick Harperb3d51be2016-07-01 11:43:18 -04001268 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
Adam Langley95c29f32014-06-20 12:00:00 -07001269 nextProto.proto = proto
1270 c.clientProtocol = proto
1271 c.clientProtocolFallback = fallback
1272
David Benjamin86271ee2014-07-21 16:14:03 -04001273 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -04001274 hs.writeHash(nextProtoBytes, seqno)
1275 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001276 postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
Adam Langley95c29f32014-06-20 12:00:00 -07001277 }
1278
Nick Harperb3d51be2016-07-01 11:43:18 -04001279 if hs.serverHello.extensions.channelIDRequested {
David Benjamin24599a82016-06-30 18:56:53 -04001280 channelIDMsg := new(channelIDMsg)
David Benjamind30a9902014-08-24 01:44:23 -04001281 if c.config.ChannelID.Curve != elliptic.P256() {
1282 return fmt.Errorf("tls: Channel ID is not on P-256.")
1283 }
1284 var resumeHash []byte
1285 if isResume {
1286 resumeHash = hs.session.handshakeHash
1287 }
1288 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
1289 if err != nil {
1290 return err
1291 }
1292 channelID := make([]byte, 128)
1293 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
1294 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
1295 writeIntPadded(channelID[64:96], r)
1296 writeIntPadded(channelID[96:128], s)
David Benjamin24599a82016-06-30 18:56:53 -04001297 channelIDMsg.channelID = channelID
David Benjamind30a9902014-08-24 01:44:23 -04001298
1299 c.channelID = &c.config.ChannelID.PublicKey
1300
David Benjamin24599a82016-06-30 18:56:53 -04001301 channelIDMsgBytes := channelIDMsg.marshal()
1302 hs.writeHash(channelIDMsgBytes, seqno)
David Benjamind30a9902014-08-24 01:44:23 -04001303 seqno++
David Benjamin0b8d5da2016-07-15 00:39:56 -04001304 postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
David Benjamind30a9902014-08-24 01:44:23 -04001305 }
1306
Adam Langley95c29f32014-06-20 12:00:00 -07001307 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -04001308 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
1309 finished.verifyData = hs.finishedHash.clientSum(nil)
1310 } else {
1311 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
1312 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -07001313 copy(out, finished.verifyData)
David Benjamin513f0ea2015-04-02 19:33:31 -04001314 if c.config.Bugs.BadFinished {
1315 finished.verifyData[0]++
1316 }
Adam Langley2ae77d22014-10-28 17:29:33 -07001317 c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
David Benjamin83f90402015-01-27 01:09:43 -05001318 hs.finishedBytes = finished.marshal()
1319 hs.writeHash(hs.finishedBytes, seqno)
David Benjamin0b8d5da2016-07-15 00:39:56 -04001320 postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
David Benjamin86271ee2014-07-21 16:14:03 -04001321
1322 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001323 c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
1324 postCCSMsgs[0] = postCCSMsgs[0][5:]
David Benjamin61672812016-07-14 23:10:43 -04001325 } else if c.config.Bugs.SendUnencryptedFinished {
David Benjamin0b8d5da2016-07-15 00:39:56 -04001326 c.writeRecord(recordTypeHandshake, postCCSMsgs[0])
1327 postCCSMsgs = postCCSMsgs[1:]
David Benjamin86271ee2014-07-21 16:14:03 -04001328 }
David Benjamin582ba042016-07-07 12:33:25 -07001329 c.flushHandshake()
David Benjamin86271ee2014-07-21 16:14:03 -04001330
1331 if !c.config.Bugs.SkipChangeCipherSpec &&
1332 c.config.Bugs.EarlyChangeCipherSpec == 0 {
David Benjamin8411b242015-11-26 12:07:28 -05001333 ccs := []byte{1}
1334 if c.config.Bugs.BadChangeCipherSpec != nil {
1335 ccs = c.config.Bugs.BadChangeCipherSpec
1336 }
1337 c.writeRecord(recordTypeChangeCipherSpec, ccs)
David Benjamin86271ee2014-07-21 16:14:03 -04001338 }
1339
David Benjamin4189bd92015-01-25 23:52:39 -05001340 if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
1341 c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
1342 }
David Benjamindc3da932015-03-12 15:09:02 -04001343 if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
1344 c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
1345 return errors.New("tls: simulating post-CCS alert")
1346 }
David Benjamin4189bd92015-01-25 23:52:39 -05001347
David Benjamin0b8d5da2016-07-15 00:39:56 -04001348 if !c.config.Bugs.SkipFinished {
1349 for _, msg := range postCCSMsgs {
1350 c.writeRecord(recordTypeHandshake, msg)
1351 }
David Benjamin02edcd02016-07-27 17:40:37 -04001352
1353 if c.config.Bugs.SendExtraFinished {
1354 c.writeRecord(recordTypeHandshake, finished.marshal())
1355 }
1356
David Benjamin582ba042016-07-07 12:33:25 -07001357 c.flushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -05001358 }
Adam Langley95c29f32014-06-20 12:00:00 -07001359 return nil
1360}
1361
David Benjamin83c0bc92014-08-04 01:23:53 -04001362func (hs *clientHandshakeState) writeClientHash(msg []byte) {
1363 // writeClientHash is called before writeRecord.
1364 hs.writeHash(msg, hs.c.sendHandshakeSeq)
1365}
1366
1367func (hs *clientHandshakeState) writeServerHash(msg []byte) {
1368 // writeServerHash is called after readHandshake.
1369 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
1370}
1371
1372func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
1373 if hs.c.isDTLS {
1374 // This is somewhat hacky. DTLS hashes a slightly different format.
1375 // First, the TLS header.
1376 hs.finishedHash.Write(msg[:4])
1377 // Then the sequence number and reassembled fragment offset (always 0).
1378 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
1379 // Then the reassembled fragment (always equal to the message length).
1380 hs.finishedHash.Write(msg[1:4])
1381 // And then the message body.
1382 hs.finishedHash.Write(msg[4:])
1383 } else {
1384 hs.finishedHash.Write(msg)
1385 }
1386}
1387
David Benjamina6f82632016-07-01 18:44:02 -04001388// selectClientCertificate selects a certificate for use with the given
1389// certificate, or none if none match. It may return a particular certificate or
1390// nil on success, or an error on internal error.
1391func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
1392 // RFC 4346 on the certificateAuthorities field:
1393 // A list of the distinguished names of acceptable certificate
1394 // authorities. These distinguished names may specify a desired
1395 // distinguished name for a root CA or for a subordinate CA; thus, this
1396 // message can be used to describe both known roots and a desired
1397 // authorization space. If the certificate_authorities list is empty
1398 // then the client MAY send any certificate of the appropriate
1399 // ClientCertificateType, unless there is some external arrangement to
1400 // the contrary.
1401
1402 var rsaAvail, ecdsaAvail bool
Nick Harperb41d2e42016-07-01 17:50:32 -04001403 if !certReq.hasRequestContext {
1404 for _, certType := range certReq.certificateTypes {
1405 switch certType {
1406 case CertTypeRSASign:
1407 rsaAvail = true
1408 case CertTypeECDSASign:
1409 ecdsaAvail = true
1410 }
David Benjamina6f82632016-07-01 18:44:02 -04001411 }
1412 }
1413
1414 // We need to search our list of client certs for one
1415 // where SignatureAlgorithm is RSA and the Issuer is in
1416 // certReq.certificateAuthorities
1417findCert:
1418 for i, chain := range c.config.Certificates {
Nick Harperb41d2e42016-07-01 17:50:32 -04001419 if !certReq.hasRequestContext && !rsaAvail && !ecdsaAvail {
David Benjamina6f82632016-07-01 18:44:02 -04001420 continue
1421 }
1422
1423 // Ensure the private key supports one of the advertised
1424 // signature algorithms.
1425 if certReq.hasSignatureAlgorithm {
David Benjamin0a8deb22016-07-09 21:02:01 -07001426 if _, err := selectSignatureAlgorithm(c.vers, chain.PrivateKey, c.config, certReq.signatureAlgorithms); err != nil {
David Benjamina6f82632016-07-01 18:44:02 -04001427 continue
1428 }
1429 }
1430
1431 for j, cert := range chain.Certificate {
1432 x509Cert := chain.Leaf
1433 // parse the certificate if this isn't the leaf
1434 // node, or if chain.Leaf was nil
1435 if j != 0 || x509Cert == nil {
1436 var err error
1437 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
1438 c.sendAlert(alertInternalError)
1439 return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
1440 }
1441 }
1442
Nick Harperb41d2e42016-07-01 17:50:32 -04001443 if !certReq.hasRequestContext {
1444 switch {
1445 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
1446 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
1447 default:
1448 continue findCert
1449 }
David Benjamina6f82632016-07-01 18:44:02 -04001450 }
1451
1452 if len(certReq.certificateAuthorities) == 0 {
1453 // They gave us an empty list, so just take the
1454 // first certificate of valid type from
1455 // c.config.Certificates.
1456 return &chain, nil
1457 }
1458
1459 for _, ca := range certReq.certificateAuthorities {
1460 if bytes.Equal(x509Cert.RawIssuer, ca) {
1461 return &chain, nil
1462 }
1463 }
1464 }
1465 }
1466
1467 return nil, nil
1468}
1469
Adam Langley95c29f32014-06-20 12:00:00 -07001470// clientSessionCacheKey returns a key used to cache sessionTickets that could
1471// be used to resume previously negotiated TLS sessions with a server.
1472func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
1473 if len(config.ServerName) > 0 {
1474 return config.ServerName
1475 }
1476 return serverAddr.String()
1477}
1478
David Benjaminfa055a22014-09-15 16:51:51 -04001479// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
1480// given list of possible protocols and a list of the preference order. The
1481// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -07001482// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -04001483func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
1484 for _, s := range preferenceProtos {
1485 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -07001486 if s == c {
1487 return s, false
1488 }
1489 }
1490 }
1491
David Benjaminfa055a22014-09-15 16:51:51 -04001492 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -07001493}
David Benjamind30a9902014-08-24 01:44:23 -04001494
1495// writeIntPadded writes x into b, padded up with leading zeros as
1496// needed.
1497func writeIntPadded(b []byte, x *big.Int) {
1498 for i := range b {
1499 b[i] = 0
1500 }
1501 xb := x.Bytes()
1502 copy(b[len(b)-len(xb):], xb)
1503}