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