blob: f4cadc26c1fb40d35a3a95b60934ceaf50e225ed [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"
David Benjaminde620d92014-07-18 15:03:41 -04009 "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"
15 "encoding/asn1"
16 "errors"
17 "fmt"
18 "io"
David Benjaminde620d92014-07-18 15:03:41 -040019 "math/big"
Adam Langley95c29f32014-06-20 12:00:00 -070020 "net"
21 "strconv"
22)
23
24type clientHandshakeState struct {
25 c *Conn
26 serverHello *serverHelloMsg
27 hello *clientHelloMsg
28 suite *cipherSuite
29 finishedHash finishedHash
30 masterSecret []byte
31 session *ClientSessionState
32}
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 {
48 if l := len(proto); l == 0 || l > 255 {
49 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 Benjamin83c0bc92014-08-04 01:23:53 -040059 isDTLS: c.isDTLS,
Adam Langley95c29f32014-06-20 12:00:00 -070060 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: true,
David Benjaminfa055a22014-09-15 16:51:51 -040069 alpnProtocols: c.config.NextProtos,
David Benjamin35a7a442014-07-05 00:23:20 -040070 duplicateExtension: c.config.Bugs.DuplicateExtension,
David Benjamind30a9902014-08-24 01:44:23 -040071 channelIDSupported: c.config.ChannelID != nil,
David Benjaminfc7b0862014-09-06 13:21:53 -040072 npnLast: c.config.Bugs.SwapNPNAndALPN,
Adam Langley95c29f32014-06-20 12:00:00 -070073 }
74
David Benjamin98e882e2014-08-08 13:24:34 -040075 if c.config.Bugs.SendClientVersion != 0 {
76 hello.vers = c.config.Bugs.SendClientVersion
77 }
78
Adam Langley95c29f32014-06-20 12:00:00 -070079 possibleCipherSuites := c.config.cipherSuites()
80 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
81
82NextCipherSuite:
83 for _, suiteId := range possibleCipherSuites {
84 for _, suite := range cipherSuites {
85 if suite.id != suiteId {
86 continue
87 }
88 // Don't advertise TLS 1.2-only cipher suites unless
89 // we're attempting TLS 1.2.
90 if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
91 continue
92 }
David Benjamin83c0bc92014-08-04 01:23:53 -040093 // Don't advertise non-DTLS cipher suites on DTLS.
94 if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
95 continue
96 }
Adam Langley95c29f32014-06-20 12:00:00 -070097 hello.cipherSuites = append(hello.cipherSuites, suiteId)
98 continue NextCipherSuite
99 }
100 }
101
David Benjaminbef270a2014-08-02 04:22:02 -0400102 if c.config.Bugs.SendFallbackSCSV {
103 hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
104 }
105
Adam Langley95c29f32014-06-20 12:00:00 -0700106 _, err := io.ReadFull(c.config.rand(), hello.random)
107 if err != nil {
108 c.sendAlert(alertInternalError)
109 return errors.New("tls: short read from Rand: " + err.Error())
110 }
111
112 if hello.vers >= VersionTLS12 {
113 hello.signatureAndHashes = supportedSKXSignatureAlgorithms
114 }
115
116 var session *ClientSessionState
117 var cacheKey string
118 sessionCache := c.config.ClientSessionCache
119 if c.config.SessionTicketsDisabled {
120 sessionCache = nil
121 }
122
123 if sessionCache != nil {
124 hello.ticketSupported = true
125
126 // Try to resume a previously negotiated TLS session, if
127 // available.
128 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
129 candidateSession, ok := sessionCache.Get(cacheKey)
130 if ok {
131 // Check that the ciphersuite/version used for the
132 // previous session are still valid.
133 cipherSuiteOk := false
134 for _, id := range hello.cipherSuites {
135 if id == candidateSession.cipherSuite {
136 cipherSuiteOk = true
137 break
138 }
139 }
140
141 versOk := candidateSession.vers >= c.config.minVersion() &&
142 candidateSession.vers <= c.config.maxVersion()
143 if versOk && cipherSuiteOk {
144 session = candidateSession
145 }
146 }
147 }
148
149 if session != nil {
150 hello.sessionTicket = session.sessionTicket
Adam Langley38311732014-10-16 19:04:35 -0700151 if c.config.Bugs.CorruptTicket {
152 hello.sessionTicket = make([]byte, len(session.sessionTicket))
153 copy(hello.sessionTicket, session.sessionTicket)
154 if len(hello.sessionTicket) > 0 {
155 offset := 40
156 if offset > len(hello.sessionTicket) {
157 offset = len(hello.sessionTicket) - 1
158 }
159 hello.sessionTicket[offset] ^= 0x40
160 }
161 }
Adam Langley95c29f32014-06-20 12:00:00 -0700162 // A random session ID is used to detect when the
163 // server accepted the ticket and is resuming a session
164 // (see RFC 5077).
Adam Langley38311732014-10-16 19:04:35 -0700165 sessionIdLen := 16
166 if c.config.Bugs.OversizedSessionId {
167 sessionIdLen = 33
168 }
169 hello.sessionId = make([]byte, sessionIdLen)
Adam Langley95c29f32014-06-20 12:00:00 -0700170 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
171 c.sendAlert(alertInternalError)
172 return errors.New("tls: short read from Rand: " + err.Error())
173 }
174 }
175
David Benjamind86c7672014-08-02 04:07:12 -0400176 var helloBytes []byte
177 if c.config.Bugs.SendV2ClientHello {
178 v2Hello := &v2ClientHelloMsg{
179 vers: hello.vers,
180 cipherSuites: hello.cipherSuites,
181 // No session resumption for V2ClientHello.
182 sessionId: nil,
183 challenge: hello.random,
184 }
185 helloBytes = v2Hello.marshal()
186 c.writeV2Record(helloBytes)
187 } else {
188 helloBytes = hello.marshal()
189 c.writeRecord(recordTypeHandshake, helloBytes)
190 }
Adam Langley95c29f32014-06-20 12:00:00 -0700191
192 msg, err := c.readHandshake()
193 if err != nil {
194 return err
195 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400196
197 if c.isDTLS {
198 helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
199 if ok {
David Benjamin8bc38f52014-08-16 12:07:27 -0400200 if helloVerifyRequest.vers != VersionTLS10 {
201 // Per RFC 6347, the version field in
202 // HelloVerifyRequest SHOULD be always DTLS
203 // 1.0. Enforce this for testing purposes.
204 return errors.New("dtls: bad HelloVerifyRequest version")
205 }
206
David Benjamin83c0bc92014-08-04 01:23:53 -0400207 hello.raw = nil
208 hello.cookie = helloVerifyRequest.cookie
209 helloBytes = hello.marshal()
210 c.writeRecord(recordTypeHandshake, helloBytes)
211
212 msg, err = c.readHandshake()
213 if err != nil {
214 return err
215 }
216 }
217 }
218
Adam Langley95c29f32014-06-20 12:00:00 -0700219 serverHello, ok := msg.(*serverHelloMsg)
220 if !ok {
221 c.sendAlert(alertUnexpectedMessage)
222 return unexpectedMessageError(serverHello, msg)
223 }
224
David Benjamin76d8abe2014-08-14 16:25:34 -0400225 c.vers, ok = c.config.mutualVersion(serverHello.vers)
226 if !ok {
Adam Langley95c29f32014-06-20 12:00:00 -0700227 c.sendAlert(alertProtocolVersion)
228 return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
229 }
Adam Langley95c29f32014-06-20 12:00:00 -0700230 c.haveVers = true
231
232 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
233 if suite == nil {
234 c.sendAlert(alertHandshakeFailure)
235 return fmt.Errorf("tls: server selected an unsupported cipher suite")
236 }
237
238 hs := &clientHandshakeState{
239 c: c,
240 serverHello: serverHello,
241 hello: hello,
242 suite: suite,
243 finishedHash: newFinishedHash(c.vers, suite),
244 session: session,
245 }
246
David Benjamin83c0bc92014-08-04 01:23:53 -0400247 hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
248 hs.writeServerHash(hs.serverHello.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700249
David Benjaminf3ec83d2014-07-21 22:42:34 -0400250 if c.config.Bugs.EarlyChangeCipherSpec > 0 {
251 hs.establishKeys()
252 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
253 }
254
Adam Langley95c29f32014-06-20 12:00:00 -0700255 isResume, err := hs.processServerHello()
256 if err != nil {
257 return err
258 }
259
260 if isResume {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400261 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
262 if err := hs.establishKeys(); err != nil {
263 return err
264 }
Adam Langley95c29f32014-06-20 12:00:00 -0700265 }
266 if err := hs.readSessionTicket(); err != nil {
267 return err
268 }
269 if err := hs.readFinished(); err != nil {
270 return err
271 }
David Benjamind30a9902014-08-24 01:44:23 -0400272 if err := hs.sendFinished(isResume); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700273 return err
274 }
275 } else {
276 if err := hs.doFullHandshake(); err != nil {
277 return err
278 }
279 if err := hs.establishKeys(); err != nil {
280 return err
281 }
David Benjamind30a9902014-08-24 01:44:23 -0400282 if err := hs.sendFinished(isResume); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700283 return err
284 }
285 if err := hs.readSessionTicket(); err != nil {
286 return err
287 }
288 if err := hs.readFinished(); err != nil {
289 return err
290 }
291 }
292
293 if sessionCache != nil && hs.session != nil && session != hs.session {
294 sessionCache.Put(cacheKey, hs.session)
295 }
296
297 c.didResume = isResume
298 c.handshakeComplete = true
299 c.cipherSuite = suite.id
300 return nil
301}
302
303func (hs *clientHandshakeState) doFullHandshake() error {
304 c := hs.c
305
306 msg, err := c.readHandshake()
307 if err != nil {
308 return err
309 }
310 certMsg, ok := msg.(*certificateMsg)
311 if !ok || len(certMsg.certificates) == 0 {
312 c.sendAlert(alertUnexpectedMessage)
313 return unexpectedMessageError(certMsg, msg)
314 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400315 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700316
317 certs := make([]*x509.Certificate, len(certMsg.certificates))
318 for i, asn1Data := range certMsg.certificates {
319 cert, err := x509.ParseCertificate(asn1Data)
320 if err != nil {
321 c.sendAlert(alertBadCertificate)
322 return errors.New("tls: failed to parse certificate from server: " + err.Error())
323 }
324 certs[i] = cert
325 }
326
327 if !c.config.InsecureSkipVerify {
328 opts := x509.VerifyOptions{
329 Roots: c.config.RootCAs,
330 CurrentTime: c.config.time(),
331 DNSName: c.config.ServerName,
332 Intermediates: x509.NewCertPool(),
333 }
334
335 for i, cert := range certs {
336 if i == 0 {
337 continue
338 }
339 opts.Intermediates.AddCert(cert)
340 }
341 c.verifiedChains, err = certs[0].Verify(opts)
342 if err != nil {
343 c.sendAlert(alertBadCertificate)
344 return err
345 }
346 }
347
348 switch certs[0].PublicKey.(type) {
349 case *rsa.PublicKey, *ecdsa.PublicKey:
350 break
351 default:
352 c.sendAlert(alertUnsupportedCertificate)
353 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
354 }
355
356 c.peerCertificates = certs
357
358 if hs.serverHello.ocspStapling {
359 msg, err = c.readHandshake()
360 if err != nil {
361 return err
362 }
363 cs, ok := msg.(*certificateStatusMsg)
364 if !ok {
365 c.sendAlert(alertUnexpectedMessage)
366 return unexpectedMessageError(cs, msg)
367 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400368 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700369
370 if cs.statusType == statusTypeOCSP {
371 c.ocspResponse = cs.response
372 }
373 }
374
375 msg, err = c.readHandshake()
376 if err != nil {
377 return err
378 }
379
380 keyAgreement := hs.suite.ka(c.vers)
381
382 skx, ok := msg.(*serverKeyExchangeMsg)
383 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -0400384 hs.writeServerHash(skx.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700385 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx)
386 if err != nil {
387 c.sendAlert(alertUnexpectedMessage)
388 return err
389 }
390
391 msg, err = c.readHandshake()
392 if err != nil {
393 return err
394 }
395 }
396
397 var chainToSend *Certificate
398 var certRequested bool
399 certReq, ok := msg.(*certificateRequestMsg)
400 if ok {
401 certRequested = true
402
403 // RFC 4346 on the certificateAuthorities field:
404 // A list of the distinguished names of acceptable certificate
405 // authorities. These distinguished names may specify a desired
406 // distinguished name for a root CA or for a subordinate CA;
407 // thus, this message can be used to describe both known roots
408 // and a desired authorization space. If the
409 // certificate_authorities list is empty then the client MAY
410 // send any certificate of the appropriate
411 // ClientCertificateType, unless there is some external
412 // arrangement to the contrary.
413
David Benjamin83c0bc92014-08-04 01:23:53 -0400414 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700415
416 var rsaAvail, ecdsaAvail bool
417 for _, certType := range certReq.certificateTypes {
418 switch certType {
David Benjamin7b030512014-07-08 17:30:11 -0400419 case CertTypeRSASign:
Adam Langley95c29f32014-06-20 12:00:00 -0700420 rsaAvail = true
David Benjamin7b030512014-07-08 17:30:11 -0400421 case CertTypeECDSASign:
Adam Langley95c29f32014-06-20 12:00:00 -0700422 ecdsaAvail = true
423 }
424 }
425
426 // We need to search our list of client certs for one
427 // where SignatureAlgorithm is RSA and the Issuer is in
428 // certReq.certificateAuthorities
429 findCert:
430 for i, chain := range c.config.Certificates {
431 if !rsaAvail && !ecdsaAvail {
432 continue
433 }
434
435 for j, cert := range chain.Certificate {
436 x509Cert := chain.Leaf
437 // parse the certificate if this isn't the leaf
438 // node, or if chain.Leaf was nil
439 if j != 0 || x509Cert == nil {
440 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
441 c.sendAlert(alertInternalError)
442 return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
443 }
444 }
445
446 switch {
447 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
448 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
449 default:
450 continue findCert
451 }
452
453 if len(certReq.certificateAuthorities) == 0 {
454 // they gave us an empty list, so just take the
455 // first RSA cert from c.config.Certificates
456 chainToSend = &chain
457 break findCert
458 }
459
460 for _, ca := range certReq.certificateAuthorities {
461 if bytes.Equal(x509Cert.RawIssuer, ca) {
462 chainToSend = &chain
463 break findCert
464 }
465 }
466 }
467 }
468
469 msg, err = c.readHandshake()
470 if err != nil {
471 return err
472 }
473 }
474
475 shd, ok := msg.(*serverHelloDoneMsg)
476 if !ok {
477 c.sendAlert(alertUnexpectedMessage)
478 return unexpectedMessageError(shd, msg)
479 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400480 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700481
482 // If the server requested a certificate then we have to send a
483 // Certificate message, even if it's empty because we don't have a
484 // certificate to send.
485 if certRequested {
486 certMsg = new(certificateMsg)
487 if chainToSend != nil {
488 certMsg.certificates = chainToSend.Certificate
489 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400490 hs.writeClientHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700491 c.writeRecord(recordTypeHandshake, certMsg.marshal())
492 }
493
494 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0])
495 if err != nil {
496 c.sendAlert(alertInternalError)
497 return err
498 }
499 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400500 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -0400501 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -0400502 }
Adam Langley95c29f32014-06-20 12:00:00 -0700503 c.writeRecord(recordTypeHandshake, ckx.marshal())
504 }
505
David Benjamine098ec22014-08-27 23:13:20 -0400506 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
507
Adam Langley95c29f32014-06-20 12:00:00 -0700508 if chainToSend != nil {
509 var signed []byte
510 certVerify := &certificateVerifyMsg{
511 hasSignatureAndHash: c.vers >= VersionTLS12,
512 }
513
514 switch key := c.config.Certificates[0].PrivateKey.(type) {
515 case *ecdsa.PrivateKey:
David Benjaminde620d92014-07-18 15:03:41 -0400516 certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureECDSA)
517 if err != nil {
518 break
519 }
520 var digest []byte
David Benjamine098ec22014-08-27 23:13:20 -0400521 digest, _, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
David Benjaminde620d92014-07-18 15:03:41 -0400522 if err != nil {
523 break
524 }
525 var r, s *big.Int
526 r, s, err = ecdsa.Sign(c.config.rand(), key, digest)
Adam Langley95c29f32014-06-20 12:00:00 -0700527 if err == nil {
528 signed, err = asn1.Marshal(ecdsaSignature{r, s})
529 }
Adam Langley95c29f32014-06-20 12:00:00 -0700530 case *rsa.PrivateKey:
David Benjaminde620d92014-07-18 15:03:41 -0400531 certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureRSA)
532 if err != nil {
533 break
534 }
535 var digest []byte
536 var hashFunc crypto.Hash
David Benjamine098ec22014-08-27 23:13:20 -0400537 digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
David Benjaminde620d92014-07-18 15:03:41 -0400538 if err != nil {
539 break
540 }
Adam Langley95c29f32014-06-20 12:00:00 -0700541 signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
Adam Langley95c29f32014-06-20 12:00:00 -0700542 default:
543 err = errors.New("unknown private key type")
544 }
545 if err != nil {
546 c.sendAlert(alertInternalError)
547 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
548 }
549 certVerify.signature = signed
550
David Benjamin83c0bc92014-08-04 01:23:53 -0400551 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700552 c.writeRecord(recordTypeHandshake, certVerify.marshal())
553 }
554
David Benjamine098ec22014-08-27 23:13:20 -0400555 hs.finishedHash.discardHandshakeBuffer()
556
Adam Langley95c29f32014-06-20 12:00:00 -0700557 return nil
558}
559
560func (hs *clientHandshakeState) establishKeys() error {
561 c := hs.c
562
563 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
564 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
565 var clientCipher, serverCipher interface{}
566 var clientHash, serverHash macFunction
567 if hs.suite.cipher != nil {
568 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
569 clientHash = hs.suite.mac(c.vers, clientMAC)
570 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
571 serverHash = hs.suite.mac(c.vers, serverMAC)
572 } else {
573 clientCipher = hs.suite.aead(clientKey, clientIV)
574 serverCipher = hs.suite.aead(serverKey, serverIV)
575 }
576
577 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
578 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
579 return nil
580}
581
582func (hs *clientHandshakeState) serverResumedSession() bool {
583 // If the server responded with the same sessionId then it means the
584 // sessionTicket is being used to resume a TLS session.
585 return hs.session != nil && hs.hello.sessionId != nil &&
586 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
587}
588
589func (hs *clientHandshakeState) processServerHello() (bool, error) {
590 c := hs.c
591
592 if hs.serverHello.compressionMethod != compressionNone {
593 c.sendAlert(alertUnexpectedMessage)
594 return false, errors.New("tls: server selected unsupported compression format")
595 }
596
David Benjaminfa055a22014-09-15 16:51:51 -0400597 clientDidNPN := hs.hello.nextProtoNeg
598 clientDidALPN := len(hs.hello.alpnProtocols) > 0
599 serverHasNPN := hs.serverHello.nextProtoNeg
600 serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
601
602 if !clientDidNPN && serverHasNPN {
Adam Langley95c29f32014-06-20 12:00:00 -0700603 c.sendAlert(alertHandshakeFailure)
604 return false, errors.New("server advertised unrequested NPN extension")
605 }
606
David Benjaminfa055a22014-09-15 16:51:51 -0400607 if !clientDidALPN && serverHasALPN {
608 c.sendAlert(alertHandshakeFailure)
609 return false, errors.New("server advertised unrequested ALPN extension")
610 }
611
612 if serverHasNPN && serverHasALPN {
613 c.sendAlert(alertHandshakeFailure)
614 return false, errors.New("server advertised both NPN and ALPN extensions")
615 }
616
617 if serverHasALPN {
618 c.clientProtocol = hs.serverHello.alpnProtocol
619 c.clientProtocolFallback = false
David Benjaminfc7b0862014-09-06 13:21:53 -0400620 c.usedALPN = true
David Benjaminfa055a22014-09-15 16:51:51 -0400621 }
622
David Benjamind30a9902014-08-24 01:44:23 -0400623 if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
624 c.sendAlert(alertHandshakeFailure)
625 return false, errors.New("server advertised unrequested Channel ID extension")
626 }
627
Adam Langley95c29f32014-06-20 12:00:00 -0700628 if hs.serverResumedSession() {
629 // Restore masterSecret and peerCerts from previous state
630 hs.masterSecret = hs.session.masterSecret
631 c.peerCertificates = hs.session.serverCertificates
David Benjamine098ec22014-08-27 23:13:20 -0400632 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -0700633 return true, nil
634 }
635 return false, nil
636}
637
638func (hs *clientHandshakeState) readFinished() error {
639 c := hs.c
640
641 c.readRecord(recordTypeChangeCipherSpec)
642 if err := c.in.error(); err != nil {
643 return err
644 }
645
646 msg, err := c.readHandshake()
647 if err != nil {
648 return err
649 }
650 serverFinished, ok := msg.(*finishedMsg)
651 if !ok {
652 c.sendAlert(alertUnexpectedMessage)
653 return unexpectedMessageError(serverFinished, msg)
654 }
655
David Benjaminf3ec83d2014-07-21 22:42:34 -0400656 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
657 verify := hs.finishedHash.serverSum(hs.masterSecret)
658 if len(verify) != len(serverFinished.verifyData) ||
659 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
660 c.sendAlert(alertHandshakeFailure)
661 return errors.New("tls: server's Finished message was incorrect")
662 }
Adam Langley95c29f32014-06-20 12:00:00 -0700663 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400664 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700665 return nil
666}
667
668func (hs *clientHandshakeState) readSessionTicket() error {
669 if !hs.serverHello.ticketSupported {
670 return nil
671 }
672
673 c := hs.c
674 msg, err := c.readHandshake()
675 if err != nil {
676 return err
677 }
678 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
679 if !ok {
680 c.sendAlert(alertUnexpectedMessage)
681 return unexpectedMessageError(sessionTicketMsg, msg)
682 }
Adam Langley95c29f32014-06-20 12:00:00 -0700683
684 hs.session = &ClientSessionState{
685 sessionTicket: sessionTicketMsg.ticket,
686 vers: c.vers,
687 cipherSuite: hs.suite.id,
688 masterSecret: hs.masterSecret,
David Benjamind30a9902014-08-24 01:44:23 -0400689 handshakeHash: hs.finishedHash.server.Sum(nil),
Adam Langley95c29f32014-06-20 12:00:00 -0700690 serverCertificates: c.peerCertificates,
691 }
692
David Benjamind30a9902014-08-24 01:44:23 -0400693 hs.writeServerHash(sessionTicketMsg.marshal())
694
Adam Langley95c29f32014-06-20 12:00:00 -0700695 return nil
696}
697
David Benjamind30a9902014-08-24 01:44:23 -0400698func (hs *clientHandshakeState) sendFinished(isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -0700699 c := hs.c
700
David Benjamin86271ee2014-07-21 16:14:03 -0400701 var postCCSBytes []byte
David Benjamin83c0bc92014-08-04 01:23:53 -0400702 seqno := hs.c.sendHandshakeSeq
Adam Langley95c29f32014-06-20 12:00:00 -0700703 if hs.serverHello.nextProtoNeg {
704 nextProto := new(nextProtoMsg)
705 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
706 nextProto.proto = proto
707 c.clientProtocol = proto
708 c.clientProtocolFallback = fallback
709
David Benjamin86271ee2014-07-21 16:14:03 -0400710 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -0400711 hs.writeHash(nextProtoBytes, seqno)
712 seqno++
David Benjamin86271ee2014-07-21 16:14:03 -0400713 postCCSBytes = append(postCCSBytes, nextProtoBytes...)
Adam Langley95c29f32014-06-20 12:00:00 -0700714 }
715
David Benjamind30a9902014-08-24 01:44:23 -0400716 if hs.serverHello.channelIDRequested {
717 encryptedExtensions := new(encryptedExtensionsMsg)
718 if c.config.ChannelID.Curve != elliptic.P256() {
719 return fmt.Errorf("tls: Channel ID is not on P-256.")
720 }
721 var resumeHash []byte
722 if isResume {
723 resumeHash = hs.session.handshakeHash
724 }
725 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
726 if err != nil {
727 return err
728 }
729 channelID := make([]byte, 128)
730 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
731 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
732 writeIntPadded(channelID[64:96], r)
733 writeIntPadded(channelID[96:128], s)
734 encryptedExtensions.channelID = channelID
735
736 c.channelID = &c.config.ChannelID.PublicKey
737
738 encryptedExtensionsBytes := encryptedExtensions.marshal()
739 hs.writeHash(encryptedExtensionsBytes, seqno)
740 seqno++
741 postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...)
742 }
743
Adam Langley95c29f32014-06-20 12:00:00 -0700744 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -0400745 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
746 finished.verifyData = hs.finishedHash.clientSum(nil)
747 } else {
748 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
749 }
David Benjamin86271ee2014-07-21 16:14:03 -0400750 finishedBytes := finished.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -0400751 hs.writeHash(finishedBytes, seqno)
David Benjamin86271ee2014-07-21 16:14:03 -0400752 postCCSBytes = append(postCCSBytes, finishedBytes...)
753
754 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
755 c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
756 postCCSBytes = postCCSBytes[5:]
757 }
758
759 if !c.config.Bugs.SkipChangeCipherSpec &&
760 c.config.Bugs.EarlyChangeCipherSpec == 0 {
761 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
762 }
763
764 c.writeRecord(recordTypeHandshake, postCCSBytes)
Adam Langley95c29f32014-06-20 12:00:00 -0700765 return nil
766}
767
David Benjamin83c0bc92014-08-04 01:23:53 -0400768func (hs *clientHandshakeState) writeClientHash(msg []byte) {
769 // writeClientHash is called before writeRecord.
770 hs.writeHash(msg, hs.c.sendHandshakeSeq)
771}
772
773func (hs *clientHandshakeState) writeServerHash(msg []byte) {
774 // writeServerHash is called after readHandshake.
775 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
776}
777
778func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
779 if hs.c.isDTLS {
780 // This is somewhat hacky. DTLS hashes a slightly different format.
781 // First, the TLS header.
782 hs.finishedHash.Write(msg[:4])
783 // Then the sequence number and reassembled fragment offset (always 0).
784 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
785 // Then the reassembled fragment (always equal to the message length).
786 hs.finishedHash.Write(msg[1:4])
787 // And then the message body.
788 hs.finishedHash.Write(msg[4:])
789 } else {
790 hs.finishedHash.Write(msg)
791 }
792}
793
Adam Langley95c29f32014-06-20 12:00:00 -0700794// clientSessionCacheKey returns a key used to cache sessionTickets that could
795// be used to resume previously negotiated TLS sessions with a server.
796func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
797 if len(config.ServerName) > 0 {
798 return config.ServerName
799 }
800 return serverAddr.String()
801}
802
David Benjaminfa055a22014-09-15 16:51:51 -0400803// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
804// given list of possible protocols and a list of the preference order. The
805// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -0700806// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -0400807func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
808 for _, s := range preferenceProtos {
809 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -0700810 if s == c {
811 return s, false
812 }
813 }
814 }
815
David Benjaminfa055a22014-09-15 16:51:51 -0400816 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -0700817}
David Benjamind30a9902014-08-24 01:44:23 -0400818
819// writeIntPadded writes x into b, padded up with leading zeros as
820// needed.
821func writeIntPadded(b []byte, x *big.Int) {
822 for i := range b {
823 b[i] = 0
824 }
825 xb := x.Bytes()
826 copy(b[len(b)-len(xb):], xb)
827}