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