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