blob: 0dac05d6fb6835e0d42413c85cacaf761f023375 [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 {
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 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.
118 if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
119 continue
120 }
Adam Langley95c29f32014-06-20 12:00:00 -0700121 hello.cipherSuites = append(hello.cipherSuites, suiteId)
122 continue NextCipherSuite
123 }
124 }
125
David Benjaminbef270a2014-08-02 04:22:02 -0400126 if c.config.Bugs.SendFallbackSCSV {
127 hello.cipherSuites = append(hello.cipherSuites, fallbackSCSV)
128 }
129
Adam Langley95c29f32014-06-20 12:00:00 -0700130 _, err := io.ReadFull(c.config.rand(), hello.random)
131 if err != nil {
132 c.sendAlert(alertInternalError)
133 return errors.New("tls: short read from Rand: " + err.Error())
134 }
135
David Benjaminc565ebb2015-04-03 04:06:36 -0400136 if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes && (c.cipherSuite == nil || !c.config.Bugs.NoSignatureAlgorithmsOnRenego) {
David Benjamin000800a2014-11-14 01:43:59 -0500137 hello.signatureAndHashes = c.config.signatureAndHashesForClient()
Adam Langley95c29f32014-06-20 12:00:00 -0700138 }
139
140 var session *ClientSessionState
141 var cacheKey string
142 sessionCache := c.config.ClientSessionCache
David Benjaminc565ebb2015-04-03 04:06:36 -0400143 if c.config.Bugs.NeverResumeOnRenego && c.cipherSuite != nil {
David Benjamincdea40c2015-03-19 14:09:43 -0400144 sessionCache = nil
145 }
Adam Langley95c29f32014-06-20 12:00:00 -0700146
147 if sessionCache != nil {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500148 hello.ticketSupported = !c.config.SessionTicketsDisabled
Adam Langley95c29f32014-06-20 12:00:00 -0700149
150 // Try to resume a previously negotiated TLS session, if
151 // available.
152 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
153 candidateSession, ok := sessionCache.Get(cacheKey)
154 if ok {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500155 ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
156
Adam Langley95c29f32014-06-20 12:00:00 -0700157 // Check that the ciphersuite/version used for the
158 // previous session are still valid.
159 cipherSuiteOk := false
160 for _, id := range hello.cipherSuites {
161 if id == candidateSession.cipherSuite {
162 cipherSuiteOk = true
163 break
164 }
165 }
166
167 versOk := candidateSession.vers >= c.config.minVersion() &&
168 candidateSession.vers <= c.config.maxVersion()
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500169 if ticketOk && versOk && cipherSuiteOk {
Adam Langley95c29f32014-06-20 12:00:00 -0700170 session = candidateSession
171 }
172 }
173 }
174
175 if session != nil {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500176 if session.sessionTicket != nil {
177 hello.sessionTicket = session.sessionTicket
178 if c.config.Bugs.CorruptTicket {
179 hello.sessionTicket = make([]byte, len(session.sessionTicket))
180 copy(hello.sessionTicket, session.sessionTicket)
181 if len(hello.sessionTicket) > 0 {
182 offset := 40
183 if offset > len(hello.sessionTicket) {
184 offset = len(hello.sessionTicket) - 1
185 }
186 hello.sessionTicket[offset] ^= 0x40
Adam Langley38311732014-10-16 19:04:35 -0700187 }
Adam Langley38311732014-10-16 19:04:35 -0700188 }
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500189 // A random session ID is used to detect when the
190 // server accepted the ticket and is resuming a session
191 // (see RFC 5077).
192 sessionIdLen := 16
193 if c.config.Bugs.OversizedSessionId {
194 sessionIdLen = 33
195 }
196 hello.sessionId = make([]byte, sessionIdLen)
197 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
198 c.sendAlert(alertInternalError)
199 return errors.New("tls: short read from Rand: " + err.Error())
200 }
201 } else {
202 hello.sessionId = session.sessionId
Adam Langley95c29f32014-06-20 12:00:00 -0700203 }
204 }
205
David Benjamind86c7672014-08-02 04:07:12 -0400206 var helloBytes []byte
207 if c.config.Bugs.SendV2ClientHello {
David Benjamin94d701b2014-11-30 13:54:41 -0500208 // Test that the peer left-pads random.
209 hello.random[0] = 0
David Benjamind86c7672014-08-02 04:07:12 -0400210 v2Hello := &v2ClientHelloMsg{
211 vers: hello.vers,
212 cipherSuites: hello.cipherSuites,
213 // No session resumption for V2ClientHello.
214 sessionId: nil,
David Benjamin94d701b2014-11-30 13:54:41 -0500215 challenge: hello.random[1:],
David Benjamind86c7672014-08-02 04:07:12 -0400216 }
217 helloBytes = v2Hello.marshal()
218 c.writeV2Record(helloBytes)
219 } else {
220 helloBytes = hello.marshal()
221 c.writeRecord(recordTypeHandshake, helloBytes)
222 }
David Benjamina4e6d482015-03-02 19:10:53 -0500223 c.dtlsFlushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700224
David Benjamin83f90402015-01-27 01:09:43 -0500225 if err := c.simulatePacketLoss(nil); err != nil {
226 return err
227 }
Adam Langley95c29f32014-06-20 12:00:00 -0700228 msg, err := c.readHandshake()
229 if err != nil {
230 return err
231 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400232
233 if c.isDTLS {
234 helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
235 if ok {
David Benjamin8bc38f52014-08-16 12:07:27 -0400236 if helloVerifyRequest.vers != VersionTLS10 {
237 // Per RFC 6347, the version field in
238 // HelloVerifyRequest SHOULD be always DTLS
239 // 1.0. Enforce this for testing purposes.
240 return errors.New("dtls: bad HelloVerifyRequest version")
241 }
242
David Benjamin83c0bc92014-08-04 01:23:53 -0400243 hello.raw = nil
244 hello.cookie = helloVerifyRequest.cookie
245 helloBytes = hello.marshal()
246 c.writeRecord(recordTypeHandshake, helloBytes)
David Benjamina4e6d482015-03-02 19:10:53 -0500247 c.dtlsFlushHandshake()
David Benjamin83c0bc92014-08-04 01:23:53 -0400248
David Benjamin83f90402015-01-27 01:09:43 -0500249 if err := c.simulatePacketLoss(nil); err != nil {
250 return err
251 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400252 msg, err = c.readHandshake()
253 if err != nil {
254 return err
255 }
256 }
257 }
258
Adam Langley95c29f32014-06-20 12:00:00 -0700259 serverHello, ok := msg.(*serverHelloMsg)
260 if !ok {
261 c.sendAlert(alertUnexpectedMessage)
262 return unexpectedMessageError(serverHello, msg)
263 }
264
David Benjamin76d8abe2014-08-14 16:25:34 -0400265 c.vers, ok = c.config.mutualVersion(serverHello.vers)
266 if !ok {
Adam Langley95c29f32014-06-20 12:00:00 -0700267 c.sendAlert(alertProtocolVersion)
268 return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
269 }
Adam Langley95c29f32014-06-20 12:00:00 -0700270 c.haveVers = true
271
272 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
273 if suite == nil {
274 c.sendAlert(alertHandshakeFailure)
275 return fmt.Errorf("tls: server selected an unsupported cipher suite")
276 }
277
David Benjaminca6554b2014-11-08 12:31:52 -0500278 if len(c.clientVerify) > 0 && !c.config.Bugs.NoRenegotiationInfo {
Adam Langley2ae77d22014-10-28 17:29:33 -0700279 var expectedRenegInfo []byte
280 expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
281 expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
282 if !bytes.Equal(serverHello.secureRenegotiation, expectedRenegInfo) {
283 c.sendAlert(alertHandshakeFailure)
284 return fmt.Errorf("tls: renegotiation mismatch")
285 }
286 }
287
Adam Langley95c29f32014-06-20 12:00:00 -0700288 hs := &clientHandshakeState{
289 c: c,
290 serverHello: serverHello,
291 hello: hello,
292 suite: suite,
293 finishedHash: newFinishedHash(c.vers, suite),
294 session: session,
295 }
296
David Benjamin83c0bc92014-08-04 01:23:53 -0400297 hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
298 hs.writeServerHash(hs.serverHello.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700299
David Benjaminf3ec83d2014-07-21 22:42:34 -0400300 if c.config.Bugs.EarlyChangeCipherSpec > 0 {
301 hs.establishKeys()
302 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
303 }
304
Adam Langley95c29f32014-06-20 12:00:00 -0700305 isResume, err := hs.processServerHello()
306 if err != nil {
307 return err
308 }
309
310 if isResume {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400311 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
312 if err := hs.establishKeys(); err != nil {
313 return err
314 }
Adam Langley95c29f32014-06-20 12:00:00 -0700315 }
316 if err := hs.readSessionTicket(); err != nil {
317 return err
318 }
319 if err := hs.readFinished(); err != nil {
320 return err
321 }
David Benjamind30a9902014-08-24 01:44:23 -0400322 if err := hs.sendFinished(isResume); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700323 return err
324 }
325 } else {
326 if err := hs.doFullHandshake(); err != nil {
327 return err
328 }
329 if err := hs.establishKeys(); err != nil {
330 return err
331 }
David Benjamind30a9902014-08-24 01:44:23 -0400332 if err := hs.sendFinished(isResume); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700333 return err
334 }
David Benjamin83f90402015-01-27 01:09:43 -0500335 // Most retransmits are triggered by a timeout, but the final
336 // leg of the handshake is retransmited upon re-receiving a
337 // Finished.
David Benjaminb3774b92015-01-31 17:16:01 -0500338 if err := c.simulatePacketLoss(func() {
339 c.writeRecord(recordTypeHandshake, hs.finishedBytes)
David Benjamina4e6d482015-03-02 19:10:53 -0500340 c.dtlsFlushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -0500341 }); err != nil {
David Benjamin83f90402015-01-27 01:09:43 -0500342 return err
343 }
Adam Langley95c29f32014-06-20 12:00:00 -0700344 if err := hs.readSessionTicket(); err != nil {
345 return err
346 }
347 if err := hs.readFinished(); err != nil {
348 return err
349 }
350 }
351
352 if sessionCache != nil && hs.session != nil && session != hs.session {
353 sessionCache.Put(cacheKey, hs.session)
354 }
355
356 c.didResume = isResume
357 c.handshakeComplete = true
David Benjaminc565ebb2015-04-03 04:06:36 -0400358 c.cipherSuite = suite
359 copy(c.clientRandom[:], hs.hello.random)
360 copy(c.serverRandom[:], hs.serverHello.random)
361 copy(c.masterSecret[:], hs.masterSecret)
Adam Langley95c29f32014-06-20 12:00:00 -0700362 return nil
363}
364
365func (hs *clientHandshakeState) doFullHandshake() error {
366 c := hs.c
367
David Benjamin48cae082014-10-27 01:06:24 -0400368 var leaf *x509.Certificate
369 if hs.suite.flags&suitePSK == 0 {
370 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700371 if err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700372 return err
373 }
Adam Langley95c29f32014-06-20 12:00:00 -0700374
David Benjamin48cae082014-10-27 01:06:24 -0400375 certMsg, ok := msg.(*certificateMsg)
376 if !ok || len(certMsg.certificates) == 0 {
377 c.sendAlert(alertUnexpectedMessage)
378 return unexpectedMessageError(certMsg, msg)
379 }
380 hs.writeServerHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700381
David Benjamin48cae082014-10-27 01:06:24 -0400382 certs := make([]*x509.Certificate, len(certMsg.certificates))
383 for i, asn1Data := range certMsg.certificates {
384 cert, err := x509.ParseCertificate(asn1Data)
385 if err != nil {
386 c.sendAlert(alertBadCertificate)
387 return errors.New("tls: failed to parse certificate from server: " + err.Error())
388 }
389 certs[i] = cert
390 }
391 leaf = certs[0]
392
393 if !c.config.InsecureSkipVerify {
394 opts := x509.VerifyOptions{
395 Roots: c.config.RootCAs,
396 CurrentTime: c.config.time(),
397 DNSName: c.config.ServerName,
398 Intermediates: x509.NewCertPool(),
399 }
400
401 for i, cert := range certs {
402 if i == 0 {
403 continue
404 }
405 opts.Intermediates.AddCert(cert)
406 }
407 c.verifiedChains, err = leaf.Verify(opts)
408 if err != nil {
409 c.sendAlert(alertBadCertificate)
410 return err
411 }
412 }
413
414 switch leaf.PublicKey.(type) {
415 case *rsa.PublicKey, *ecdsa.PublicKey:
416 break
417 default:
418 c.sendAlert(alertUnsupportedCertificate)
419 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey)
420 }
421
422 c.peerCertificates = certs
423 }
Adam Langley95c29f32014-06-20 12:00:00 -0700424
425 if hs.serverHello.ocspStapling {
David Benjamin48cae082014-10-27 01:06:24 -0400426 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700427 if err != nil {
428 return err
429 }
430 cs, ok := msg.(*certificateStatusMsg)
431 if !ok {
432 c.sendAlert(alertUnexpectedMessage)
433 return unexpectedMessageError(cs, msg)
434 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400435 hs.writeServerHash(cs.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700436
437 if cs.statusType == statusTypeOCSP {
438 c.ocspResponse = cs.response
439 }
440 }
441
David Benjamin48cae082014-10-27 01:06:24 -0400442 msg, err := c.readHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700443 if err != nil {
444 return err
445 }
446
447 keyAgreement := hs.suite.ka(c.vers)
448
449 skx, ok := msg.(*serverKeyExchangeMsg)
450 if ok {
David Benjamin83c0bc92014-08-04 01:23:53 -0400451 hs.writeServerHash(skx.marshal())
David Benjamin48cae082014-10-27 01:06:24 -0400452 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
Adam Langley95c29f32014-06-20 12:00:00 -0700453 if err != nil {
454 c.sendAlert(alertUnexpectedMessage)
455 return err
456 }
457
458 msg, err = c.readHandshake()
459 if err != nil {
460 return err
461 }
462 }
463
464 var chainToSend *Certificate
465 var certRequested bool
466 certReq, ok := msg.(*certificateRequestMsg)
467 if ok {
468 certRequested = true
469
470 // RFC 4346 on the certificateAuthorities field:
471 // A list of the distinguished names of acceptable certificate
472 // authorities. These distinguished names may specify a desired
473 // distinguished name for a root CA or for a subordinate CA;
474 // thus, this message can be used to describe both known roots
475 // and a desired authorization space. If the
476 // certificate_authorities list is empty then the client MAY
477 // send any certificate of the appropriate
478 // ClientCertificateType, unless there is some external
479 // arrangement to the contrary.
480
David Benjamin83c0bc92014-08-04 01:23:53 -0400481 hs.writeServerHash(certReq.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700482
483 var rsaAvail, ecdsaAvail bool
484 for _, certType := range certReq.certificateTypes {
485 switch certType {
David Benjamin7b030512014-07-08 17:30:11 -0400486 case CertTypeRSASign:
Adam Langley95c29f32014-06-20 12:00:00 -0700487 rsaAvail = true
David Benjamin7b030512014-07-08 17:30:11 -0400488 case CertTypeECDSASign:
Adam Langley95c29f32014-06-20 12:00:00 -0700489 ecdsaAvail = true
490 }
491 }
492
493 // We need to search our list of client certs for one
494 // where SignatureAlgorithm is RSA and the Issuer is in
495 // certReq.certificateAuthorities
496 findCert:
497 for i, chain := range c.config.Certificates {
498 if !rsaAvail && !ecdsaAvail {
499 continue
500 }
501
502 for j, cert := range chain.Certificate {
503 x509Cert := chain.Leaf
504 // parse the certificate if this isn't the leaf
505 // node, or if chain.Leaf was nil
506 if j != 0 || x509Cert == nil {
507 if x509Cert, err = x509.ParseCertificate(cert); err != nil {
508 c.sendAlert(alertInternalError)
509 return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
510 }
511 }
512
513 switch {
514 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
515 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
516 default:
517 continue findCert
518 }
519
520 if len(certReq.certificateAuthorities) == 0 {
521 // they gave us an empty list, so just take the
522 // first RSA cert from c.config.Certificates
523 chainToSend = &chain
524 break findCert
525 }
526
527 for _, ca := range certReq.certificateAuthorities {
528 if bytes.Equal(x509Cert.RawIssuer, ca) {
529 chainToSend = &chain
530 break findCert
531 }
532 }
533 }
534 }
535
536 msg, err = c.readHandshake()
537 if err != nil {
538 return err
539 }
540 }
541
542 shd, ok := msg.(*serverHelloDoneMsg)
543 if !ok {
544 c.sendAlert(alertUnexpectedMessage)
545 return unexpectedMessageError(shd, msg)
546 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400547 hs.writeServerHash(shd.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700548
549 // If the server requested a certificate then we have to send a
550 // Certificate message, even if it's empty because we don't have a
551 // certificate to send.
552 if certRequested {
David Benjamin48cae082014-10-27 01:06:24 -0400553 certMsg := new(certificateMsg)
Adam Langley95c29f32014-06-20 12:00:00 -0700554 if chainToSend != nil {
555 certMsg.certificates = chainToSend.Certificate
556 }
David Benjamin83c0bc92014-08-04 01:23:53 -0400557 hs.writeClientHash(certMsg.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700558 c.writeRecord(recordTypeHandshake, certMsg.marshal())
559 }
560
David Benjamin48cae082014-10-27 01:06:24 -0400561 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
Adam Langley95c29f32014-06-20 12:00:00 -0700562 if err != nil {
563 c.sendAlert(alertInternalError)
564 return err
565 }
566 if ckx != nil {
David Benjaminf3ec83d2014-07-21 22:42:34 -0400567 if c.config.Bugs.EarlyChangeCipherSpec < 2 {
David Benjamin83c0bc92014-08-04 01:23:53 -0400568 hs.writeClientHash(ckx.marshal())
David Benjaminf3ec83d2014-07-21 22:42:34 -0400569 }
Adam Langley95c29f32014-06-20 12:00:00 -0700570 c.writeRecord(recordTypeHandshake, ckx.marshal())
571 }
572
Adam Langley75712922014-10-10 16:23:43 -0700573 if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 {
574 hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
575 c.extendedMasterSecret = true
576 } else {
577 if c.config.Bugs.RequireExtendedMasterSecret {
578 return errors.New("tls: extended master secret required but not supported by peer")
579 }
580 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
581 }
David Benjamine098ec22014-08-27 23:13:20 -0400582
Adam Langley95c29f32014-06-20 12:00:00 -0700583 if chainToSend != nil {
584 var signed []byte
585 certVerify := &certificateVerifyMsg{
586 hasSignatureAndHash: c.vers >= VersionTLS12,
587 }
588
David Benjamin72dc7832015-03-16 17:49:43 -0400589 // Determine the hash to sign.
590 var signatureType uint8
591 switch c.config.Certificates[0].PrivateKey.(type) {
592 case *ecdsa.PrivateKey:
593 signatureType = signatureECDSA
594 case *rsa.PrivateKey:
595 signatureType = signatureRSA
596 default:
597 c.sendAlert(alertInternalError)
598 return errors.New("unknown private key type")
599 }
600 if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
601 certReq.signatureAndHashes = c.config.signatureAndHashesForClient()
602 }
603 certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, c.config.signatureAndHashesForClient(), signatureType)
604 if err != nil {
605 c.sendAlert(alertInternalError)
606 return err
607 }
608 digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
609 if err != nil {
610 c.sendAlert(alertInternalError)
611 return err
612 }
613
Adam Langley95c29f32014-06-20 12:00:00 -0700614 switch key := c.config.Certificates[0].PrivateKey.(type) {
615 case *ecdsa.PrivateKey:
David Benjaminde620d92014-07-18 15:03:41 -0400616 var r, s *big.Int
617 r, s, err = ecdsa.Sign(c.config.rand(), key, digest)
Adam Langley95c29f32014-06-20 12:00:00 -0700618 if err == nil {
619 signed, err = asn1.Marshal(ecdsaSignature{r, s})
620 }
Adam Langley95c29f32014-06-20 12:00:00 -0700621 case *rsa.PrivateKey:
Adam Langley95c29f32014-06-20 12:00:00 -0700622 signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
Adam Langley95c29f32014-06-20 12:00:00 -0700623 default:
624 err = errors.New("unknown private key type")
625 }
626 if err != nil {
627 c.sendAlert(alertInternalError)
628 return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
629 }
630 certVerify.signature = signed
631
David Benjamin83c0bc92014-08-04 01:23:53 -0400632 hs.writeClientHash(certVerify.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700633 c.writeRecord(recordTypeHandshake, certVerify.marshal())
634 }
David Benjamina4e6d482015-03-02 19:10:53 -0500635 c.dtlsFlushHandshake()
Adam Langley95c29f32014-06-20 12:00:00 -0700636
David Benjamine098ec22014-08-27 23:13:20 -0400637 hs.finishedHash.discardHandshakeBuffer()
638
Adam Langley95c29f32014-06-20 12:00:00 -0700639 return nil
640}
641
642func (hs *clientHandshakeState) establishKeys() error {
643 c := hs.c
644
645 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
646 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
647 var clientCipher, serverCipher interface{}
648 var clientHash, serverHash macFunction
649 if hs.suite.cipher != nil {
650 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
651 clientHash = hs.suite.mac(c.vers, clientMAC)
652 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
653 serverHash = hs.suite.mac(c.vers, serverMAC)
654 } else {
655 clientCipher = hs.suite.aead(clientKey, clientIV)
656 serverCipher = hs.suite.aead(serverKey, serverIV)
657 }
658
659 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
660 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
661 return nil
662}
663
664func (hs *clientHandshakeState) serverResumedSession() bool {
665 // If the server responded with the same sessionId then it means the
666 // sessionTicket is being used to resume a TLS session.
667 return hs.session != nil && hs.hello.sessionId != nil &&
668 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
669}
670
671func (hs *clientHandshakeState) processServerHello() (bool, error) {
672 c := hs.c
673
674 if hs.serverHello.compressionMethod != compressionNone {
675 c.sendAlert(alertUnexpectedMessage)
676 return false, errors.New("tls: server selected unsupported compression format")
677 }
678
David Benjaminfa055a22014-09-15 16:51:51 -0400679 clientDidNPN := hs.hello.nextProtoNeg
680 clientDidALPN := len(hs.hello.alpnProtocols) > 0
681 serverHasNPN := hs.serverHello.nextProtoNeg
682 serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
683
684 if !clientDidNPN && serverHasNPN {
Adam Langley95c29f32014-06-20 12:00:00 -0700685 c.sendAlert(alertHandshakeFailure)
686 return false, errors.New("server advertised unrequested NPN extension")
687 }
688
David Benjaminfa055a22014-09-15 16:51:51 -0400689 if !clientDidALPN && serverHasALPN {
690 c.sendAlert(alertHandshakeFailure)
691 return false, errors.New("server advertised unrequested ALPN extension")
692 }
693
694 if serverHasNPN && serverHasALPN {
695 c.sendAlert(alertHandshakeFailure)
696 return false, errors.New("server advertised both NPN and ALPN extensions")
697 }
698
699 if serverHasALPN {
700 c.clientProtocol = hs.serverHello.alpnProtocol
701 c.clientProtocolFallback = false
David Benjaminfc7b0862014-09-06 13:21:53 -0400702 c.usedALPN = true
David Benjaminfa055a22014-09-15 16:51:51 -0400703 }
704
David Benjamind30a9902014-08-24 01:44:23 -0400705 if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
706 c.sendAlert(alertHandshakeFailure)
707 return false, errors.New("server advertised unrequested Channel ID extension")
708 }
709
David Benjaminca6c8262014-11-15 19:06:08 -0500710 if hs.serverHello.srtpProtectionProfile != 0 {
711 if hs.serverHello.srtpMasterKeyIdentifier != "" {
712 return false, errors.New("tls: server selected SRTP MKI value")
713 }
714
715 found := false
716 for _, p := range c.config.SRTPProtectionProfiles {
717 if p == hs.serverHello.srtpProtectionProfile {
718 found = true
719 break
720 }
721 }
722 if !found {
723 return false, errors.New("tls: server advertised unsupported SRTP profile")
724 }
725
726 c.srtpProtectionProfile = hs.serverHello.srtpProtectionProfile
727 }
728
Adam Langley95c29f32014-06-20 12:00:00 -0700729 if hs.serverResumedSession() {
730 // Restore masterSecret and peerCerts from previous state
731 hs.masterSecret = hs.session.masterSecret
732 c.peerCertificates = hs.session.serverCertificates
Adam Langley75712922014-10-10 16:23:43 -0700733 c.extendedMasterSecret = hs.session.extendedMasterSecret
David Benjamine098ec22014-08-27 23:13:20 -0400734 hs.finishedHash.discardHandshakeBuffer()
Adam Langley95c29f32014-06-20 12:00:00 -0700735 return true, nil
736 }
737 return false, nil
738}
739
740func (hs *clientHandshakeState) readFinished() error {
741 c := hs.c
742
743 c.readRecord(recordTypeChangeCipherSpec)
744 if err := c.in.error(); err != nil {
745 return err
746 }
747
748 msg, err := c.readHandshake()
749 if err != nil {
750 return err
751 }
752 serverFinished, ok := msg.(*finishedMsg)
753 if !ok {
754 c.sendAlert(alertUnexpectedMessage)
755 return unexpectedMessageError(serverFinished, msg)
756 }
757
David Benjaminf3ec83d2014-07-21 22:42:34 -0400758 if c.config.Bugs.EarlyChangeCipherSpec == 0 {
759 verify := hs.finishedHash.serverSum(hs.masterSecret)
760 if len(verify) != len(serverFinished.verifyData) ||
761 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
762 c.sendAlert(alertHandshakeFailure)
763 return errors.New("tls: server's Finished message was incorrect")
764 }
Adam Langley95c29f32014-06-20 12:00:00 -0700765 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700766 c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
David Benjamin83c0bc92014-08-04 01:23:53 -0400767 hs.writeServerHash(serverFinished.marshal())
Adam Langley95c29f32014-06-20 12:00:00 -0700768 return nil
769}
770
771func (hs *clientHandshakeState) readSessionTicket() error {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500772 c := hs.c
773
774 // Create a session with no server identifier. Either a
775 // session ID or session ticket will be attached.
776 session := &ClientSessionState{
777 vers: c.vers,
778 cipherSuite: hs.suite.id,
779 masterSecret: hs.masterSecret,
780 handshakeHash: hs.finishedHash.server.Sum(nil),
781 serverCertificates: c.peerCertificates,
782 }
783
Adam Langley95c29f32014-06-20 12:00:00 -0700784 if !hs.serverHello.ticketSupported {
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500785 if hs.session == nil && len(hs.serverHello.sessionId) > 0 {
786 session.sessionId = hs.serverHello.sessionId
787 hs.session = session
788 }
Adam Langley95c29f32014-06-20 12:00:00 -0700789 return nil
790 }
791
Adam Langley95c29f32014-06-20 12:00:00 -0700792 msg, err := c.readHandshake()
793 if err != nil {
794 return err
795 }
796 sessionTicketMsg, ok := msg.(*newSessionTicketMsg)
797 if !ok {
798 c.sendAlert(alertUnexpectedMessage)
799 return unexpectedMessageError(sessionTicketMsg, msg)
800 }
Adam Langley95c29f32014-06-20 12:00:00 -0700801
David Benjaminfe8eb9a2014-11-17 03:19:02 -0500802 session.sessionTicket = sessionTicketMsg.ticket
803 hs.session = session
Adam Langley95c29f32014-06-20 12:00:00 -0700804
David Benjamind30a9902014-08-24 01:44:23 -0400805 hs.writeServerHash(sessionTicketMsg.marshal())
806
Adam Langley95c29f32014-06-20 12:00:00 -0700807 return nil
808}
809
David Benjamind30a9902014-08-24 01:44:23 -0400810func (hs *clientHandshakeState) sendFinished(isResume bool) error {
Adam Langley95c29f32014-06-20 12:00:00 -0700811 c := hs.c
812
David Benjamin86271ee2014-07-21 16:14:03 -0400813 var postCCSBytes []byte
David Benjamin83c0bc92014-08-04 01:23:53 -0400814 seqno := hs.c.sendHandshakeSeq
Adam Langley95c29f32014-06-20 12:00:00 -0700815 if hs.serverHello.nextProtoNeg {
816 nextProto := new(nextProtoMsg)
817 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
818 nextProto.proto = proto
819 c.clientProtocol = proto
820 c.clientProtocolFallback = fallback
821
David Benjamin86271ee2014-07-21 16:14:03 -0400822 nextProtoBytes := nextProto.marshal()
David Benjamin83c0bc92014-08-04 01:23:53 -0400823 hs.writeHash(nextProtoBytes, seqno)
824 seqno++
David Benjamin86271ee2014-07-21 16:14:03 -0400825 postCCSBytes = append(postCCSBytes, nextProtoBytes...)
Adam Langley95c29f32014-06-20 12:00:00 -0700826 }
827
David Benjamind30a9902014-08-24 01:44:23 -0400828 if hs.serverHello.channelIDRequested {
829 encryptedExtensions := new(encryptedExtensionsMsg)
830 if c.config.ChannelID.Curve != elliptic.P256() {
831 return fmt.Errorf("tls: Channel ID is not on P-256.")
832 }
833 var resumeHash []byte
834 if isResume {
835 resumeHash = hs.session.handshakeHash
836 }
837 r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
838 if err != nil {
839 return err
840 }
841 channelID := make([]byte, 128)
842 writeIntPadded(channelID[0:32], c.config.ChannelID.X)
843 writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
844 writeIntPadded(channelID[64:96], r)
845 writeIntPadded(channelID[96:128], s)
846 encryptedExtensions.channelID = channelID
847
848 c.channelID = &c.config.ChannelID.PublicKey
849
850 encryptedExtensionsBytes := encryptedExtensions.marshal()
851 hs.writeHash(encryptedExtensionsBytes, seqno)
852 seqno++
853 postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...)
854 }
855
Adam Langley95c29f32014-06-20 12:00:00 -0700856 finished := new(finishedMsg)
David Benjaminf3ec83d2014-07-21 22:42:34 -0400857 if c.config.Bugs.EarlyChangeCipherSpec == 2 {
858 finished.verifyData = hs.finishedHash.clientSum(nil)
859 } else {
860 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
861 }
David Benjamin513f0ea2015-04-02 19:33:31 -0400862 if c.config.Bugs.BadFinished {
863 finished.verifyData[0]++
864 }
Adam Langley2ae77d22014-10-28 17:29:33 -0700865 c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
David Benjamin83f90402015-01-27 01:09:43 -0500866 hs.finishedBytes = finished.marshal()
867 hs.writeHash(hs.finishedBytes, seqno)
868 postCCSBytes = append(postCCSBytes, hs.finishedBytes...)
David Benjamin86271ee2014-07-21 16:14:03 -0400869
870 if c.config.Bugs.FragmentAcrossChangeCipherSpec {
871 c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
872 postCCSBytes = postCCSBytes[5:]
873 }
David Benjamina4e6d482015-03-02 19:10:53 -0500874 c.dtlsFlushHandshake()
David Benjamin86271ee2014-07-21 16:14:03 -0400875
876 if !c.config.Bugs.SkipChangeCipherSpec &&
877 c.config.Bugs.EarlyChangeCipherSpec == 0 {
878 c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
879 }
880
David Benjamin4189bd92015-01-25 23:52:39 -0500881 if c.config.Bugs.AppDataAfterChangeCipherSpec != nil {
882 c.writeRecord(recordTypeApplicationData, c.config.Bugs.AppDataAfterChangeCipherSpec)
883 }
David Benjamindc3da932015-03-12 15:09:02 -0400884 if c.config.Bugs.AlertAfterChangeCipherSpec != 0 {
885 c.sendAlert(c.config.Bugs.AlertAfterChangeCipherSpec)
886 return errors.New("tls: simulating post-CCS alert")
887 }
David Benjamin4189bd92015-01-25 23:52:39 -0500888
David Benjaminb80168e2015-02-08 18:30:14 -0500889 if !c.config.Bugs.SkipFinished {
890 c.writeRecord(recordTypeHandshake, postCCSBytes)
David Benjamina4e6d482015-03-02 19:10:53 -0500891 c.dtlsFlushHandshake()
David Benjaminb3774b92015-01-31 17:16:01 -0500892 }
Adam Langley95c29f32014-06-20 12:00:00 -0700893 return nil
894}
895
David Benjamin83c0bc92014-08-04 01:23:53 -0400896func (hs *clientHandshakeState) writeClientHash(msg []byte) {
897 // writeClientHash is called before writeRecord.
898 hs.writeHash(msg, hs.c.sendHandshakeSeq)
899}
900
901func (hs *clientHandshakeState) writeServerHash(msg []byte) {
902 // writeServerHash is called after readHandshake.
903 hs.writeHash(msg, hs.c.recvHandshakeSeq-1)
904}
905
906func (hs *clientHandshakeState) writeHash(msg []byte, seqno uint16) {
907 if hs.c.isDTLS {
908 // This is somewhat hacky. DTLS hashes a slightly different format.
909 // First, the TLS header.
910 hs.finishedHash.Write(msg[:4])
911 // Then the sequence number and reassembled fragment offset (always 0).
912 hs.finishedHash.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
913 // Then the reassembled fragment (always equal to the message length).
914 hs.finishedHash.Write(msg[1:4])
915 // And then the message body.
916 hs.finishedHash.Write(msg[4:])
917 } else {
918 hs.finishedHash.Write(msg)
919 }
920}
921
Adam Langley95c29f32014-06-20 12:00:00 -0700922// clientSessionCacheKey returns a key used to cache sessionTickets that could
923// be used to resume previously negotiated TLS sessions with a server.
924func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
925 if len(config.ServerName) > 0 {
926 return config.ServerName
927 }
928 return serverAddr.String()
929}
930
David Benjaminfa055a22014-09-15 16:51:51 -0400931// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
932// given list of possible protocols and a list of the preference order. The
933// first list must not be empty. It returns the resulting protocol and flag
Adam Langley95c29f32014-06-20 12:00:00 -0700934// indicating if the fallback case was reached.
David Benjaminfa055a22014-09-15 16:51:51 -0400935func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
936 for _, s := range preferenceProtos {
937 for _, c := range protos {
Adam Langley95c29f32014-06-20 12:00:00 -0700938 if s == c {
939 return s, false
940 }
941 }
942 }
943
David Benjaminfa055a22014-09-15 16:51:51 -0400944 return protos[0], true
Adam Langley95c29f32014-06-20 12:00:00 -0700945}
David Benjamind30a9902014-08-24 01:44:23 -0400946
947// writeIntPadded writes x into b, padded up with leading zeros as
948// needed.
949func writeIntPadded(b []byte, x *big.Int) {
950 for i := range b {
951 b[i] = 0
952 }
953 xb := x.Bytes()
954 copy(b[len(b)-len(xb):], xb)
955}