blob: a3d8848caf9c354b69b7360ba626fe8ed8ce69c4 [file] [log] [blame]
Adam Langley5e598c52009-11-05 15:44:32 -08001// 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
Adam Langley5e598c52009-11-05 15:44:32 -08007import (
Joel Sing7b7dac52013-07-17 12:33:16 -04008 "crypto"
9 "crypto/ecdsa"
Filippo Valsordaf3533852019-05-16 19:13:29 -040010 "crypto/ed25519"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080011 "crypto/rsa"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080012 "crypto/subtle"
Mikkel Krautzc47123d2010-08-16 11:22:22 -040013 "crypto/x509"
Russ Coxc2049d22011-11-01 22:04:37 -040014 "errors"
Adam Langley6b29f7b2014-02-12 11:20:01 -050015 "fmt"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080016 "io"
Minaev Mikee5b13402018-01-26 09:17:46 +000017 "sync/atomic"
Adam Langley5e598c52009-11-05 15:44:32 -080018)
19
Adam Langley65c7dc42012-09-24 16:52:43 -040020// serverHandshakeState contains details of a server handshake in progress.
21// It's discarded once the handshake has completed.
22type serverHandshakeState struct {
Filippo Valsorda106db712018-11-05 19:23:25 -050023 c *Conn
24 clientHello *clientHelloMsg
25 hello *serverHelloMsg
26 suite *cipherSuite
Filippo Valsordaf3533852019-05-16 19:13:29 -040027 ecdhOk bool
28 ecSignOk bool
Filippo Valsorda106db712018-11-05 19:23:25 -050029 rsaDecryptOk bool
30 rsaSignOk bool
31 sessionState *sessionState
32 finishedHash finishedHash
33 masterSecret []byte
34 cert *Certificate
Adam Langley65c7dc42012-09-24 16:52:43 -040035}
36
37// serverHandshake performs a TLS handshake as a server.
Russ Coxc2049d22011-11-01 22:04:37 -040038func (c *Conn) serverHandshake() error {
Adam Langley65c7dc42012-09-24 16:52:43 -040039 // If this is the first server handshake, we generate a random key to
40 // encrypt the tickets with.
Adam Langley46f4bfb2017-04-28 13:37:52 -070041 c.config.serverInitOnce.Do(func() { c.config.serverInit(nil) })
Adam Langley65c7dc42012-09-24 16:52:43 -040042
Filippo Valsordac21ba092018-11-02 00:57:30 -040043 clientHello, err := c.readClientHello()
Russ Cox72d93222010-04-26 22:19:04 -070044 if err != nil {
45 return err
Adam Langley5e598c52009-11-05 15:44:32 -080046 }
Adam Langley65c7dc42012-09-24 16:52:43 -040047
Filippo Valsordac21ba092018-11-02 00:57:30 -040048 if c.vers == VersionTLS13 {
49 hs := serverHandshakeStateTLS13{
50 c: c,
51 clientHello: clientHello,
52 }
53 return hs.handshake()
54 }
55
56 hs := serverHandshakeState{
57 c: c,
58 clientHello: clientHello,
59 }
60 return hs.handshake()
61}
62
63func (hs *serverHandshakeState) handshake() error {
64 c := hs.c
65
66 if err := hs.processClientHello(); err != nil {
67 return err
68 }
69
Filippo Valsordaee769922018-10-12 17:07:04 -040070 // For an overview of TLS handshaking, see RFC 5246, Section 7.3.
Adam Langley2a8c81f2016-06-01 14:41:09 -070071 c.buffering = true
Filippo Valsordac21ba092018-11-02 00:57:30 -040072 if hs.checkForResumption() {
Adam Langley65c7dc42012-09-24 16:52:43 -040073 // The client has included a session ticket and so we do an abbreviated handshake.
74 if err := hs.doResumeHandshake(); err != nil {
75 return err
76 }
77 if err := hs.establishKeys(); err != nil {
78 return err
79 }
Jonathan Rudenbergbff14172015-04-17 21:32:11 -040080 // ticketSupported is set in a resumption handshake if the
81 // ticket from the client was encrypted with an old session
82 // ticket key and thus a refreshed ticket should be sent.
83 if hs.hello.ticketSupported {
84 if err := hs.sendSessionTicket(); err != nil {
85 return err
86 }
87 }
Adam Langleyaf125a52016-04-26 10:45:35 -070088 if err := hs.sendFinished(c.serverFinished[:]); err != nil {
Adam Langley65c7dc42012-09-24 16:52:43 -040089 return err
90 }
Adam Langley2a8c81f2016-06-01 14:41:09 -070091 if _, err := c.flush(); err != nil {
92 return err
93 }
Adam Langleyaf125a52016-04-26 10:45:35 -070094 c.clientFinishedIsFirst = false
Andres Erbsenfce63882014-08-11 16:40:42 -070095 if err := hs.readFinished(nil); err != nil {
Adam Langley65c7dc42012-09-24 16:52:43 -040096 return err
97 }
98 c.didResume = true
99 } else {
100 // The client didn't include a session ticket, or it wasn't
101 // valid so we do a full handshake.
Filippo Valsordac21ba092018-11-02 00:57:30 -0400102 if err := hs.pickCipherSuite(); err != nil {
103 return err
104 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400105 if err := hs.doFullHandshake(); err != nil {
106 return err
107 }
108 if err := hs.establishKeys(); err != nil {
109 return err
110 }
Adam Langleyaf125a52016-04-26 10:45:35 -0700111 if err := hs.readFinished(c.clientFinished[:]); err != nil {
Adam Langley65c7dc42012-09-24 16:52:43 -0400112 return err
113 }
Adam Langleyaf125a52016-04-26 10:45:35 -0700114 c.clientFinishedIsFirst = true
Adam Langley2a8c81f2016-06-01 14:41:09 -0700115 c.buffering = true
Adam Langley65c7dc42012-09-24 16:52:43 -0400116 if err := hs.sendSessionTicket(); err != nil {
117 return err
118 }
Andres Erbsenfce63882014-08-11 16:40:42 -0700119 if err := hs.sendFinished(nil); err != nil {
Adam Langley65c7dc42012-09-24 16:52:43 -0400120 return err
121 }
Adam Langley2a8c81f2016-06-01 14:41:09 -0700122 if _, err := c.flush(); err != nil {
123 return err
124 }
Adam Langley5e598c52009-11-05 15:44:32 -0800125 }
Mike Danesec5291412017-12-20 19:47:49 -0800126
127 c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random)
Minaev Mikee5b13402018-01-26 09:17:46 +0000128 atomic.StoreUint32(&c.handshakeStatus, 1)
Adam Langley65c7dc42012-09-24 16:52:43 -0400129
130 return nil
131}
132
Filippo Valsordac21ba092018-11-02 00:57:30 -0400133// readClientHello reads a ClientHello message and selects the protocol version.
134func (c *Conn) readClientHello() (*clientHelloMsg, error) {
Adam Langley65c7dc42012-09-24 16:52:43 -0400135 msg, err := c.readHandshake()
136 if err != nil {
Filippo Valsordac21ba092018-11-02 00:57:30 -0400137 return nil, err
Russ Cox72d93222010-04-26 22:19:04 -0700138 }
Filippo Valsordac21ba092018-11-02 00:57:30 -0400139 clientHello, ok := msg.(*clientHelloMsg)
Adam Langley65c7dc42012-09-24 16:52:43 -0400140 if !ok {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500141 c.sendAlert(alertUnexpectedMessage)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400142 return nil, unexpectedMessageError(clientHello, msg)
Adam Langley65c7dc42012-09-24 16:52:43 -0400143 }
Adam Langleycff3e752016-10-10 15:27:34 -0700144
Adam Langleycff3e752016-10-10 15:27:34 -0700145 if c.config.GetConfigForClient != nil {
Filippo Valsordac21ba092018-11-02 00:57:30 -0400146 chi := clientHelloInfo(c, clientHello)
147 if newConfig, err := c.config.GetConfigForClient(chi); err != nil {
Adam Langleycff3e752016-10-10 15:27:34 -0700148 c.sendAlert(alertInternalError)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400149 return nil, err
Adam Langleycff3e752016-10-10 15:27:34 -0700150 } else if newConfig != nil {
Adam Langley46f4bfb2017-04-28 13:37:52 -0700151 newConfig.serverInitOnce.Do(func() { newConfig.serverInit(c.config) })
Adam Langleycff3e752016-10-10 15:27:34 -0700152 c.config = newConfig
153 }
154 }
155
Filippo Valsordac21ba092018-11-02 00:57:30 -0400156 clientVersions := clientHello.supportedVersions
157 if len(clientHello.supportedVersions) == 0 {
158 clientVersions = supportedVersionsFromMax(clientHello.vers)
Filippo Valsorda7f5dce02018-10-31 09:34:10 -0400159 }
160 c.vers, ok = c.config.mutualVersion(false, clientVersions)
Adam Langley65c7dc42012-09-24 16:52:43 -0400161 if !ok {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500162 c.sendAlert(alertProtocolVersion)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400163 return nil, fmt.Errorf("tls: client offered only unsupported versions: %x", clientVersions)
Adam Langley65c7dc42012-09-24 16:52:43 -0400164 }
Russ Cox72d93222010-04-26 22:19:04 -0700165 c.haveVers = true
Filippo Valsordac21ba092018-11-02 00:57:30 -0400166 c.in.version = c.vers
167 c.out.version = c.vers
168
169 return clientHello, nil
170}
171
172func (hs *serverHandshakeState) processClientHello() error {
173 c := hs.c
Adam Langley5e598c52009-11-05 15:44:32 -0800174
Adam Langley65c7dc42012-09-24 16:52:43 -0400175 hs.hello = new(serverHelloMsg)
Filippo Valsorda7f5dce02018-10-31 09:34:10 -0400176 hs.hello.vers = c.vers
Adam Langley5e598c52009-11-05 15:44:32 -0800177
Adam Langley4883b732010-12-16 17:10:50 -0500178 supportedCurve := false
Adam Langleycff3e752016-10-10 15:27:34 -0700179 preferredCurves := c.config.curvePreferences()
Adam Langley4883b732010-12-16 17:10:50 -0500180Curves:
Adam Langley65c7dc42012-09-24 16:52:43 -0400181 for _, curve := range hs.clientHello.supportedCurves {
Adam Langleydb99a8f2014-02-24 17:57:51 -0500182 for _, supported := range preferredCurves {
183 if supported == curve {
184 supportedCurve = true
185 break Curves
186 }
Adam Langley4883b732010-12-16 17:10:50 -0500187 }
188 }
189
190 supportedPointFormat := false
Adam Langley65c7dc42012-09-24 16:52:43 -0400191 for _, pointFormat := range hs.clientHello.supportedPoints {
Adam Langley4883b732010-12-16 17:10:50 -0500192 if pointFormat == pointFormatUncompressed {
193 supportedPointFormat = true
194 break
195 }
196 }
Filippo Valsordaf3533852019-05-16 19:13:29 -0400197 hs.ecdhOk = supportedCurve && supportedPointFormat
Adam Langley5e598c52009-11-05 15:44:32 -0800198
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800199 foundCompression := false
Adam Langley5e598c52009-11-05 15:44:32 -0800200 // We only support null compression, so check that the client offered it.
Adam Langley65c7dc42012-09-24 16:52:43 -0400201 for _, compression := range hs.clientHello.compressionMethods {
Adam Langley5e598c52009-11-05 15:44:32 -0800202 if compression == compressionNone {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800203 foundCompression = true
204 break
Adam Langley5e598c52009-11-05 15:44:32 -0800205 }
206 }
207
Adam Langley65c7dc42012-09-24 16:52:43 -0400208 if !foundCompression {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500209 c.sendAlert(alertHandshakeFailure)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400210 return errors.New("tls: client does not support uncompressed connections")
Adam Langley5e598c52009-11-05 15:44:32 -0800211 }
212
Adam Langley65c7dc42012-09-24 16:52:43 -0400213 hs.hello.random = make([]byte, 32)
Filippo Valsorda46d4aa22018-11-05 20:39:45 -0500214 serverRandom := hs.hello.random
215 // Downgrade protection canaries. See RFC 8446, Section 4.1.3.
216 maxVers := c.config.maxSupportedVersion(false)
217 if maxVers >= VersionTLS12 && c.vers < maxVers {
218 if c.vers == VersionTLS12 {
219 copy(serverRandom[24:], downgradeCanaryTLS12)
220 } else {
221 copy(serverRandom[24:], downgradeCanaryTLS11)
222 }
223 serverRandom = serverRandom[:24]
224 }
225 _, err := io.ReadFull(c.config.rand(), serverRandom)
Adam Langley5e598c52009-11-05 15:44:32 -0800226 if err != nil {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500227 c.sendAlert(alertInternalError)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400228 return err
Adam Langley5e598c52009-11-05 15:44:32 -0800229 }
Adam Langleyaf125a52016-04-26 10:45:35 -0700230
231 if len(hs.clientHello.secureRenegotiation) != 0 {
232 c.sendAlert(alertHandshakeFailure)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400233 return errors.New("tls: initial handshake had non-empty renegotiation extension")
Adam Langleyaf125a52016-04-26 10:45:35 -0700234 }
235
236 hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported
Adam Langley65c7dc42012-09-24 16:52:43 -0400237 hs.hello.compressionMethod = compressionNone
238 if len(hs.clientHello.serverName) > 0 {
239 c.serverName = hs.clientHello.serverName
Adam Langley9ebb5962009-12-23 11:13:09 -0800240 }
Adam Langleyd0e255f2014-08-05 11:36:20 -0700241
242 if len(hs.clientHello.alpnProtocols) > 0 {
243 if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
244 hs.hello.alpnProtocol = selectedProto
245 c.clientProtocol = selectedProto
246 }
247 } else {
248 // Although sending an empty NPN extension is reasonable, Firefox has
249 // had a bug around this. Best to send nothing at all if
Adam Langleycff3e752016-10-10 15:27:34 -0700250 // c.config.NextProtos is empty. See
Péter Surányi9b6ccb12015-02-06 21:44:39 +0900251 // https://golang.org/issue/5445.
Adam Langleycff3e752016-10-10 15:27:34 -0700252 if hs.clientHello.nextProtoNeg && len(c.config.NextProtos) > 0 {
Adam Langleyd0e255f2014-08-05 11:36:20 -0700253 hs.hello.nextProtoNeg = true
Adam Langleycff3e752016-10-10 15:27:34 -0700254 hs.hello.nextProtos = c.config.NextProtos
Adam Langleyd0e255f2014-08-05 11:36:20 -0700255 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400256 }
257
Filippo Valsordac21ba092018-11-02 00:57:30 -0400258 hs.cert, err = c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
Emmanuel Odekef0711b92016-03-14 03:35:13 -0600259 if err != nil {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500260 c.sendAlert(alertInternalError)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400261 return err
Adam Langleyeef70352013-09-17 13:30:36 -0400262 }
Jonathan Rudenberg02e69c42015-04-16 14:59:22 -0400263 if hs.clientHello.scts {
264 hs.hello.scts = hs.cert.SignedCertificateTimestamps
265 }
Adam Langleyeef70352013-09-17 13:30:36 -0400266
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700267 if priv, ok := hs.cert.PrivateKey.(crypto.Signer); ok {
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700268 switch priv.Public().(type) {
269 case *ecdsa.PublicKey:
Filippo Valsordaf3533852019-05-16 19:13:29 -0400270 hs.ecSignOk = true
271 case ed25519.PublicKey:
272 hs.ecSignOk = true
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700273 case *rsa.PublicKey:
Adam Langley7b850ec62015-04-02 16:19:46 -0700274 hs.rsaSignOk = true
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700275 default:
276 c.sendAlert(alertInternalError)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400277 return fmt.Errorf("tls: unsupported signing key type (%T)", priv.Public())
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700278 }
279 }
280 if priv, ok := hs.cert.PrivateKey.(crypto.Decrypter); ok {
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700281 switch priv.Public().(type) {
282 case *rsa.PublicKey:
Adam Langley7b850ec62015-04-02 16:19:46 -0700283 hs.rsaDecryptOk = true
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700284 default:
285 c.sendAlert(alertInternalError)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400286 return fmt.Errorf("tls: unsupported decryption key type (%T)", priv.Public())
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700287 }
288 }
Adam Langleyeef70352013-09-17 13:30:36 -0400289
Filippo Valsordac21ba092018-11-02 00:57:30 -0400290 return nil
291}
292
293func (hs *serverHandshakeState) pickCipherSuite() error {
294 c := hs.c
Adam Langley65c7dc42012-09-24 16:52:43 -0400295
Adam Langley793cbd52013-01-22 10:10:38 -0500296 var preferenceList, supportedList []uint16
297 if c.config.PreferServerCipherSuites {
298 preferenceList = c.config.cipherSuites()
299 supportedList = hs.clientHello.cipherSuites
300 } else {
301 preferenceList = hs.clientHello.cipherSuites
302 supportedList = c.config.cipherSuites()
303 }
304
305 for _, id := range preferenceList {
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700306 if hs.setCipherSuite(id, supportedList, c.vers) {
Adam Langley65c7dc42012-09-24 16:52:43 -0400307 break
308 }
309 }
310
311 if hs.suite == nil {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500312 c.sendAlert(alertHandshakeFailure)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400313 return errors.New("tls: no cipher suite supported by both client and server")
Adam Langley65c7dc42012-09-24 16:52:43 -0400314 }
315
Adam Langleye5624ed2014-10-15 17:54:04 -0700316 for _, id := range hs.clientHello.cipherSuites {
317 if id == TLS_FALLBACK_SCSV {
Filippo Valsorda46d4aa22018-11-05 20:39:45 -0500318 // The client is doing a fallback connection. See RFC 7507.
319 if hs.clientHello.vers < c.config.maxSupportedVersion(false) {
Adam Langleye5624ed2014-10-15 17:54:04 -0700320 c.sendAlert(alertInappropriateFallback)
Filippo Valsordac21ba092018-11-02 00:57:30 -0400321 return errors.New("tls: client using inappropriate protocol fallback")
Adam Langleye5624ed2014-10-15 17:54:04 -0700322 }
323 break
324 }
325 }
326
Filippo Valsordac21ba092018-11-02 00:57:30 -0400327 return nil
Adam Langley65c7dc42012-09-24 16:52:43 -0400328}
329
Josh Bleecher Snyder2adc4e82015-02-17 15:44:42 -0800330// checkForResumption reports whether we should perform resumption on this connection.
Adam Langley65c7dc42012-09-24 16:52:43 -0400331func (hs *serverHandshakeState) checkForResumption() bool {
332 c := hs.c
333
Adam Langley64df53e2014-09-26 11:02:09 +1000334 if c.config.SessionTicketsDisabled {
335 return false
336 }
337
Filippo Valsorda6435d0c2018-11-05 15:59:08 -0500338 plaintext, usedOldKey := c.decryptTicket(hs.clientHello.sessionTicket)
339 if plaintext == nil {
340 return false
341 }
342 hs.sessionState = &sessionState{usedOldKey: usedOldKey}
343 ok := hs.sessionState.unmarshal(plaintext)
344 if !ok {
Adam Langley65c7dc42012-09-24 16:52:43 -0400345 return false
346 }
347
David Benjaminebbe4f82016-02-15 11:41:40 -0500348 // Never resume a session for a different TLS version.
349 if c.vers != hs.sessionState.vers {
Adam Langley65c7dc42012-09-24 16:52:43 -0400350 return false
351 }
352
353 cipherSuiteOk := false
354 // Check that the client is still offering the ciphersuite in the session.
355 for _, id := range hs.clientHello.cipherSuites {
356 if id == hs.sessionState.cipherSuite {
357 cipherSuiteOk = true
358 break
359 }
360 }
361 if !cipherSuiteOk {
362 return false
363 }
364
365 // Check that we also support the ciphersuite from the session.
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700366 if !hs.setCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers) {
Adam Langley65c7dc42012-09-24 16:52:43 -0400367 return false
368 }
369
370 sessionHasClientCerts := len(hs.sessionState.certificates) != 0
Filippo Valsorda6435d0c2018-11-05 15:59:08 -0500371 needClientCerts := requiresClientCert(c.config.ClientAuth)
Adam Langley65c7dc42012-09-24 16:52:43 -0400372 if needClientCerts && !sessionHasClientCerts {
373 return false
374 }
375 if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
376 return false
377 }
378
379 return true
380}
381
382func (hs *serverHandshakeState) doResumeHandshake() error {
383 c := hs.c
384
385 hs.hello.cipherSuite = hs.suite.id
386 // We echo the client's session ID in the ServerHello to let it know
387 // that we're doing a resumption.
388 hs.hello.sessionId = hs.clientHello.sessionId
Jonathan Rudenbergbff14172015-04-17 21:32:11 -0400389 hs.hello.ticketSupported = hs.sessionState.usedOldKey
Adam Langley09b238f2015-04-28 09:13:38 -0700390 hs.finishedHash = newFinishedHash(c.vers, hs.suite)
391 hs.finishedHash.discardHandshakeBuffer()
392 hs.finishedHash.Write(hs.clientHello.marshal())
Adam Langley65c7dc42012-09-24 16:52:43 -0400393 hs.finishedHash.Write(hs.hello.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500394 if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
395 return err
396 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400397
Filippo Valsorda106db712018-11-05 19:23:25 -0500398 if err := c.processCertsFromClient(Certificate{
399 Certificate: hs.sessionState.certificates,
400 }); err != nil {
401 return err
Adam Langley65c7dc42012-09-24 16:52:43 -0400402 }
403
404 hs.masterSecret = hs.sessionState.masterSecret
405
406 return nil
407}
408
409func (hs *serverHandshakeState) doFullHandshake() error {
Adam Langley65c7dc42012-09-24 16:52:43 -0400410 c := hs.c
Adam Langleye6e8b722012-04-12 12:35:21 -0400411
Adam Langleyeef70352013-09-17 13:30:36 -0400412 if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
Adam Langley65c7dc42012-09-24 16:52:43 -0400413 hs.hello.ocspStapling = true
Adam Langley6f921f22011-04-14 14:47:28 -0400414 }
Adam Langley5e598c52009-11-05 15:44:32 -0800415
Adam Langleycff3e752016-10-10 15:27:34 -0700416 hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled
Adam Langley65c7dc42012-09-24 16:52:43 -0400417 hs.hello.cipherSuite = hs.suite.id
Adam Langley09b238f2015-04-28 09:13:38 -0700418
419 hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite)
Adam Langleycff3e752016-10-10 15:27:34 -0700420 if c.config.ClientAuth == NoClientCert {
Adam Langley09b238f2015-04-28 09:13:38 -0700421 // No need to keep a full record of the handshake if client
422 // certificates won't be used.
423 hs.finishedHash.discardHandshakeBuffer()
424 }
425 hs.finishedHash.Write(hs.clientHello.marshal())
Adam Langley65c7dc42012-09-24 16:52:43 -0400426 hs.finishedHash.Write(hs.hello.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500427 if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
428 return err
429 }
Adam Langley5e598c52009-11-05 15:44:32 -0800430
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800431 certMsg := new(certificateMsg)
Adam Langleyeef70352013-09-17 13:30:36 -0400432 certMsg.certificates = hs.cert.Certificate
Adam Langley65c7dc42012-09-24 16:52:43 -0400433 hs.finishedHash.Write(certMsg.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500434 if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
435 return err
436 }
Adam Langley5e598c52009-11-05 15:44:32 -0800437
Adam Langley65c7dc42012-09-24 16:52:43 -0400438 if hs.hello.ocspStapling {
Adam Langley6f921f22011-04-14 14:47:28 -0400439 certStatus := new(certificateStatusMsg)
Adam Langleyeef70352013-09-17 13:30:36 -0400440 certStatus.response = hs.cert.OCSPStaple
Adam Langley65c7dc42012-09-24 16:52:43 -0400441 hs.finishedHash.Write(certStatus.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500442 if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil {
443 return err
444 }
Adam Langley6f921f22011-04-14 14:47:28 -0400445 }
446
Adam Langley7e767792013-07-02 19:58:56 -0400447 keyAgreement := hs.suite.ka(c.vers)
Adam Langleycff3e752016-10-10 15:27:34 -0700448 skx, err := keyAgreement.generateServerKeyExchange(c.config, hs.cert, hs.clientHello, hs.hello)
Adam Langley4883b732010-12-16 17:10:50 -0500449 if err != nil {
450 c.sendAlert(alertHandshakeFailure)
451 return err
452 }
453 if skx != nil {
Adam Langley65c7dc42012-09-24 16:52:43 -0400454 hs.finishedHash.Write(skx.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500455 if _, err := c.writeRecord(recordTypeHandshake, skx.marshal()); err != nil {
456 return err
457 }
Adam Langley4883b732010-12-16 17:10:50 -0500458 }
459
Filippo Valsorda0b3a57b2019-06-13 18:33:33 -0400460 var certReq *certificateRequestMsg
Adam Langleycff3e752016-10-10 15:27:34 -0700461 if c.config.ClientAuth >= RequestClientCert {
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400462 // Request a client certificate
Filippo Valsorda0b3a57b2019-06-13 18:33:33 -0400463 certReq = new(certificateRequestMsg)
Joel Sing7b7dac52013-07-17 12:33:16 -0400464 certReq.certificateTypes = []byte{
465 byte(certTypeRSASign),
466 byte(certTypeECDSASign),
467 }
Adam Langley7e767792013-07-02 19:58:56 -0400468 if c.vers >= VersionTLS12 {
Filippo Valsorda4c8b09e2018-10-24 21:22:00 -0400469 certReq.hasSignatureAlgorithm = true
Filippo Valsorda0b3a57b2019-06-13 18:33:33 -0400470 certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithmsTLS12
Adam Langley7e767792013-07-02 19:58:56 -0400471 }
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500472
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400473 // An empty list of certificateAuthorities signals to
474 // the client that it may send any certificate in response
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500475 // to our request. When we know the CAs we trust, then
476 // we can send them down, so that the client can choose
477 // an appropriate certificate to give to us.
Adam Langleycff3e752016-10-10 15:27:34 -0700478 if c.config.ClientCAs != nil {
479 certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500480 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400481 hs.finishedHash.Write(certReq.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500482 if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil {
483 return err
484 }
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400485 }
486
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800487 helloDone := new(serverHelloDoneMsg)
Adam Langley65c7dc42012-09-24 16:52:43 -0400488 hs.finishedHash.Write(helloDone.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500489 if _, err := c.writeRecord(recordTypeHandshake, helloDone.marshal()); err != nil {
490 return err
491 }
Adam Langley5e598c52009-11-05 15:44:32 -0800492
Adam Langley2a8c81f2016-06-01 14:41:09 -0700493 if _, err := c.flush(); err != nil {
494 return err
495 }
496
Joel Sing7b7dac52013-07-17 12:33:16 -0400497 var pub crypto.PublicKey // public key for client auth, if any
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400498
Adam Langley65c7dc42012-09-24 16:52:43 -0400499 msg, err := c.readHandshake()
Russ Cox72d93222010-04-26 22:19:04 -0700500 if err != nil {
501 return err
502 }
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500503
504 // If we requested a client certificate, then the client must send a
505 // certificate message, even if it's empty.
Adam Langleycff3e752016-10-10 15:27:34 -0700506 if c.config.ClientAuth >= RequestClientCert {
Filippo Valsorda106db712018-11-05 19:23:25 -0500507 certMsg, ok := msg.(*certificateMsg)
508 if !ok {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500509 c.sendAlert(alertUnexpectedMessage)
510 return unexpectedMessageError(certMsg, msg)
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500511 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400512 hs.finishedHash.Write(certMsg.marshal())
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500513
Filippo Valsorda106db712018-11-05 19:23:25 -0500514 if err := c.processCertsFromClient(Certificate{
515 Certificate: certMsg.certificates,
516 }); err != nil {
Adam Langley65c7dc42012-09-24 16:52:43 -0400517 return err
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500518 }
Filippo Valsorda106db712018-11-05 19:23:25 -0500519 if len(certMsg.certificates) != 0 {
520 pub = c.peerCertificates[0].PublicKey
521 }
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500522
523 msg, err = c.readHandshake()
524 if err != nil {
525 return err
526 }
527 }
528
529 // Get client key exchange
Russ Cox72d93222010-04-26 22:19:04 -0700530 ckx, ok := msg.(*clientKeyExchangeMsg)
Adam Langley5e598c52009-11-05 15:44:32 -0800531 if !ok {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500532 c.sendAlert(alertUnexpectedMessage)
533 return unexpectedMessageError(ckx, msg)
Adam Langley5e598c52009-11-05 15:44:32 -0800534 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400535 hs.finishedHash.Write(ckx.marshal())
Adam Langley5e598c52009-11-05 15:44:32 -0800536
Adam Langleycff3e752016-10-10 15:27:34 -0700537 preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers)
Adam Langley09b238f2015-04-28 09:13:38 -0700538 if err != nil {
539 c.sendAlert(alertHandshakeFailure)
540 return err
541 }
542 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
Filippo Valsorda29b01d52018-11-03 18:13:05 -0400543 if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.clientHello.random, hs.masterSecret); err != nil {
Joonas Kuorilehto320bd562016-08-20 14:41:42 +0300544 c.sendAlert(alertInternalError)
545 return err
546 }
Adam Langley09b238f2015-04-28 09:13:38 -0700547
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400548 // If we received a client cert in response to our certificate request message,
549 // the client will send us a certificateVerifyMsg immediately after the
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +0000550 // clientKeyExchangeMsg. This message is a digest of all preceding
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400551 // handshake-layer messages that is signed using the private key corresponding
552 // to the client's certificate. This allows us to verify that the client is in
Robert Henckec8727c82011-05-18 13:14:56 -0400553 // possession of the private key of the certificate.
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400554 if len(c.peerCertificates) > 0 {
555 msg, err = c.readHandshake()
556 if err != nil {
557 return err
558 }
559 certVerify, ok := msg.(*certificateVerifyMsg)
560 if !ok {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500561 c.sendAlert(alertUnexpectedMessage)
562 return unexpectedMessageError(certVerify, msg)
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400563 }
564
Adam Langley09b238f2015-04-28 09:13:38 -0700565 // Determine the signature type.
Filippo Valsorda0b3a57b2019-06-13 18:33:33 -0400566 _, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, certReq.supportedSignatureAlgorithms, c.vers)
Peter Wuc89d75f2017-11-22 18:25:20 +0000567 if err != nil {
568 c.sendAlert(alertIllegalParameter)
569 return err
Adam Langley09b238f2015-04-28 09:13:38 -0700570 }
571
Filippo Valsordaf3533852019-05-16 19:13:29 -0400572 signed, err := hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret)
573 if err == nil {
574 err = verifyHandshakeSignature(sigType, pub, hashFunc, signed, certVerify.signature)
Joel Sing7b7dac52013-07-17 12:33:16 -0400575 }
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400576 if err != nil {
Adam Langleyf6e2eab2010-10-11 10:39:56 -0400577 c.sendAlert(alertBadCertificate)
Adam Langley09b238f2015-04-28 09:13:38 -0700578 return errors.New("tls: could not validate signature of connection nonces: " + err.Error())
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400579 }
580
Adam Langley65c7dc42012-09-24 16:52:43 -0400581 hs.finishedHash.Write(certVerify.marshal())
Mikkel Krautzc47123d2010-08-16 11:22:22 -0400582 }
Adam Langley09b238f2015-04-28 09:13:38 -0700583
584 hs.finishedHash.discardHandshakeBuffer()
Adam Langley5e598c52009-11-05 15:44:32 -0800585
Adam Langley65c7dc42012-09-24 16:52:43 -0400586 return nil
587}
Adam Langley5e598c52009-11-05 15:44:32 -0800588
Adam Langley65c7dc42012-09-24 16:52:43 -0400589func (hs *serverHandshakeState) establishKeys() error {
590 c := hs.c
591
592 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
Adam Langley09b238f2015-04-28 09:13:38 -0700593 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
Adam Langley65c7dc42012-09-24 16:52:43 -0400594
Adam Langley2fe9a5a2013-08-29 17:18:59 -0400595 var clientCipher, serverCipher interface{}
596 var clientHash, serverHash macFunction
Adam Langley65c7dc42012-09-24 16:52:43 -0400597
Adam Langley2fe9a5a2013-08-29 17:18:59 -0400598 if hs.suite.aead == nil {
599 clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
600 clientHash = hs.suite.mac(c.vers, clientMAC)
601 serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
602 serverHash = hs.suite.mac(c.vers, serverMAC)
603 } else {
604 clientCipher = hs.suite.aead(clientKey, clientIV)
605 serverCipher = hs.suite.aead(serverKey, serverIV)
606 }
607
608 c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
Adam Langley65c7dc42012-09-24 16:52:43 -0400609 c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
610
611 return nil
612}
613
Andres Erbsenfce63882014-08-11 16:40:42 -0700614func (hs *serverHandshakeState) readFinished(out []byte) error {
Adam Langley65c7dc42012-09-24 16:52:43 -0400615 c := hs.c
616
Filippo Valsordadb27e782018-11-03 18:29:09 -0400617 if err := c.readChangeCipherSpec(); err != nil {
618 return err
Adam Langley5e598c52009-11-05 15:44:32 -0800619 }
620
Adam Langley65c7dc42012-09-24 16:52:43 -0400621 if hs.hello.nextProtoNeg {
622 msg, err := c.readHandshake()
Russ Cox72d93222010-04-26 22:19:04 -0700623 if err != nil {
624 return err
625 }
626 nextProto, ok := msg.(*nextProtoMsg)
Adam Langley9ebb5962009-12-23 11:13:09 -0800627 if !ok {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500628 c.sendAlert(alertUnexpectedMessage)
629 return unexpectedMessageError(nextProto, msg)
Adam Langley9ebb5962009-12-23 11:13:09 -0800630 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400631 hs.finishedHash.Write(nextProto.marshal())
Russ Cox72d93222010-04-26 22:19:04 -0700632 c.clientProtocol = nextProto.proto
Adam Langley9ebb5962009-12-23 11:13:09 -0800633 }
634
Adam Langley65c7dc42012-09-24 16:52:43 -0400635 msg, err := c.readHandshake()
Russ Cox72d93222010-04-26 22:19:04 -0700636 if err != nil {
637 return err
638 }
639 clientFinished, ok := msg.(*finishedMsg)
Adam Langley5e598c52009-11-05 15:44:32 -0800640 if !ok {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500641 c.sendAlert(alertUnexpectedMessage)
642 return unexpectedMessageError(clientFinished, msg)
Adam Langley5e598c52009-11-05 15:44:32 -0800643 }
644
Adam Langley65c7dc42012-09-24 16:52:43 -0400645 verify := hs.finishedHash.clientSum(hs.masterSecret)
Adam Langley5e598c52009-11-05 15:44:32 -0800646 if len(verify) != len(clientFinished.verifyData) ||
647 subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
Adam Langley6b29f7b2014-02-12 11:20:01 -0500648 c.sendAlert(alertHandshakeFailure)
649 return errors.New("tls: client's Finished message is incorrect")
Adam Langley5e598c52009-11-05 15:44:32 -0800650 }
651
Adam Langley65c7dc42012-09-24 16:52:43 -0400652 hs.finishedHash.Write(clientFinished.marshal())
Andres Erbsenfce63882014-08-11 16:40:42 -0700653 copy(out, verify)
Adam Langley65c7dc42012-09-24 16:52:43 -0400654 return nil
655}
Adam Langley5e598c52009-11-05 15:44:32 -0800656
Adam Langley65c7dc42012-09-24 16:52:43 -0400657func (hs *serverHandshakeState) sendSessionTicket() error {
658 if !hs.hello.ticketSupported {
659 return nil
660 }
661
662 c := hs.c
663 m := new(newSessionTicketMsg)
664
Filippo Valsorda106db712018-11-05 19:23:25 -0500665 var certsFromClient [][]byte
666 for _, cert := range c.peerCertificates {
667 certsFromClient = append(certsFromClient, cert.Raw)
668 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400669 state := sessionState{
670 vers: c.vers,
671 cipherSuite: hs.suite.id,
672 masterSecret: hs.masterSecret,
Filippo Valsorda106db712018-11-05 19:23:25 -0500673 certificates: certsFromClient,
Adam Langley65c7dc42012-09-24 16:52:43 -0400674 }
Filippo Valsorda106db712018-11-05 19:23:25 -0500675 var err error
Filippo Valsorda6435d0c2018-11-05 15:59:08 -0500676 m.ticket, err = c.encryptTicket(state.marshal())
Adam Langley65c7dc42012-09-24 16:52:43 -0400677 if err != nil {
678 return err
679 }
680
681 hs.finishedHash.Write(m.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500682 if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
683 return err
684 }
Adam Langley65c7dc42012-09-24 16:52:43 -0400685
686 return nil
687}
688
Andres Erbsenfce63882014-08-11 16:40:42 -0700689func (hs *serverHandshakeState) sendFinished(out []byte) error {
Adam Langley65c7dc42012-09-24 16:52:43 -0400690 c := hs.c
691
Tamir Duberstein37c28752016-02-26 14:17:29 -0500692 if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil {
693 return err
694 }
Adam Langley5e598c52009-11-05 15:44:32 -0800695
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800696 finished := new(finishedMsg)
Adam Langley65c7dc42012-09-24 16:52:43 -0400697 finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
698 hs.finishedHash.Write(finished.marshal())
Tamir Duberstein37c28752016-02-26 14:17:29 -0500699 if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
700 return err
701 }
Adam Langley5e598c52009-11-05 15:44:32 -0800702
Adam Langley65c7dc42012-09-24 16:52:43 -0400703 c.cipherSuite = hs.suite.id
Andres Erbsenfce63882014-08-11 16:40:42 -0700704 copy(out, finished.verifyData)
Adam Langley65c7dc42012-09-24 16:52:43 -0400705
706 return nil
707}
708
709// processCertsFromClient takes a chain of client certificates either from a
710// Certificates message or from a sessionState and verifies them. It returns
711// the public key of the leaf certificate.
Filippo Valsorda106db712018-11-05 19:23:25 -0500712func (c *Conn) processCertsFromClient(certificate Certificate) error {
713 certificates := certificate.Certificate
Adam Langley65c7dc42012-09-24 16:52:43 -0400714 certs := make([]*x509.Certificate, len(certificates))
715 var err error
716 for i, asn1Data := range certificates {
717 if certs[i], err = x509.ParseCertificate(asn1Data); err != nil {
718 c.sendAlert(alertBadCertificate)
Filippo Valsorda106db712018-11-05 19:23:25 -0500719 return errors.New("tls: failed to parse client certificate: " + err.Error())
Adam Langley65c7dc42012-09-24 16:52:43 -0400720 }
721 }
722
Filippo Valsorda106db712018-11-05 19:23:25 -0500723 if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {
724 c.sendAlert(alertBadCertificate)
725 return errors.New("tls: client didn't provide a certificate")
726 }
727
Adam Langley65c7dc42012-09-24 16:52:43 -0400728 if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
729 opts := x509.VerifyOptions{
730 Roots: c.config.ClientCAs,
731 CurrentTime: c.config.time(),
732 Intermediates: x509.NewCertPool(),
733 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
734 }
735
736 for _, cert := range certs[1:] {
737 opts.Intermediates.AddCert(cert)
738 }
739
740 chains, err := certs[0].Verify(opts)
741 if err != nil {
742 c.sendAlert(alertBadCertificate)
Filippo Valsorda106db712018-11-05 19:23:25 -0500743 return errors.New("tls: failed to verify client's certificate: " + err.Error())
Adam Langley65c7dc42012-09-24 16:52:43 -0400744 }
745
Adam Langley65c7dc42012-09-24 16:52:43 -0400746 c.verifiedChains = chains
747 }
748
Joshua Boelter426c2872016-07-13 16:22:28 -0600749 if c.config.VerifyPeerCertificate != nil {
750 if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
751 c.sendAlert(alertBadCertificate)
Filippo Valsorda106db712018-11-05 19:23:25 -0500752 return err
Joshua Boelter426c2872016-07-13 16:22:28 -0600753 }
754 }
755
Emmanuel Odekef0711b92016-03-14 03:35:13 -0600756 if len(certs) == 0 {
Filippo Valsorda106db712018-11-05 19:23:25 -0500757 return nil
Adam Langley65c7dc42012-09-24 16:52:43 -0400758 }
759
Filippo Valsorda106db712018-11-05 19:23:25 -0500760 switch certs[0].PublicKey.(type) {
Filippo Valsordaf3533852019-05-16 19:13:29 -0400761 case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
Emmanuel Odekef0711b92016-03-14 03:35:13 -0600762 default:
763 c.sendAlert(alertUnsupportedCertificate)
Filippo Valsorda106db712018-11-05 19:23:25 -0500764 return fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey)
Emmanuel Odekef0711b92016-03-14 03:35:13 -0600765 }
Filippo Valsorda106db712018-11-05 19:23:25 -0500766
Emmanuel Odekef0711b92016-03-14 03:35:13 -0600767 c.peerCertificates = certs
Filippo Valsorda106db712018-11-05 19:23:25 -0500768 c.ocspResponse = certificate.OCSPStaple
769 c.scts = certificate.SignedCertificateTimestamps
770 return nil
Adam Langley65c7dc42012-09-24 16:52:43 -0400771}
772
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700773// setCipherSuite sets a cipherSuite with the given id as the serverHandshakeState
774// suite if that cipher suite is acceptable to use.
775// It returns a bool indicating if the suite was set.
776func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16) bool {
Adam Langley793cbd52013-01-22 10:10:38 -0500777 for _, supported := range supportedCipherSuites {
Filippo Valsordaf3533852019-05-16 19:13:29 -0400778 if id != supported {
779 continue
Adam Langley65c7dc42012-09-24 16:52:43 -0400780 }
Filippo Valsordaf3533852019-05-16 19:13:29 -0400781 candidate := cipherSuiteByID(id)
782 if candidate == nil {
783 continue
784 }
785 // Don't select a ciphersuite which we can't
786 // support for this client.
787 if candidate.flags&suiteECDHE != 0 {
788 if !hs.ecdhOk {
789 continue
790 }
791 if candidate.flags&suiteECSign != 0 {
792 if !hs.ecSignOk {
793 continue
794 }
795 } else if !hs.rsaSignOk {
796 continue
797 }
798 } else if !hs.rsaDecryptOk {
799 continue
800 }
801 if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
802 continue
803 }
804 hs.suite = candidate
805 return true
Adam Langley65c7dc42012-09-24 16:52:43 -0400806 }
Jacob H. Haven28f33b42015-03-19 04:01:57 -0700807 return false
Adam Langley5e598c52009-11-05 15:44:32 -0800808}
Filippo Valsorda51c959b2016-10-19 15:21:54 +0200809
Filippo Valsordac21ba092018-11-02 00:57:30 -0400810func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
811 supportedVersions := clientHello.supportedVersions
812 if len(clientHello.supportedVersions) == 0 {
813 supportedVersions = supportedVersionsFromMax(clientHello.vers)
Filippo Valsorda51c959b2016-10-19 15:21:54 +0200814 }
815
Filippo Valsordac21ba092018-11-02 00:57:30 -0400816 return &ClientHelloInfo{
817 CipherSuites: clientHello.cipherSuites,
818 ServerName: clientHello.serverName,
819 SupportedCurves: clientHello.supportedCurves,
820 SupportedPoints: clientHello.supportedPoints,
821 SignatureSchemes: clientHello.supportedSignatureAlgorithms,
822 SupportedProtos: clientHello.alpnProtocols,
Filippo Valsorda51c959b2016-10-19 15:21:54 +0200823 SupportedVersions: supportedVersions,
Filippo Valsordac21ba092018-11-02 00:57:30 -0400824 Conn: c.conn,
Filippo Valsorda51c959b2016-10-19 15:21:54 +0200825 }
Filippo Valsorda51c959b2016-10-19 15:21:54 +0200826}