github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/crypto/tls/handshake_server.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  	"crypto"
     9  	"crypto/ecdsa"
    10  	"crypto/rsa"
    11  	"crypto/subtle"
    12  	"crypto/x509"
    13  	"encoding/asn1"
    14  	"errors"
    15  	"fmt"
    16  	"io"
    17  )
    18  
    19  // serverHandshakeState contains details of a server handshake in progress.
    20  // It's discarded once the handshake has completed.
    21  type serverHandshakeState struct {
    22  	c               *Conn
    23  	clientHello     *clientHelloMsg
    24  	hello           *serverHelloMsg
    25  	suite           *cipherSuite
    26  	ellipticOk      bool
    27  	ecdsaOk         bool
    28  	sessionState    *sessionState
    29  	finishedHash    finishedHash
    30  	masterSecret    []byte
    31  	certsFromClient [][]byte
    32  	cert            *Certificate
    33  }
    34  
    35  // serverHandshake performs a TLS handshake as a server.
    36  func (c *Conn) serverHandshake() error {
    37  	config := c.config
    38  
    39  	// If this is the first server handshake, we generate a random key to
    40  	// encrypt the tickets with.
    41  	config.serverInitOnce.Do(config.serverInit)
    42  
    43  	hs := serverHandshakeState{
    44  		c: c,
    45  	}
    46  	isResume, err := hs.readClientHello()
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
    52  	if isResume {
    53  		// The client has included a session ticket and so we do an abbreviated handshake.
    54  		if err := hs.doResumeHandshake(); err != nil {
    55  			return err
    56  		}
    57  		if err := hs.establishKeys(); err != nil {
    58  			return err
    59  		}
    60  		if err := hs.sendFinished(); err != nil {
    61  			return err
    62  		}
    63  		if err := hs.readFinished(); err != nil {
    64  			return err
    65  		}
    66  		c.didResume = true
    67  	} else {
    68  		// The client didn't include a session ticket, or it wasn't
    69  		// valid so we do a full handshake.
    70  		if err := hs.doFullHandshake(); err != nil {
    71  			return err
    72  		}
    73  		if err := hs.establishKeys(); err != nil {
    74  			return err
    75  		}
    76  		if err := hs.readFinished(); err != nil {
    77  			return err
    78  		}
    79  		if err := hs.sendSessionTicket(); err != nil {
    80  			return err
    81  		}
    82  		if err := hs.sendFinished(); err != nil {
    83  			return err
    84  		}
    85  	}
    86  	c.handshakeComplete = true
    87  
    88  	return nil
    89  }
    90  
    91  // readClientHello reads a ClientHello message from the client and decides
    92  // whether we will perform session resumption.
    93  func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
    94  	config := hs.c.config
    95  	c := hs.c
    96  
    97  	msg, err := c.readHandshake()
    98  	if err != nil {
    99  		return false, err
   100  	}
   101  	var ok bool
   102  	hs.clientHello, ok = msg.(*clientHelloMsg)
   103  	if !ok {
   104  		c.sendAlert(alertUnexpectedMessage)
   105  		return false, unexpectedMessageError(hs.clientHello, msg)
   106  	}
   107  	c.vers, ok = config.mutualVersion(hs.clientHello.vers)
   108  	if !ok {
   109  		c.sendAlert(alertProtocolVersion)
   110  		return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
   111  	}
   112  	c.haveVers = true
   113  
   114  	hs.finishedHash = newFinishedHash(c.vers)
   115  	hs.finishedHash.Write(hs.clientHello.marshal())
   116  
   117  	hs.hello = new(serverHelloMsg)
   118  
   119  	supportedCurve := false
   120  	preferredCurves := config.curvePreferences()
   121  Curves:
   122  	for _, curve := range hs.clientHello.supportedCurves {
   123  		for _, supported := range preferredCurves {
   124  			if supported == curve {
   125  				supportedCurve = true
   126  				break Curves
   127  			}
   128  		}
   129  	}
   130  
   131  	supportedPointFormat := false
   132  	for _, pointFormat := range hs.clientHello.supportedPoints {
   133  		if pointFormat == pointFormatUncompressed {
   134  			supportedPointFormat = true
   135  			break
   136  		}
   137  	}
   138  	hs.ellipticOk = supportedCurve && supportedPointFormat
   139  
   140  	foundCompression := false
   141  	// We only support null compression, so check that the client offered it.
   142  	for _, compression := range hs.clientHello.compressionMethods {
   143  		if compression == compressionNone {
   144  			foundCompression = true
   145  			break
   146  		}
   147  	}
   148  
   149  	if !foundCompression {
   150  		c.sendAlert(alertHandshakeFailure)
   151  		return false, errors.New("tls: client does not support uncompressed connections")
   152  	}
   153  
   154  	hs.hello.vers = c.vers
   155  	hs.hello.random = make([]byte, 32)
   156  	_, err = io.ReadFull(config.rand(), hs.hello.random)
   157  	if err != nil {
   158  		c.sendAlert(alertInternalError)
   159  		return false, err
   160  	}
   161  	hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
   162  	hs.hello.compressionMethod = compressionNone
   163  	if len(hs.clientHello.serverName) > 0 {
   164  		c.serverName = hs.clientHello.serverName
   165  	}
   166  	// Although sending an empty NPN extension is reasonable, Firefox has
   167  	// had a bug around this. Best to send nothing at all if
   168  	// config.NextProtos is empty. See
   169  	// https://code.google.com/p/go/issues/detail?id=5445.
   170  	if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
   171  		hs.hello.nextProtoNeg = true
   172  		hs.hello.nextProtos = config.NextProtos
   173  	}
   174  
   175  	if len(config.Certificates) == 0 {
   176  		c.sendAlert(alertInternalError)
   177  		return false, errors.New("tls: no certificates configured")
   178  	}
   179  	hs.cert = &config.Certificates[0]
   180  	if len(hs.clientHello.serverName) > 0 {
   181  		hs.cert = config.getCertificateForName(hs.clientHello.serverName)
   182  	}
   183  
   184  	_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
   185  
   186  	if hs.checkForResumption() {
   187  		return true, nil
   188  	}
   189  
   190  	var preferenceList, supportedList []uint16
   191  	if c.config.PreferServerCipherSuites {
   192  		preferenceList = c.config.cipherSuites()
   193  		supportedList = hs.clientHello.cipherSuites
   194  	} else {
   195  		preferenceList = hs.clientHello.cipherSuites
   196  		supportedList = c.config.cipherSuites()
   197  	}
   198  
   199  	for _, id := range preferenceList {
   200  		if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil {
   201  			break
   202  		}
   203  	}
   204  
   205  	if hs.suite == nil {
   206  		c.sendAlert(alertHandshakeFailure)
   207  		return false, errors.New("tls: no cipher suite supported by both client and server")
   208  	}
   209  
   210  	return false, nil
   211  }
   212  
   213  // checkForResumption returns true if we should perform resumption on this connection.
   214  func (hs *serverHandshakeState) checkForResumption() bool {
   215  	c := hs.c
   216  
   217  	var ok bool
   218  	if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
   219  		return false
   220  	}
   221  
   222  	if hs.sessionState.vers > hs.clientHello.vers {
   223  		return false
   224  	}
   225  	if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
   226  		return false
   227  	}
   228  
   229  	cipherSuiteOk := false
   230  	// Check that the client is still offering the ciphersuite in the session.
   231  	for _, id := range hs.clientHello.cipherSuites {
   232  		if id == hs.sessionState.cipherSuite {
   233  			cipherSuiteOk = true
   234  			break
   235  		}
   236  	}
   237  	if !cipherSuiteOk {
   238  		return false
   239  	}
   240  
   241  	// Check that we also support the ciphersuite from the session.
   242  	hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk)
   243  	if hs.suite == nil {
   244  		return false
   245  	}
   246  
   247  	sessionHasClientCerts := len(hs.sessionState.certificates) != 0
   248  	needClientCerts := c.config.ClientAuth == RequireAnyClientCert || c.config.ClientAuth == RequireAndVerifyClientCert
   249  	if needClientCerts && !sessionHasClientCerts {
   250  		return false
   251  	}
   252  	if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
   253  		return false
   254  	}
   255  
   256  	return true
   257  }
   258  
   259  func (hs *serverHandshakeState) doResumeHandshake() error {
   260  	c := hs.c
   261  
   262  	hs.hello.cipherSuite = hs.suite.id
   263  	// We echo the client's session ID in the ServerHello to let it know
   264  	// that we're doing a resumption.
   265  	hs.hello.sessionId = hs.clientHello.sessionId
   266  	hs.finishedHash.Write(hs.hello.marshal())
   267  	c.writeRecord(recordTypeHandshake, hs.hello.marshal())
   268  
   269  	if len(hs.sessionState.certificates) > 0 {
   270  		if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
   271  			return err
   272  		}
   273  	}
   274  
   275  	hs.masterSecret = hs.sessionState.masterSecret
   276  
   277  	return nil
   278  }
   279  
   280  func (hs *serverHandshakeState) doFullHandshake() error {
   281  	config := hs.c.config
   282  	c := hs.c
   283  
   284  	if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
   285  		hs.hello.ocspStapling = true
   286  	}
   287  
   288  	hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
   289  	hs.hello.cipherSuite = hs.suite.id
   290  	hs.finishedHash.Write(hs.hello.marshal())
   291  	c.writeRecord(recordTypeHandshake, hs.hello.marshal())
   292  
   293  	certMsg := new(certificateMsg)
   294  	certMsg.certificates = hs.cert.Certificate
   295  	hs.finishedHash.Write(certMsg.marshal())
   296  	c.writeRecord(recordTypeHandshake, certMsg.marshal())
   297  
   298  	if hs.hello.ocspStapling {
   299  		certStatus := new(certificateStatusMsg)
   300  		certStatus.statusType = statusTypeOCSP
   301  		certStatus.response = hs.cert.OCSPStaple
   302  		hs.finishedHash.Write(certStatus.marshal())
   303  		c.writeRecord(recordTypeHandshake, certStatus.marshal())
   304  	}
   305  
   306  	keyAgreement := hs.suite.ka(c.vers)
   307  	skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
   308  	if err != nil {
   309  		c.sendAlert(alertHandshakeFailure)
   310  		return err
   311  	}
   312  	if skx != nil {
   313  		hs.finishedHash.Write(skx.marshal())
   314  		c.writeRecord(recordTypeHandshake, skx.marshal())
   315  	}
   316  
   317  	if config.ClientAuth >= RequestClientCert {
   318  		// Request a client certificate
   319  		certReq := new(certificateRequestMsg)
   320  		certReq.certificateTypes = []byte{
   321  			byte(certTypeRSASign),
   322  			byte(certTypeECDSASign),
   323  		}
   324  		if c.vers >= VersionTLS12 {
   325  			certReq.hasSignatureAndHash = true
   326  			certReq.signatureAndHashes = supportedClientCertSignatureAlgorithms
   327  		}
   328  
   329  		// An empty list of certificateAuthorities signals to
   330  		// the client that it may send any certificate in response
   331  		// to our request. When we know the CAs we trust, then
   332  		// we can send them down, so that the client can choose
   333  		// an appropriate certificate to give to us.
   334  		if config.ClientCAs != nil {
   335  			certReq.certificateAuthorities = config.ClientCAs.Subjects()
   336  		}
   337  		hs.finishedHash.Write(certReq.marshal())
   338  		c.writeRecord(recordTypeHandshake, certReq.marshal())
   339  	}
   340  
   341  	helloDone := new(serverHelloDoneMsg)
   342  	hs.finishedHash.Write(helloDone.marshal())
   343  	c.writeRecord(recordTypeHandshake, helloDone.marshal())
   344  
   345  	var pub crypto.PublicKey // public key for client auth, if any
   346  
   347  	msg, err := c.readHandshake()
   348  	if err != nil {
   349  		return err
   350  	}
   351  
   352  	var ok bool
   353  	// If we requested a client certificate, then the client must send a
   354  	// certificate message, even if it's empty.
   355  	if config.ClientAuth >= RequestClientCert {
   356  		if certMsg, ok = msg.(*certificateMsg); !ok {
   357  			c.sendAlert(alertUnexpectedMessage)
   358  			return unexpectedMessageError(certMsg, msg)
   359  		}
   360  		hs.finishedHash.Write(certMsg.marshal())
   361  
   362  		if len(certMsg.certificates) == 0 {
   363  			// The client didn't actually send a certificate
   364  			switch config.ClientAuth {
   365  			case RequireAnyClientCert, RequireAndVerifyClientCert:
   366  				c.sendAlert(alertBadCertificate)
   367  				return errors.New("tls: client didn't provide a certificate")
   368  			}
   369  		}
   370  
   371  		pub, err = hs.processCertsFromClient(certMsg.certificates)
   372  		if err != nil {
   373  			return err
   374  		}
   375  
   376  		msg, err = c.readHandshake()
   377  		if err != nil {
   378  			return err
   379  		}
   380  	}
   381  
   382  	// Get client key exchange
   383  	ckx, ok := msg.(*clientKeyExchangeMsg)
   384  	if !ok {
   385  		c.sendAlert(alertUnexpectedMessage)
   386  		return unexpectedMessageError(ckx, msg)
   387  	}
   388  	hs.finishedHash.Write(ckx.marshal())
   389  
   390  	// If we received a client cert in response to our certificate request message,
   391  	// the client will send us a certificateVerifyMsg immediately after the
   392  	// clientKeyExchangeMsg.  This message is a digest of all preceding
   393  	// handshake-layer messages that is signed using the private key corresponding
   394  	// to the client's certificate. This allows us to verify that the client is in
   395  	// possession of the private key of the certificate.
   396  	if len(c.peerCertificates) > 0 {
   397  		msg, err = c.readHandshake()
   398  		if err != nil {
   399  			return err
   400  		}
   401  		certVerify, ok := msg.(*certificateVerifyMsg)
   402  		if !ok {
   403  			c.sendAlert(alertUnexpectedMessage)
   404  			return unexpectedMessageError(certVerify, msg)
   405  		}
   406  
   407  		switch key := pub.(type) {
   408  		case *ecdsa.PublicKey:
   409  			ecdsaSig := new(ecdsaSignature)
   410  			if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
   411  				break
   412  			}
   413  			if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
   414  				err = errors.New("ECDSA signature contained zero or negative values")
   415  				break
   416  			}
   417  			digest, _, _ := hs.finishedHash.hashForClientCertificate(signatureECDSA)
   418  			if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
   419  				err = errors.New("ECDSA verification failure")
   420  				break
   421  			}
   422  		case *rsa.PublicKey:
   423  			digest, hashFunc, _ := hs.finishedHash.hashForClientCertificate(signatureRSA)
   424  			err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
   425  		}
   426  		if err != nil {
   427  			c.sendAlert(alertBadCertificate)
   428  			return errors.New("could not validate signature of connection nonces: " + err.Error())
   429  		}
   430  
   431  		hs.finishedHash.Write(certVerify.marshal())
   432  	}
   433  
   434  	preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
   435  	if err != nil {
   436  		c.sendAlert(alertHandshakeFailure)
   437  		return err
   438  	}
   439  	hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.clientHello.random, hs.hello.random)
   440  
   441  	return nil
   442  }
   443  
   444  func (hs *serverHandshakeState) establishKeys() error {
   445  	c := hs.c
   446  
   447  	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
   448  		keysFromMasterSecret(c.vers, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
   449  
   450  	var clientCipher, serverCipher interface{}
   451  	var clientHash, serverHash macFunction
   452  
   453  	if hs.suite.aead == nil {
   454  		clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
   455  		clientHash = hs.suite.mac(c.vers, clientMAC)
   456  		serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
   457  		serverHash = hs.suite.mac(c.vers, serverMAC)
   458  	} else {
   459  		clientCipher = hs.suite.aead(clientKey, clientIV)
   460  		serverCipher = hs.suite.aead(serverKey, serverIV)
   461  	}
   462  
   463  	c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
   464  	c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
   465  
   466  	return nil
   467  }
   468  
   469  func (hs *serverHandshakeState) readFinished() error {
   470  	c := hs.c
   471  
   472  	c.readRecord(recordTypeChangeCipherSpec)
   473  	if err := c.in.error(); err != nil {
   474  		return err
   475  	}
   476  
   477  	if hs.hello.nextProtoNeg {
   478  		msg, err := c.readHandshake()
   479  		if err != nil {
   480  			return err
   481  		}
   482  		nextProto, ok := msg.(*nextProtoMsg)
   483  		if !ok {
   484  			c.sendAlert(alertUnexpectedMessage)
   485  			return unexpectedMessageError(nextProto, msg)
   486  		}
   487  		hs.finishedHash.Write(nextProto.marshal())
   488  		c.clientProtocol = nextProto.proto
   489  	}
   490  
   491  	msg, err := c.readHandshake()
   492  	if err != nil {
   493  		return err
   494  	}
   495  	clientFinished, ok := msg.(*finishedMsg)
   496  	if !ok {
   497  		c.sendAlert(alertUnexpectedMessage)
   498  		return unexpectedMessageError(clientFinished, msg)
   499  	}
   500  
   501  	verify := hs.finishedHash.clientSum(hs.masterSecret)
   502  	if len(verify) != len(clientFinished.verifyData) ||
   503  		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
   504  		c.sendAlert(alertHandshakeFailure)
   505  		return errors.New("tls: client's Finished message is incorrect")
   506  	}
   507  
   508  	hs.finishedHash.Write(clientFinished.marshal())
   509  	return nil
   510  }
   511  
   512  func (hs *serverHandshakeState) sendSessionTicket() error {
   513  	if !hs.hello.ticketSupported {
   514  		return nil
   515  	}
   516  
   517  	c := hs.c
   518  	m := new(newSessionTicketMsg)
   519  
   520  	var err error
   521  	state := sessionState{
   522  		vers:         c.vers,
   523  		cipherSuite:  hs.suite.id,
   524  		masterSecret: hs.masterSecret,
   525  		certificates: hs.certsFromClient,
   526  	}
   527  	m.ticket, err = c.encryptTicket(&state)
   528  	if err != nil {
   529  		return err
   530  	}
   531  
   532  	hs.finishedHash.Write(m.marshal())
   533  	c.writeRecord(recordTypeHandshake, m.marshal())
   534  
   535  	return nil
   536  }
   537  
   538  func (hs *serverHandshakeState) sendFinished() error {
   539  	c := hs.c
   540  
   541  	c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
   542  
   543  	finished := new(finishedMsg)
   544  	finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
   545  	hs.finishedHash.Write(finished.marshal())
   546  	c.writeRecord(recordTypeHandshake, finished.marshal())
   547  
   548  	c.cipherSuite = hs.suite.id
   549  
   550  	return nil
   551  }
   552  
   553  // processCertsFromClient takes a chain of client certificates either from a
   554  // Certificates message or from a sessionState and verifies them. It returns
   555  // the public key of the leaf certificate.
   556  func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
   557  	c := hs.c
   558  
   559  	hs.certsFromClient = certificates
   560  	certs := make([]*x509.Certificate, len(certificates))
   561  	var err error
   562  	for i, asn1Data := range certificates {
   563  		if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
   564  			c.sendAlert(alertBadCertificate)
   565  			return nil, errors.New("tls: failed to parse client certificate: " + err.Error())
   566  		}
   567  	}
   568  
   569  	if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
   570  		opts := x509.VerifyOptions{
   571  			Roots:         c.config.ClientCAs,
   572  			CurrentTime:   c.config.time(),
   573  			Intermediates: x509.NewCertPool(),
   574  			KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
   575  		}
   576  
   577  		for _, cert := range certs[1:] {
   578  			opts.Intermediates.AddCert(cert)
   579  		}
   580  
   581  		chains, err := certs[0].Verify(opts)
   582  		if err != nil {
   583  			c.sendAlert(alertBadCertificate)
   584  			return nil, errors.New("tls: failed to verify client's certificate: " + err.Error())
   585  		}
   586  
   587  		ok := false
   588  		for _, ku := range certs[0].ExtKeyUsage {
   589  			if ku == x509.ExtKeyUsageClientAuth {
   590  				ok = true
   591  				break
   592  			}
   593  		}
   594  		if !ok {
   595  			c.sendAlert(alertHandshakeFailure)
   596  			return nil, errors.New("tls: client's certificate's extended key usage doesn't permit it to be used for client authentication")
   597  		}
   598  
   599  		c.verifiedChains = chains
   600  	}
   601  
   602  	if len(certs) > 0 {
   603  		var pub crypto.PublicKey
   604  		switch key := certs[0].PublicKey.(type) {
   605  		case *ecdsa.PublicKey, *rsa.PublicKey:
   606  			pub = key
   607  		default:
   608  			c.sendAlert(alertUnsupportedCertificate)
   609  			return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
   610  		}
   611  		c.peerCertificates = certs
   612  		return pub, nil
   613  	}
   614  
   615  	return nil, nil
   616  }
   617  
   618  // tryCipherSuite returns a cipherSuite with the given id if that cipher suite
   619  // is acceptable to use.
   620  func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk bool) *cipherSuite {
   621  	for _, supported := range supportedCipherSuites {
   622  		if id == supported {
   623  			var candidate *cipherSuite
   624  
   625  			for _, s := range cipherSuites {
   626  				if s.id == id {
   627  					candidate = s
   628  					break
   629  				}
   630  			}
   631  			if candidate == nil {
   632  				continue
   633  			}
   634  			// Don't select a ciphersuite which we can't
   635  			// support for this client.
   636  			if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
   637  				continue
   638  			}
   639  			if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
   640  				continue
   641  			}
   642  			if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
   643  				continue
   644  			}
   645  			return candidate
   646  		}
   647  	}
   648  
   649  	return nil
   650  }