blob: bc10fe77d1625ef94f15ea8c0073d77f18fe4d5d [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
5package main
6
7import (
8 "bytes"
9 "crypto/ecdsa"
David Benjamind30a9902014-08-24 01:44:23 -040010 "crypto/elliptic"
Adam Langley95c29f32014-06-20 12:00:00 -070011 "crypto/rsa"
12 "crypto/subtle"
13 "crypto/x509"
14 "encoding/asn1"
15 "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
29 masterSecret []byte
30 session *ClientSessionState
31 finishedBytes []byte
Adam Langley95c29f32014-06-20 12:00:00 -070032}
33
34func (c *Conn) clientHandshake() error {
35 if c.config == nil {
36 c.config = defaultConfig()
37 }
38
39 if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify {
40 return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config")
41 }
42
David Benjamin83c0bc92014-08-04 01:23:53 -040043 c.sendHandshakeSeq = 0
44 c.recvHandshakeSeq = 0
45
David Benjaminfa055a22014-09-15 16:51:51 -040046 nextProtosLength := 0
47 for _, proto := range c.config.NextProtos {
Adam Langleyefb0e162015-07-09 11:35:04 -070048 if l := len(proto); l > 255 {
David Benjaminfa055a22014-09-15 16:51:51 -040049 return errors.New("tls: invalid NextProtos value")
50 } else {
51 nextProtosLength += 1 + l
52 }
53 }
54 if nextProtosLength > 0xffff {
55 return errors.New("tls: NextProtos values too large")
56 }
57
Adam Langley95c29f32014-06-20 12:00:00 -070058 hello := &clientHelloMsg{
David Benjaminca6c8262014-11-15 19:06:08 -050059 isDTLS: c.isDTLS,
60 vers: c.config.maxVersion(),
61 compressionMethods: []uint8{compressionNone},
62 random: make([]byte, 32),
63 ocspStapling: true,
64 serverName: c.config.ServerName,
65 supportedCurves: c.config.curvePreferences(),
66 supportedPoints: []uint8{pointFormatUncompressed},
67 nextProtoNeg: len(c.config.NextProtos) > 0,
68 secureRenegotiation: []byte{},
69 alpnProtocols: c.config.NextProtos,
70 duplicateExtension: c.config.Bugs.DuplicateExtension,
71 channelIDSupported: c.config.ChannelID != nil,
72 npnLast: c.config.Bugs.SwapNPNAndALPN,
73 extendedMasterSecret: c.config.maxVersion() >= VersionTLS10,
74 srtpProtectionProfiles: c.config.SRTPProtectionProfiles,
75 srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
Adam Langley95c29f32014-06-20 12:00:00 -070076 }
77
David Benjamin98e882e2014-08-08 13:24:34 -040078 if c.config.Bugs.SendClientVersion != 0 {
79 hello.vers = c.config.Bugs.SendClientVersion
80 }
81
Adam Langley75712922014-10-10 16:23:43 -070082 if c.config.Bugs.NoExtendedMasterSecret {
83 hello.extendedMasterSecret = false
84 }
85
David Benjamin55a43642015-04-20 14:45:55 -040086 if c.config.Bugs.NoSupportedCurves {
87 hello.supportedCurves = nil
88 }
89
Adam Langley2ae77d22014-10-28 17:29:33 -070090 if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
91 if c.config.Bugs.BadRenegotiationInfo {
92 hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
93 hello.secureRenegotiation[0] ^= 0x80
94 } else {
95 hello.secureRenegotiation = c.clientVerify
96 }
97 }
98
David Benjaminca6554b2014-11-08 12:31:52 -050099 if c.config.Bugs.NoRenegotiationInfo {
100 hello.secureRenegotiation = nil
101 }
102
Adam Langley95c29f32014-06-20 12:00:00 -0700103 possibleCipherSuites := c.config.cipherSuites()
104 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
105
106NextCipherSuite:
107 for _, suiteId := range possibleCipherSuites {
108 for _, suite := range cipherSuites {
109 if suite.id != suiteId {
110 continue
111 }
112 // Don't advertise TLS 1.2-only cipher suites unless
113 // we're attempting TLS 1.2.
114 if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
115 continue
116 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400117 // Don't advertise non-DTLS cipher suites on DTLS.
David Benjamin0fa40122015-05-30 17:13:12 -0400118 if c.isDTLS && suite.flags&suiteNoDTLS != 0 && !c.config.Bugs.EnableAllCiphersInDTLS {
David Benjamin83c0bc92014-08-04 01:23:53 -0400119 continue
120 }
Adam Langley95c29f32014-06-20 12:00:00 -0700121 hello.cipherSuites = append(hello.cipherSuites, suiteId)
122 continue NextCipherSuite
123 }
124 }
125
Adam Langley5021b222015-06-12 18:27:58 -0700126 if c.config.Bugs.SendRenegotiationSCSV {
127 hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
128 }
129
David Benjaminbef270a2014-08-02 04:22:02 -0400130 if c.config.Bugs.SendFallbackSCSV {
131 hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
132 }
133
Adam Langley95c29f32014-06-20 12:00:00 -0700134 _, err := io.ReadFull(c.config.rand(), hello.random)
135 if err != nil {
136 c.sendAlert(alertInternalError)
137 return errors.New("tls: short read from Rand: " + err.Error())
138 }
139
David Benjamin44d3eed2015-05-21 01:29:55 -0400140 if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes {
David Benjamin000800a2014-11-14 01:43:59 -0500141 hello.signatureAndHashes = c.config.signatureAndHashesForClient()
Adam Langley95c29f32014-06-20 12:00:00 -0700142 }
143
144 var session *ClientSessionState
145 var cacheKey string
146 sessionCache := c.config.ClientSessionCache
Adam Langley95c29f32014-06-20 12:00:00 -0700147
148 if sessionCache != nil {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500149 hello.ticketSupported = !c.config.SessionTicketsDisabled
Adam Langley95c29f32014-06-20 12:00:00 -0700150
151 // Try to resume a previously negotiated TLS session, if
152 // available.
153 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
154 candidateSession, ok := sessionCache.Get(cacheKey)
155 if ok {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500156 ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
157
Adam Langley95c29f32014-06-20 12:00:00 -0700158 // Check that the ciphersuite/version used for the
159 // previous session are still valid.
160 cipherSuiteOk := false
161 for _, id := range hello.cipherSuites {
162 if id == candidateSession.cipherSuite {
163 cipherSuiteOk = true
164 break
165 }
166 }
167
168 versOk := candidateSession.vers >= c.config.minVersion() &&
169 candidateSession.vers <= c.config.maxVersion()
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500170 if ticketOk && versOk && cipherSuiteOk {
Adam Langley95c29f32014-06-20 12:00:00 -0700171 session = candidateSession
172 }
173 }
174 }
175
176 if session != nil {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500177 if session.sessionTicket != nil {
178 hello.sessionTicket = session.sessionTicket
179 if c.config.Bugs.CorruptTicket {
180 hello.sessionTicket = make([]byte, len(session.sessionTicket))
181 copy(hello.sessionTicket, session.sessionTicket)
182 if len(hello.sessionTicket) > 0 {
183 offset := 40
184 if offset > len(hello.sessionTicket) {
185 offset = len(hello.sessionTicket) - 1
186 }
187 hello.sessionTicket[offset] ^= 0x40
Adam Langley38311732014-10-16 19:04:35 -0700188 }
Adam Langley38311732014-10-16 19:04:35 -0700189 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500190 // A random session ID is used to detect when the
191 // server accepted the ticket and is resuming a session
192 // (see RFC 5077).
193 sessionIdLen := 16
194 if c.config.Bugs.OversizedSessionId {
195 sessionIdLen = 33
196 }
197 hello.sessionId = make([]byte, sessionIdLen)
198 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
199 c.sendAlert(alertInternalError)
200 return errors.New("tls: short read from Rand: " + err.Error())
201 }
202 } else {
203 hello.sessionId = session.sessionId
Adam Langley95c29f32014-06-20 12:00:00 -0700204 }
205 }
206
David Benjamind86c7672014-08-02 04:07:12 -0400207 var helloBytes []byte
208 if c.config.Bugs.SendV2ClientHello {
David Benjamin94d701b2014-11-30 13:54:41 -0500209 // Test that the peer left-pads random.
210 hello.random[0] = 0
David Benjamind86c7672014-08-02 04:07:12 -0400211 v2Hello := &v2ClientHelloMsg{
212 vers: hello.vers,
213 cipherSuites: hello.cipherSuites,
214 // No session resumption for V2ClientHello.
215 sessionId: nil,
David Benjamin94d701b2014-11-30 13:54:41 -0500216 challenge: hello.random[1:],
David Benjamind86c7672014-08-02 04:07:12 -0400217 }
218 helloBytes = v2Hello.marshal()
219 c.writeV2Record(helloBytes)
220 } else {
221 helloBytes = hello.marshal()
222 c.writeRecord(recordTypeHandshake, helloBytes)
223 }
David Benjamina4e6d482015-03-02 19:10:53 -0500224 c.dtlsFlushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700225
David Benjamin83f90402015-01-27 01:09:43 -0500226 if err := c.simulatePacketLoss(nil); err != nil {
227 return err
228 }
Adam Langley95c29f32014-06-20 12:00:00 -0700229 msg, err := c.readHandshake()
230 if err != nil {
231 return err
232 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400233
234 if c.isDTLS {
235 helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
236 if ok {
David Benjamin8bc38f52014-08-16 12:07:27 -0400237 if helloVerifyRequest.vers != VersionTLS10 {
238 // Per RFC 6347, the version field in
239 // HelloVerifyRequest SHOULD be always DTLS
240 // 1.0. Enforce this for testing purposes.
241 return errors.New("dtls: bad HelloVerifyRequest version")
242 }
243
David Benjamin83c0bc92014-08-04 01:23:53 -0400244 hello.raw = nil
245 hello.cookie = helloVerifyRequest.cookie
246 helloBytes = hello.marshal()
247 c.writeRecord(recordTypeHandshake, helloBytes)
David Benjamina4e6d482015-03-02 19:10:53 -0500248 c.dtlsFlushHandshake()
David Benjamin83c0bc92014-08-04 01:23:53 -0400249
David Benjamin83f90402015-01-27 01:09:43 -0500250 if err := c.simulatePacketLoss(nil); err != nil {
251 return err
252 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400253 msg, err = c.readHandshake()
254 if err != nil {
255 return err
256 }
257 }
258 }
259
Adam Langley95c29f32014-06-20 12:00:00 -0700260 serverHello, ok := msg.(*serverHelloMsg)
261 if !ok {
262 c.sendAlert(alertUnexpectedMessage)
263 return unexpectedMessageError(serverHello, msg)
264 }
265
David Benjamin76d8abe2014-08-14 16:25:34 -0400266 c.vers, ok = c.config.mutualVersion(serverHello.vers)
267 if !ok {
Adam Langley95c29f32014-06-20 12:00:00 -0700268 c.sendAlert(alertProtocolVersion)
269 return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
270 }
Adam Langley95c29f32014-06-20 12:00:00 -0700271 c.haveVers = true
272
273 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
274 if suite == nil {
275 c.sendAlert(alertHandshakeFailure)
276 return fmt.Errorf("tls: server selected an unsupported cipher suite")
277 }
278
Adam Langley5021b222015-06-12 18:27:58 -0700279 if c.config.Bugs.RequireRenegotiationInfo && serverHello.secureRenegotiation == nil {
280 return errors.New("tls: renegotiation extension missing")
281 }
282
David Benjaminca6554b2014-11-08 12:31:52 -0500283 if len(c.clientVerify) > 0 && !c.config.Bugs.NoRenegotiationInfo {
Adam Langley2ae77d22014-10-28 17:29:33 -0700284 var expectedRenegInfo []byte
285 expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
286 expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
287 if !bytes.Equal(serverHello.secureRenegotiation, expectedRenegInfo) {
288 c.sendAlert(alertHandshakeFailure)
289 return fmt.Errorf("tls: renegotiation mismatch")
290 }
291 }
292
Adam Langley95c29f32014-06-20 12:00:00 -0700293 hs := &clientHandshakeState{
294 c: c,
295 serverHello: serverHello,
296 hello: hello,
297 suite: suite,
298 finishedHash: newFinishedHash(c.vers, suite),
299 session: session,
300 }
301
David Benjamin83c0bc92014-08-04 01:23:53 -0400302 hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
303 hs.writeServerHash(hs.serverHello.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700304
David Benjaminf3ec83d2014-07-21 22:42:34 -0400305 if c.config.Bugs.EarlyChangeCipherSpec > 0 {
306 hs.establishKeys()
307 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
308 }
309
Adam Langley95c29f32014-06-20 12:00:00 -0700310 isResume, err := hs.processServerHello()
311 if err != nil {
312 return err
313 }
314
315 if isResume {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400316 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
317 if err := hs.establishKeys(); err != nil {
318 return err
319 }
Adam Langley95c29f32014-06-20 12:00:00 -0700320 }
321 if err := hs.readSessionTicket(); err != nil {
322 return err
323 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700324 if err := hs.readFinished(c.firstFinished[:]); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700325 return err
326 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700327 if err := hs.sendFinished(nil, isResume); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700328 return err
329 }
330 } else {
331 if err := hs.doFullHandshake(); err != nil {
332 return err
333 }
334 if err := hs.establishKeys(); err != nil {
335 return err
336 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700337 if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700338 return err
339 }
David Benjamin83f90402015-01-27 01:09:43 -0500340 // Most retransmits are triggered by a timeout, but the final
341 // leg of the handshake is retransmited upon re-receiving a
342 // Finished.
David Benjaminb3774b92015-01-31 17:16:01 -0500343 if err := c.simulatePacketLoss(func() {
344 c.writeRecord(recordTypeHandshake, hs.finishedBytes)
David Benjamina4e6d482015-03-02 19:10:53 -0500345 c.dtlsFlushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -0500346 }); err != nil {
David Benjamin83f90402015-01-27 01:09:43 -0500347 return err
348 }
Adam Langley95c29f32014-06-20 12:00:00 -0700349 if err := hs.readSessionTicket(); err != nil {
350 return err
351 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700352 if err := hs.readFinished(nil); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700353 return err
354 }
355 }
356
357 if sessionCache != nil && hs.session != nil && session != hs.session {
358 sessionCache.Put(cacheKey, hs.session)
359 }
360
361 c.didResume = isResume
362 c.handshakeComplete = true
David Benjaminc565ebb2015-04-03 04:06:36 -0400363 c.cipherSuite = suite
364 copy(c.clientRandom[:], hs.hello.random)
365 copy(c.serverRandom[:], hs.serverHello.random)
366 copy(c.masterSecret[:], hs.masterSecret)
Adam Langley95c29f32014-06-20 12:00:00 -0700367 return nil
368}
369
370func (hs *clientHandshakeState) doFullHandshake() error {
371 c := hs.c
372
David Benjamin48cae082014-10-27 01:06:24 -0400373 var leaf *x509.Certificate
374 if hs.suite.flags&suitePSK == 0 {
375 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700376 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700377 return err
378 }
Adam Langley95c29f32014-06-20 12:00:00 -0700379
David Benjamin48cae082014-10-27 01:06:24 -0400380 certMsg, ok := msg.(*certificateMsg)
381 if !ok || len(certMsg.certificates) == 0 {
382 c.sendAlert(alertUnexpectedMessage)
383 return unexpectedMessageError(certMsg, msg)
384 }
385 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700386
David Benjamin48cae082014-10-27 01:06:24 -0400387 certs := make([]*x509.Certificate, len(certMsg.certificates))
388 for i, asn1Data := range certMsg.certificates {
389 cert, err := x509.ParseCertificate(asn1Data)
390 if err != nil {
391 c.sendAlert(alertBadCertificate)
392 return errors.New("tls: failed to parse certificate from server: " + err.Error())
393 }
394 certs[i] = cert
395 }
396 leaf = certs[0]
397
398 if !c.config.InsecureSkipVerify {
399 opts := x509.VerifyOptions{
400 Roots: c.config.RootCAs,
401 CurrentTime: c.config.time(),
402 DNSName: c.config.ServerName,
403 Intermediates: x509.NewCertPool(),
404 }
405
406 for i, cert := range certs {
407 if i == 0 {
408 continue
409 }
410 opts.Intermediates.AddCert(cert)
411 }
412 c.verifiedChains, err = leaf.Verify(opts)
413 if err != nil {
414 c.sendAlert(alertBadCertificate)
415 return err
416 }
417 }
418
419 switch leaf.PublicKey.(type) {
420 case *rsa.PublicKey, *ecdsa.PublicKey:
421 break
422 default:
423 c.sendAlert(alertUnsupportedCertificate)
424 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey)
425 }
426
427 c.peerCertificates = certs
428 }
Adam Langley95c29f32014-06-20 12:00:00 -0700429
430 if hs.serverHello.ocspStapling {
David Benjamin48cae082014-10-27 01:06:24 -0400431 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700432 if err != nil {
433 return err
434 }
435 cs, ok := msg.(*certificateStatusMsg)
436 if !ok {
437 c.sendAlert(alertUnexpectedMessage)
438 return unexpectedMessageError(cs, msg)
439 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400440 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700441
442 if cs.statusType == statusTypeOCSP {
443 c.ocspResponse = cs.response
444 }
445 }
446
David Benjamin48cae082014-10-27 01:06:24 -0400447 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700448 if err != nil {
449 return err
450 }
451
452 keyAgreement := hs.suite.ka(c.vers)
453
454 skx, ok := msg.(*serverKeyExchangeMsg)
455 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -0400456 hs.writeServerHash(skx.marshal())
David Benjamin48cae082014-10-27 01:06:24 -0400457 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
Adam Langley95c29f32014-06-20 12:00:00 -0700458 if err != nil {
459 c.sendAlert(alertUnexpectedMessage)
460 return err
461 }
462
463 msg, err = c.readHandshake()
464 if err != nil {
465 return err
466 }
467 }
468
469 var chainToSend *Certificate
470 var certRequested bool
471 certReq, ok := msg.(*certificateRequestMsg)
472 if ok {
473 certRequested = true
474
475 // RFC 4346 on the certificateAuthorities field:
476 // A list of the distinguished names of acceptable certificate
477 // authorities. These distinguished names may specify a desired
478 // distinguished name for a root CA or for a subordinate CA;
479 // thus, this message can be used to describe both known roots
480 // and a desired authorization space. If the
481 // certificate_authorities list is empty then the client MAY
482 // send any certificate of the appropriate
483 // ClientCertificateType, unless there is some external
484 // arrangement to the contrary.
485
David Benjamin83c0bc92014-08-04 01:23:53 -0400486 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700487
488 var rsaAvail, ecdsaAvail bool
489 for _, certType := range certReq.certificateTypes {
490 switch certType {
David Benjamin7b030512014-07-08 17:30:11 -0400491 case CertTypeRSASign:
Adam Langley95c29f32014-06-20 12:00:00 -0700492 rsaAvail = true
David Benjamin7b030512014-07-08 17:30:11 -0400493 case CertTypeECDSASign:
Adam Langley95c29f32014-06-20 12:00:00 -0700494 ecdsaAvail = true
495 }
496 }
497
498 // We need to search our list of client certs for one
499 // where SignatureAlgorithm is RSA and the Issuer is in
500 // certReq.certificateAuthorities
501 findCert:
502 for i, chain := range c.config.Certificates {
503 if !rsaAvail && !ecdsaAvail {
504 continue
505 }
506
507 for j, cert := range chain.Certificate {
508 x509Cert := chain.Leaf
509 // parse the certificate if this isn't the leaf
510 // node, or if chain.Leaf was nil
511 if j != 0 || x509Cert == nil {
512 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
513 c.sendAlert(alertInternalError)
514 return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
515 }
516 }
517
518 switch {
519 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
520 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
521 default:
522 continue findCert
523 }
524
525 if len(certReq.certificateAuthorities) == 0 {
526 // they gave us an empty list, so just take the
527 // first RSA cert from c.config.Certificates
528 chainToSend = &chain
529 break findCert
530 }
531
532 for _, ca := range certReq.certificateAuthorities {
533 if bytes.Equal(x509Cert.RawIssuer, ca) {
534 chainToSend = &chain
535 break findCert
536 }
537 }
538 }
539 }
540
541 msg, err = c.readHandshake()
542 if err != nil {
543 return err
544 }
545 }
546
547 shd, ok := msg.(*serverHelloDoneMsg)
548 if !ok {
549 c.sendAlert(alertUnexpectedMessage)
550 return unexpectedMessageError(shd, msg)
551 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400552 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700553
554 // If the server requested a certificate then we have to send a
555 // Certificate message, even if it's empty because we don't have a
556 // certificate to send.
557 if certRequested {
David Benjamin48cae082014-10-27 01:06:24 -0400558 certMsg := new(certificateMsg)
Adam Langley95c29f32014-06-20 12:00:00 -0700559 if chainToSend != nil {
560 certMsg.certificates = chainToSend.Certificate
561 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400562 hs.writeClientHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700563 c.writeRecord(recordTypeHandshake, certMsg.marshal())
564 }
565
David Benjamin48cae082014-10-27 01:06:24 -0400566 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
Adam Langley95c29f32014-06-20 12:00:00 -0700567 if err != nil {
568 c.sendAlert(alertInternalError)
569 return err
570 }
571 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400572 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -0400573 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -0400574 }
Adam Langley95c29f32014-06-20 12:00:00 -0700575 c.writeRecord(recordTypeHandshake, ckx.marshal())
576 }
577
Adam Langley75712922014-10-10 16:23:43 -0700578 if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 {
579 hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
580 c.extendedMasterSecret = true
581 } else {
582 if c.config.Bugs.RequireExtendedMasterSecret {
583 return errors.New("tls: extended master secret required but not supported by peer")
584 }
585 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
586 }
David Benjamine098ec22014-08-27 23:13:20 -0400587
Adam Langley95c29f32014-06-20 12:00:00 -0700588 if chainToSend != nil {
589 var signed []byte
590 certVerify := &certificateVerifyMsg{
591 hasSignatureAndHash: c.vers >= VersionTLS12,
592 }
593
David Benjamin72dc7832015-03-16 17:49:43 -0400594 // Determine the hash to sign.
595 var signatureType uint8
596 switch c.config.Certificates[0].PrivateKey.(type) {
597 case *ecdsa.PrivateKey:
598 signatureType = signatureECDSA
599 case *rsa.PrivateKey:
600 signatureType = signatureRSA
601 default:
602 c.sendAlert(alertInternalError)
603 return errors.New("unknown private key type")
604 }
605 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
606 certReq.signatureAndHashes = c.config.signatureAndHashesForClient()
607 }
608 certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, c.config.signatureAndHashesForClient(), signatureType)
609 if err != nil {
610 c.sendAlert(alertInternalError)
611 return err
612 }
613 digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
614 if err != nil {
615 c.sendAlert(alertInternalError)
616 return err
617 }
618
Adam Langley95c29f32014-06-20 12:00:00 -0700619 switch key := c.config.Certificates[0].PrivateKey.(type) {
620 case *ecdsa.PrivateKey:
David Benjaminde620d92014-07-18 15:03:41 -0400621 var r, s *big.Int
622 r, s, err = ecdsa.Sign(c.config.rand(), key, digest)
Adam Langley95c29f32014-06-20 12:00:00 -0700623 if err == nil {
624 signed, err = asn1.Marshal(ecdsaSignature{r, s})
625 }
Adam Langley95c29f32014-06-20 12:00:00 -0700626 case *rsa.PrivateKey:
Adam Langley95c29f32014-06-20 12:00:00 -0700627 signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
Adam Langley95c29f32014-06-20 12:00:00 -0700628 default:
629 err = errors.New("unknown private key type")
630 }
631 if err != nil {
632 c.sendAlert(alertInternalError)
633 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
634 }
635 certVerify.signature = signed
636
David Benjamin83c0bc92014-08-04 01:23:53 -0400637 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700638 c.writeRecord(recordTypeHandshake, certVerify.marshal())
639 }
David Benjamina4e6d482015-03-02 19:10:53 -0500640 c.dtlsFlushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700641
David Benjamine098ec22014-08-27 23:13:20 -0400642 hs.finishedHash.discardHandshakeBuffer()
643
Adam Langley95c29f32014-06-20 12:00:00 -0700644 return nil
645}
646
647func (hs *clientHandshakeState) establishKeys() error {
648 c := hs.c
649
650 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
651 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
652 var clientCipher, serverCipher interface{}
653 var clientHash, serverHash macFunction
654 if hs.suite.cipher != nil {
655 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
656 clientHash = hs.suite.mac(c.vers, clientMAC)
657 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
658 serverHash = hs.suite.mac(c.vers, serverMAC)
659 } else {
660 clientCipher = hs.suite.aead(clientKey, clientIV)
661 serverCipher = hs.suite.aead(serverKey, serverIV)
662 }
663
664 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
665 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
666 return nil
667}
668
669func (hs *clientHandshakeState) serverResumedSession() bool {
670 // If the server responded with the same sessionId then it means the
671 // sessionTicket is being used to resume a TLS session.
672 return hs.session != nil && hs.hello.sessionId != nil &&
673 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
674}
675
676func (hs *clientHandshakeState) processServerHello() (bool, error) {
677 c := hs.c
678
679 if hs.serverHello.compressionMethod != compressionNone {
680 c.sendAlert(alertUnexpectedMessage)
681 return false, errors.New("tls: server selected unsupported compression format")
682 }
683
David Benjaminfa055a22014-09-15 16:51:51 -0400684 clientDidNPN := hs.hello.nextProtoNeg
685 clientDidALPN := len(hs.hello.alpnProtocols) > 0
686 serverHasNPN := hs.serverHello.nextProtoNeg
687 serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
688
689 if !clientDidNPN && serverHasNPN {
Adam Langley95c29f32014-06-20 12:00:00 -0700690 c.sendAlert(alertHandshakeFailure)
691 return false, errors.New("server advertised unrequested NPN extension")
692 }
693
David Benjaminfa055a22014-09-15 16:51:51 -0400694 if !clientDidALPN && serverHasALPN {
695 c.sendAlert(alertHandshakeFailure)
696 return false, errors.New("server advertised unrequested ALPN extension")
697 }
698
699 if serverHasNPN && serverHasALPN {
700 c.sendAlert(alertHandshakeFailure)
701 return false, errors.New("server advertised both NPN and ALPN extensions")
702 }
703
704 if serverHasALPN {
705 c.clientProtocol = hs.serverHello.alpnProtocol
706 c.clientProtocolFallback = false
David Benjaminfc7b0862014-09-06 13:21:53 -0400707 c.usedALPN = true
David Benjaminfa055a22014-09-15 16:51:51 -0400708 }
709
David Benjamind30a9902014-08-24 01:44:23 -0400710 if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
711 c.sendAlert(alertHandshakeFailure)
712 return false, errors.New("server advertised unrequested Channel ID extension")
713 }
714
David Benjaminca6c8262014-11-15 19:06:08 -0500715 if hs.serverHello.srtpProtectionProfile != 0 {
716 if hs.serverHello.srtpMasterKeyIdentifier != "" {
717 return false, errors.New("tls: server selected SRTP MKI value")
718 }
719
720 found := false
721 for _, p := range c.config.SRTPProtectionProfiles {
722 if p == hs.serverHello.srtpProtectionProfile {
723 found = true
724 break
725 }
726 }
727 if !found {
728 return false, errors.New("tls: server advertised unsupported SRTP profile")
729 }
730
731 c.srtpProtectionProfile = hs.serverHello.srtpProtectionProfile
732 }
733
Adam Langley95c29f32014-06-20 12:00:00 -0700734 if hs.serverResumedSession() {
David Benjamin4b27d9f2015-05-12 22:42:52 -0400735 // For test purposes, assert that the server never accepts the
736 // resumption offer on renegotiation.
737 if c.cipherSuite != nil && c.config.Bugs.FailIfResumeOnRenego {
738 return false, errors.New("tls: server resumed session on renegotiation")
739 }
740
Adam Langley95c29f32014-06-20 12:00:00 -0700741 // Restore masterSecret and peerCerts from previous state
742 hs.masterSecret = hs.session.masterSecret
743 c.peerCertificates = hs.session.serverCertificates
Adam Langley75712922014-10-10 16:23:43 -0700744 c.extendedMasterSecret = hs.session.extendedMasterSecret
David Benjamine098ec22014-08-27 23:13:20 -0400745 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -0700746 return true, nil
747 }
748 return false, nil
749}
750
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700751func (hs *clientHandshakeState) readFinished(out []byte) error {
Adam Langley95c29f32014-06-20 12:00:00 -0700752 c := hs.c
753
754 c.readRecord(recordTypeChangeCipherSpec)
755 if err := c.in.error(); err != nil {
756 return err
757 }
758
759 msg, err := c.readHandshake()
760 if err != nil {
761 return err
762 }
763 serverFinished, ok := msg.(*finishedMsg)
764 if !ok {
765 c.sendAlert(alertUnexpectedMessage)
766 return unexpectedMessageError(serverFinished, msg)
767 }
768
David Benjaminf3ec83d2014-07-21 22:42:34 -0400769 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
770 verify := hs.finishedHash.serverSum(hs.masterSecret)
771 if len(verify) != len(serverFinished.verifyData) ||
772 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
773 c.sendAlert(alertHandshakeFailure)
774 return errors.New("tls: server's Finished message was incorrect")
775 }
Adam Langley95c29f32014-06-20 12:00:00 -0700776 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700777 c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700778 copy(out, serverFinished.verifyData)
David Benjamin83c0bc92014-08-04 01:23:53 -0400779 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700780 return nil
781}
782
783func (hs *clientHandshakeState) readSessionTicket() error {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500784 c := hs.c
785
786 // Create a session with no server identifier. Either a
787 // session ID or session ticket will be attached.
788 session := &ClientSessionState{
789 vers: c.vers,
790 cipherSuite: hs.suite.id,
791 masterSecret: hs.masterSecret,
792 handshakeHash: hs.finishedHash.server.Sum(nil),
793 serverCertificates: c.peerCertificates,
794 }
795
Adam Langley95c29f32014-06-20 12:00:00 -0700796 if !hs.serverHello.ticketSupported {
David Benjamind98452d2015-06-16 14:16:23 -0400797 if c.config.Bugs.ExpectNewTicket {
798 return errors.New("tls: expected new ticket")
799 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500800 if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
801 session.sessionId = hs.serverHello.sessionId
802 hs.session = session
803 }
Adam Langley95c29f32014-06-20 12:00:00 -0700804 return nil
805 }
806
Adam Langley95c29f32014-06-20 12:00:00 -0700807 msg, err := c.readHandshake()
808 if err != nil {
809 return err
810 }
811 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
812 if !ok {
813 c.sendAlert(alertUnexpectedMessage)
814 return unexpectedMessageError(sessionTicketMsg, msg)
815 }
Adam Langley95c29f32014-06-20 12:00:00 -0700816
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500817 session.sessionTicket = sessionTicketMsg.ticket
818 hs.session = session
Adam Langley95c29f32014-06-20 12:00:00 -0700819
David Benjamind30a9902014-08-24 01:44:23 -0400820 hs.writeServerHash(sessionTicketMsg.marshal())
821
Adam Langley95c29f32014-06-20 12:00:00 -0700822 return nil
823}
824
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700825func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -0700826 c := hs.c
827
David Benjamin86271ee2014-07-21 16:14:03 -0400828 var postCCSBytes []byte
David Benjamin83c0bc92014-08-04 01:23:53 -0400829 seqno := hs.c.sendHandshakeSeq
Adam Langley95c29f32014-06-20 12:00:00 -0700830 if hs.serverHello.nextProtoNeg {
831 nextProto := new(nextProtoMsg)
832 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
833 nextProto.proto = proto
834 c.clientProtocol = proto
835 c.clientProtocolFallback = fallback
836
David Benjamin86271ee2014-07-21 16:14:03 -0400837 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -0400838 hs.writeHash(nextProtoBytes, seqno)
839 seqno++
David Benjamin86271ee2014-07-21 16:14:03 -0400840 postCCSBytes = append(postCCSBytes, nextProtoBytes...)
Adam Langley95c29f32014-06-20 12:00:00 -0700841 }
842
David Benjamind30a9902014-08-24 01:44:23 -0400843 if hs.serverHello.channelIDRequested {
844 encryptedExtensions := new(encryptedExtensionsMsg)
845 if c.config.ChannelID.Curve != elliptic.P256() {
846 return fmt.Errorf("tls: Channel ID is not on P-256.")
847 }
848 var resumeHash []byte
849 if isResume {
850 resumeHash = hs.session.handshakeHash
851 }
852 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
853 if err != nil {
854 return err
855 }
856 channelID := make([]byte, 128)
857 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
858 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
859 writeIntPadded(channelID[64:96], r)
860 writeIntPadded(channelID[96:128], s)
861 encryptedExtensions.channelID = channelID
862
863 c.channelID = &c.config.ChannelID.PublicKey
864
865 encryptedExtensionsBytes := encryptedExtensions.marshal()
866 hs.writeHash(encryptedExtensionsBytes, seqno)
867 seqno++
868 postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...)
869 }
870
Adam Langley95c29f32014-06-20 12:00:00 -0700871 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -0400872 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
873 finished.verifyData = hs.finishedHash.clientSum(nil)
874 } else {
875 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
876 }
Adam Langleyaf0e32c2015-06-03 09:57:23 -0700877 copy(out, finished.verifyData)
David Benjamin513f0ea2015-04-02 19:33:31 -0400878 if c.config.Bugs.BadFinished {
879 finished.verifyData[0]++
880 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700881 c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
David Benjamin83f90402015-01-27 01:09:43 -0500882 hs.finishedBytes = finished.marshal()
883 hs.writeHash(hs.finishedBytes, seqno)
884 postCCSBytes = append(postCCSBytes, hs.finishedBytes...)
David Benjamin86271ee2014-07-21 16:14:03 -0400885
886 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
887 c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
888 postCCSBytes = postCCSBytes[5:]
889 }
David Benjamina4e6d482015-03-02 19:10:53 -0500890 c.dtlsFlushHandshake()
David Benjamin86271ee2014-07-21 16:14:03 -0400891
892 if !c.config.Bugs.SkipChangeCipherSpec &&
893 c.config.Bugs.EarlyChangeCipherSpec == 0 {
894 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
895 }
896
David Benjamin4189bd92015-01-25 23:52:39 -0500897 if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
898 c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
899 }
David Benjamindc3da932015-03-12 15:09:02 -0400900 if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
901 c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
902 return errors.New("tls: simulating post-CCS alert")
903 }
David Benjamin4189bd92015-01-25 23:52:39 -0500904
David Benjaminb80168e2015-02-08 18:30:14 -0500905 if !c.config.Bugs.SkipFinished {
906 c.writeRecord(recordTypeHandshake, postCCSBytes)
David Benjamina4e6d482015-03-02 19:10:53 -0500907 c.dtlsFlushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -0500908 }
Adam Langley95c29f32014-06-20 12:00:00 -0700909 return nil
910}
911
David Benjamin83c0bc92014-08-04 01:23:53 -0400912func (hs *clientHandshakeState) writeClientHash(msg []byte) {
913 // writeClientHash is called before writeRecord.
914 hs.writeHash(msg, hs.c.sendHandshakeSeq)
915}
916
917func (hs *clientHandshakeState) writeServerHash(msg []byte) {
918 // writeServerHash is called after readHandshake.
919 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
920}
921
922func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
923 if hs.c.isDTLS {
924 // This is somewhat hacky. DTLS hashes a slightly different format.
925 // First, the TLS header.
926 hs.finishedHash.Write(msg[:4])
927 // Then the sequence number and reassembled fragment offset (always 0).
928 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
929 // Then the reassembled fragment (always equal to the message length).
930 hs.finishedHash.Write(msg[1:4])
931 // And then the message body.
932 hs.finishedHash.Write(msg[4:])
933 } else {
934 hs.finishedHash.Write(msg)
935 }
936}
937
Adam Langley95c29f32014-06-20 12:00:00 -0700938// clientSessionCacheKey returns a key used to cache sessionTickets that could
939// be used to resume previously negotiated TLS sessions with a server.
940func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
941 if len(config.ServerName) > 0 {
942 return config.ServerName
943 }
944 return serverAddr.String()
945}
946
David Benjaminfa055a22014-09-15 16:51:51 -0400947// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
948// given list of possible protocols and a list of the preference order. The
949// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -0700950// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -0400951func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
952 for _, s := range preferenceProtos {
953 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -0700954 if s == c {
955 return s, false
956 }
957 }
958 }
959
David Benjaminfa055a22014-09-15 16:51:51 -0400960 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -0700961}
David Benjamind30a9902014-08-24 01:44:23 -0400962
963// writeIntPadded writes x into b, padded up with leading zeros as
964// needed.
965func writeIntPadded(b []byte, x *big.Int) {
966 for i := range b {
967 b[i] = 0
968 }
969 xb := x.Bytes()
970 copy(b[len(b)-len(xb):], xb)
971}