github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/crypto/tls/handshake_client.go (about) 1 // 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 5 package tls 6 7 import ( 8 "bytes" 9 "crypto" 10 "crypto/ecdsa" 11 "crypto/rsa" 12 "crypto/subtle" 13 "crypto/x509" 14 "errors" 15 "fmt" 16 "io" 17 "net" 18 "strconv" 19 ) 20 21 type clientHandshakeState struct { 22 c *Conn 23 serverHello *serverHelloMsg 24 hello *clientHelloMsg 25 suite *cipherSuite 26 finishedHash finishedHash 27 masterSecret []byte 28 session *ClientSessionState 29 } 30 31 func (c *Conn) clientHandshake() error { 32 if c.config == nil { 33 c.config = defaultConfig() 34 } 35 36 if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify { 37 return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") 38 } 39 40 nextProtosLength := 0 41 for _, proto := range c.config.NextProtos { 42 if l := len(proto); l == 0 || l > 255 { 43 return errors.New("tls: invalid NextProtos value") 44 } else { 45 nextProtosLength += 1 + l 46 } 47 } 48 if nextProtosLength > 0xffff { 49 return errors.New("tls: NextProtos values too large") 50 } 51 52 hello := &clientHelloMsg{ 53 vers: c.config.maxVersion(), 54 compressionMethods: []uint8{compressionNone}, 55 random: make([]byte, 32), 56 ocspStapling: true, 57 scts: true, 58 serverName: c.config.ServerName, 59 supportedCurves: c.config.curvePreferences(), 60 supportedPoints: []uint8{pointFormatUncompressed}, 61 nextProtoNeg: len(c.config.NextProtos) > 0, 62 secureRenegotiation: true, 63 alpnProtocols: c.config.NextProtos, 64 } 65 66 possibleCipherSuites := c.config.cipherSuites() 67 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites)) 68 69 NextCipherSuite: 70 for _, suiteId := range possibleCipherSuites { 71 for _, suite := range cipherSuites { 72 if suite.id != suiteId { 73 continue 74 } 75 // Don't advertise TLS 1.2-only cipher suites unless 76 // we're attempting TLS 1.2. 77 if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { 78 continue 79 } 80 hello.cipherSuites = append(hello.cipherSuites, suiteId) 81 continue NextCipherSuite 82 } 83 } 84 85 _, err := io.ReadFull(c.config.rand(), hello.random) 86 if err != nil { 87 c.sendAlert(alertInternalError) 88 return errors.New("tls: short read from Rand: " + err.Error()) 89 } 90 91 if hello.vers >= VersionTLS12 { 92 hello.signatureAndHashes = supportedSignatureAlgorithms 93 } 94 95 var session *ClientSessionState 96 var cacheKey string 97 sessionCache := c.config.ClientSessionCache 98 if c.config.SessionTicketsDisabled { 99 sessionCache = nil 100 } 101 102 if sessionCache != nil { 103 hello.ticketSupported = true 104 105 // Try to resume a previously negotiated TLS session, if 106 // available. 107 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) 108 candidateSession, ok := sessionCache.Get(cacheKey) 109 if ok { 110 // Check that the ciphersuite/version used for the 111 // previous session are still valid. 112 cipherSuiteOk := false 113 for _, id := range hello.cipherSuites { 114 if id == candidateSession.cipherSuite { 115 cipherSuiteOk = true 116 break 117 } 118 } 119 120 versOk := candidateSession.vers >= c.config.minVersion() && 121 candidateSession.vers <= c.config.maxVersion() 122 if versOk && cipherSuiteOk { 123 session = candidateSession 124 } 125 } 126 } 127 128 if session != nil { 129 hello.sessionTicket = session.sessionTicket 130 // A random session ID is used to detect when the 131 // server accepted the ticket and is resuming a session 132 // (see RFC 5077). 133 hello.sessionId = make([]byte, 16) 134 if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil { 135 c.sendAlert(alertInternalError) 136 return errors.New("tls: short read from Rand: " + err.Error()) 137 } 138 } 139 140 c.writeRecord(recordTypeHandshake, hello.marshal()) 141 142 msg, err := c.readHandshake() 143 if err != nil { 144 return err 145 } 146 serverHello, ok := msg.(*serverHelloMsg) 147 if !ok { 148 c.sendAlert(alertUnexpectedMessage) 149 return unexpectedMessageError(serverHello, msg) 150 } 151 152 vers, ok := c.config.mutualVersion(serverHello.vers) 153 if !ok || vers < VersionTLS10 { 154 // TLS 1.0 is the minimum version supported as a client. 155 c.sendAlert(alertProtocolVersion) 156 return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers) 157 } 158 c.vers = vers 159 c.haveVers = true 160 161 suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite) 162 if suite == nil { 163 c.sendAlert(alertHandshakeFailure) 164 return fmt.Errorf("tls: server selected an unsupported cipher suite") 165 } 166 167 hs := &clientHandshakeState{ 168 c: c, 169 serverHello: serverHello, 170 hello: hello, 171 suite: suite, 172 finishedHash: newFinishedHash(c.vers, suite), 173 session: session, 174 } 175 176 isResume, err := hs.processServerHello() 177 if err != nil { 178 return err 179 } 180 181 // No signatures of the handshake are needed in a resumption. 182 // Otherwise, in a full handshake, if we don't have any certificates 183 // configured then we will never send a CertificateVerify message and 184 // thus no signatures are needed in that case either. 185 if isResume || len(c.config.Certificates) == 0 { 186 hs.finishedHash.discardHandshakeBuffer() 187 } 188 189 hs.finishedHash.Write(hs.hello.marshal()) 190 hs.finishedHash.Write(hs.serverHello.marshal()) 191 192 if isResume { 193 if err := hs.establishKeys(); err != nil { 194 return err 195 } 196 if err := hs.readSessionTicket(); err != nil { 197 return err 198 } 199 if err := hs.readFinished(c.firstFinished[:]); err != nil { 200 return err 201 } 202 if err := hs.sendFinished(nil); err != nil { 203 return err 204 } 205 } else { 206 if err := hs.doFullHandshake(); err != nil { 207 return err 208 } 209 if err := hs.establishKeys(); err != nil { 210 return err 211 } 212 if err := hs.sendFinished(c.firstFinished[:]); err != nil { 213 return err 214 } 215 if err := hs.readSessionTicket(); err != nil { 216 return err 217 } 218 if err := hs.readFinished(nil); err != nil { 219 return err 220 } 221 } 222 223 if sessionCache != nil && hs.session != nil && session != hs.session { 224 sessionCache.Put(cacheKey, hs.session) 225 } 226 227 c.didResume = isResume 228 c.handshakeComplete = true 229 c.cipherSuite = suite.id 230 return nil 231 } 232 233 func (hs *clientHandshakeState) doFullHandshake() error { 234 c := hs.c 235 236 msg, err := c.readHandshake() 237 if err != nil { 238 return err 239 } 240 certMsg, ok := msg.(*certificateMsg) 241 if !ok || len(certMsg.certificates) == 0 { 242 c.sendAlert(alertUnexpectedMessage) 243 return unexpectedMessageError(certMsg, msg) 244 } 245 hs.finishedHash.Write(certMsg.marshal()) 246 247 certs := make([]*x509.Certificate, len(certMsg.certificates)) 248 for i, asn1Data := range certMsg.certificates { 249 cert, err := x509.ParseCertificate(asn1Data) 250 if err != nil { 251 c.sendAlert(alertBadCertificate) 252 return errors.New("tls: failed to parse certificate from server: " + err.Error()) 253 } 254 certs[i] = cert 255 } 256 257 if !c.config.InsecureSkipVerify { 258 opts := x509.VerifyOptions{ 259 Roots: c.config.RootCAs, 260 CurrentTime: c.config.time(), 261 DNSName: c.config.ServerName, 262 Intermediates: x509.NewCertPool(), 263 } 264 265 for i, cert := range certs { 266 if i == 0 { 267 continue 268 } 269 opts.Intermediates.AddCert(cert) 270 } 271 c.verifiedChains, err = certs[0].Verify(opts) 272 if err != nil { 273 c.sendAlert(alertBadCertificate) 274 return err 275 } 276 } 277 278 switch certs[0].PublicKey.(type) { 279 case *rsa.PublicKey, *ecdsa.PublicKey: 280 break 281 default: 282 c.sendAlert(alertUnsupportedCertificate) 283 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) 284 } 285 286 c.peerCertificates = certs 287 288 if hs.serverHello.ocspStapling { 289 msg, err = c.readHandshake() 290 if err != nil { 291 return err 292 } 293 cs, ok := msg.(*certificateStatusMsg) 294 if !ok { 295 c.sendAlert(alertUnexpectedMessage) 296 return unexpectedMessageError(cs, msg) 297 } 298 hs.finishedHash.Write(cs.marshal()) 299 300 if cs.statusType == statusTypeOCSP { 301 c.ocspResponse = cs.response 302 } 303 } 304 305 msg, err = c.readHandshake() 306 if err != nil { 307 return err 308 } 309 310 keyAgreement := hs.suite.ka(c.vers) 311 312 skx, ok := msg.(*serverKeyExchangeMsg) 313 if ok { 314 hs.finishedHash.Write(skx.marshal()) 315 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx) 316 if err != nil { 317 c.sendAlert(alertUnexpectedMessage) 318 return err 319 } 320 321 msg, err = c.readHandshake() 322 if err != nil { 323 return err 324 } 325 } 326 327 var chainToSend *Certificate 328 var certRequested bool 329 certReq, ok := msg.(*certificateRequestMsg) 330 if ok { 331 certRequested = true 332 333 // RFC 4346 on the certificateAuthorities field: 334 // A list of the distinguished names of acceptable certificate 335 // authorities. These distinguished names may specify a desired 336 // distinguished name for a root CA or for a subordinate CA; 337 // thus, this message can be used to describe both known roots 338 // and a desired authorization space. If the 339 // certificate_authorities list is empty then the client MAY 340 // send any certificate of the appropriate 341 // ClientCertificateType, unless there is some external 342 // arrangement to the contrary. 343 344 hs.finishedHash.Write(certReq.marshal()) 345 346 var rsaAvail, ecdsaAvail bool 347 for _, certType := range certReq.certificateTypes { 348 switch certType { 349 case certTypeRSASign: 350 rsaAvail = true 351 case certTypeECDSASign: 352 ecdsaAvail = true 353 } 354 } 355 356 // We need to search our list of client certs for one 357 // where SignatureAlgorithm is acceptable to the server and the 358 // Issuer is in certReq.certificateAuthorities 359 findCert: 360 for i, chain := range c.config.Certificates { 361 if !rsaAvail && !ecdsaAvail { 362 continue 363 } 364 365 for j, cert := range chain.Certificate { 366 x509Cert := chain.Leaf 367 // parse the certificate if this isn't the leaf 368 // node, or if chain.Leaf was nil 369 if j != 0 || x509Cert == nil { 370 if x509Cert, err = x509.ParseCertificate(cert); err != nil { 371 c.sendAlert(alertInternalError) 372 return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) 373 } 374 } 375 376 switch { 377 case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA: 378 case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA: 379 default: 380 continue findCert 381 } 382 383 if len(certReq.certificateAuthorities) == 0 { 384 // they gave us an empty list, so just take the 385 // first cert from c.config.Certificates 386 chainToSend = &chain 387 break findCert 388 } 389 390 for _, ca := range certReq.certificateAuthorities { 391 if bytes.Equal(x509Cert.RawIssuer, ca) { 392 chainToSend = &chain 393 break findCert 394 } 395 } 396 } 397 } 398 399 msg, err = c.readHandshake() 400 if err != nil { 401 return err 402 } 403 } 404 405 shd, ok := msg.(*serverHelloDoneMsg) 406 if !ok { 407 c.sendAlert(alertUnexpectedMessage) 408 return unexpectedMessageError(shd, msg) 409 } 410 hs.finishedHash.Write(shd.marshal()) 411 412 // If the server requested a certificate then we have to send a 413 // Certificate message, even if it's empty because we don't have a 414 // certificate to send. 415 if certRequested { 416 certMsg = new(certificateMsg) 417 if chainToSend != nil { 418 certMsg.certificates = chainToSend.Certificate 419 } 420 hs.finishedHash.Write(certMsg.marshal()) 421 c.writeRecord(recordTypeHandshake, certMsg.marshal()) 422 } 423 424 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0]) 425 if err != nil { 426 c.sendAlert(alertInternalError) 427 return err 428 } 429 if ckx != nil { 430 hs.finishedHash.Write(ckx.marshal()) 431 c.writeRecord(recordTypeHandshake, ckx.marshal()) 432 } 433 434 if chainToSend != nil { 435 certVerify := &certificateVerifyMsg{ 436 hasSignatureAndHash: c.vers >= VersionTLS12, 437 } 438 439 key, ok := chainToSend.PrivateKey.(crypto.Signer) 440 if !ok { 441 c.sendAlert(alertInternalError) 442 return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) 443 } 444 445 var signatureType uint8 446 switch key.Public().(type) { 447 case *ecdsa.PublicKey: 448 signatureType = signatureECDSA 449 case *rsa.PublicKey: 450 signatureType = signatureRSA 451 default: 452 c.sendAlert(alertInternalError) 453 return fmt.Errorf("tls: failed to sign handshake with client certificate: unknown client certificate key type: %T", key) 454 } 455 456 certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureType) 457 if err != nil { 458 c.sendAlert(alertInternalError) 459 return err 460 } 461 digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret) 462 if err != nil { 463 c.sendAlert(alertInternalError) 464 return err 465 } 466 certVerify.signature, err = key.Sign(c.config.rand(), digest, hashFunc) 467 if err != nil { 468 c.sendAlert(alertInternalError) 469 return err 470 } 471 472 hs.finishedHash.Write(certVerify.marshal()) 473 c.writeRecord(recordTypeHandshake, certVerify.marshal()) 474 } 475 476 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) 477 478 hs.finishedHash.discardHandshakeBuffer() 479 480 return nil 481 } 482 483 func (hs *clientHandshakeState) establishKeys() error { 484 c := hs.c 485 486 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := 487 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) 488 var clientCipher, serverCipher interface{} 489 var clientHash, serverHash macFunction 490 if hs.suite.cipher != nil { 491 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) 492 clientHash = hs.suite.mac(c.vers, clientMAC) 493 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) 494 serverHash = hs.suite.mac(c.vers, serverMAC) 495 } else { 496 clientCipher = hs.suite.aead(clientKey, clientIV) 497 serverCipher = hs.suite.aead(serverKey, serverIV) 498 } 499 500 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) 501 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) 502 return nil 503 } 504 505 func (hs *clientHandshakeState) serverResumedSession() bool { 506 // If the server responded with the same sessionId then it means the 507 // sessionTicket is being used to resume a TLS session. 508 return hs.session != nil && hs.hello.sessionId != nil && 509 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) 510 } 511 512 func (hs *clientHandshakeState) processServerHello() (bool, error) { 513 c := hs.c 514 515 if hs.serverHello.compressionMethod != compressionNone { 516 c.sendAlert(alertUnexpectedMessage) 517 return false, errors.New("tls: server selected unsupported compression format") 518 } 519 520 clientDidNPN := hs.hello.nextProtoNeg 521 clientDidALPN := len(hs.hello.alpnProtocols) > 0 522 serverHasNPN := hs.serverHello.nextProtoNeg 523 serverHasALPN := len(hs.serverHello.alpnProtocol) > 0 524 525 if !clientDidNPN && serverHasNPN { 526 c.sendAlert(alertHandshakeFailure) 527 return false, errors.New("server advertised unrequested NPN extension") 528 } 529 530 if !clientDidALPN && serverHasALPN { 531 c.sendAlert(alertHandshakeFailure) 532 return false, errors.New("server advertised unrequested ALPN extension") 533 } 534 535 if serverHasNPN && serverHasALPN { 536 c.sendAlert(alertHandshakeFailure) 537 return false, errors.New("server advertised both NPN and ALPN extensions") 538 } 539 540 if serverHasALPN { 541 c.clientProtocol = hs.serverHello.alpnProtocol 542 c.clientProtocolFallback = false 543 } 544 c.scts = hs.serverHello.scts 545 546 if hs.serverResumedSession() { 547 // Restore masterSecret and peerCerts from previous state 548 hs.masterSecret = hs.session.masterSecret 549 c.peerCertificates = hs.session.serverCertificates 550 c.verifiedChains = hs.session.verifiedChains 551 return true, nil 552 } 553 return false, nil 554 } 555 556 func (hs *clientHandshakeState) readFinished(out []byte) error { 557 c := hs.c 558 559 c.readRecord(recordTypeChangeCipherSpec) 560 if err := c.in.error(); err != nil { 561 return err 562 } 563 564 msg, err := c.readHandshake() 565 if err != nil { 566 return err 567 } 568 serverFinished, ok := msg.(*finishedMsg) 569 if !ok { 570 c.sendAlert(alertUnexpectedMessage) 571 return unexpectedMessageError(serverFinished, msg) 572 } 573 574 verify := hs.finishedHash.serverSum(hs.masterSecret) 575 if len(verify) != len(serverFinished.verifyData) || 576 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { 577 c.sendAlert(alertHandshakeFailure) 578 return errors.New("tls: server's Finished message was incorrect") 579 } 580 hs.finishedHash.Write(serverFinished.marshal()) 581 copy(out, verify) 582 return nil 583 } 584 585 func (hs *clientHandshakeState) readSessionTicket() error { 586 if !hs.serverHello.ticketSupported { 587 return nil 588 } 589 590 c := hs.c 591 msg, err := c.readHandshake() 592 if err != nil { 593 return err 594 } 595 sessionTicketMsg, ok := msg.(*newSessionTicketMsg) 596 if !ok { 597 c.sendAlert(alertUnexpectedMessage) 598 return unexpectedMessageError(sessionTicketMsg, msg) 599 } 600 hs.finishedHash.Write(sessionTicketMsg.marshal()) 601 602 hs.session = &ClientSessionState{ 603 sessionTicket: sessionTicketMsg.ticket, 604 vers: c.vers, 605 cipherSuite: hs.suite.id, 606 masterSecret: hs.masterSecret, 607 serverCertificates: c.peerCertificates, 608 verifiedChains: c.verifiedChains, 609 } 610 611 return nil 612 } 613 614 func (hs *clientHandshakeState) sendFinished(out []byte) error { 615 c := hs.c 616 617 c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) 618 if hs.serverHello.nextProtoNeg { 619 nextProto := new(nextProtoMsg) 620 proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos) 621 nextProto.proto = proto 622 c.clientProtocol = proto 623 c.clientProtocolFallback = fallback 624 625 hs.finishedHash.Write(nextProto.marshal()) 626 c.writeRecord(recordTypeHandshake, nextProto.marshal()) 627 } 628 629 finished := new(finishedMsg) 630 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) 631 hs.finishedHash.Write(finished.marshal()) 632 c.writeRecord(recordTypeHandshake, finished.marshal()) 633 copy(out, finished.verifyData) 634 return nil 635 } 636 637 // clientSessionCacheKey returns a key used to cache sessionTickets that could 638 // be used to resume previously negotiated TLS sessions with a server. 639 func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { 640 if len(config.ServerName) > 0 { 641 return config.ServerName 642 } 643 return serverAddr.String() 644 } 645 646 // mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol 647 // given list of possible protocols and a list of the preference order. The 648 // first list must not be empty. It returns the resulting protocol and flag 649 // indicating if the fallback case was reached. 650 func mutualProtocol(protos, preferenceProtos []string) (string, bool) { 651 for _, s := range preferenceProtos { 652 for _, c := range protos { 653 if s == c { 654 return s, false 655 } 656 } 657 } 658 659 return protos[0], true 660 }