@@ -19,20 +19,19 @@ import (
19
19
// serverHandshakeState contains details of a server handshake in progress.
20
20
// It's discarded once the handshake has completed.
21
21
type 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
- cachedClientHelloInfo * ClientHelloInfo
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
36
35
}
37
36
38
37
// serverHandshake performs a TLS handshake as a server.
@@ -41,17 +40,36 @@ func (c *Conn) serverHandshake() error {
41
40
// encrypt the tickets with.
42
41
c .config .serverInitOnce .Do (func () { c .config .serverInit (nil ) })
43
42
43
+ clientHello , err := c .readClientHello ()
44
+ if err != nil {
45
+ return err
46
+ }
47
+
48
+ if c .vers == VersionTLS13 {
49
+ hs := serverHandshakeStateTLS13 {
50
+ c : c ,
51
+ clientHello : clientHello ,
52
+ }
53
+ return hs .handshake ()
54
+ }
55
+
44
56
hs := serverHandshakeState {
45
- c : c ,
57
+ c : c ,
58
+ clientHello : clientHello ,
46
59
}
47
- isResume , err := hs .readClientHello ()
48
- if err != nil {
60
+ return hs .handshake ()
61
+ }
62
+
63
+ func (hs * serverHandshakeState ) handshake () error {
64
+ c := hs .c
65
+
66
+ if err := hs .processClientHello (); err != nil {
49
67
return err
50
68
}
51
69
52
70
// For an overview of TLS handshaking, see RFC 5246, Section 7.3.
53
71
c .buffering = true
54
- if isResume {
72
+ if hs . checkForResumption () {
55
73
// The client has included a session ticket and so we do an abbreviated handshake.
56
74
if err := hs .doResumeHandshake (); err != nil {
57
75
return err
@@ -81,6 +99,9 @@ func (c *Conn) serverHandshake() error {
81
99
} else {
82
100
// The client didn't include a session ticket, or it wasn't
83
101
// valid so we do a full handshake.
102
+ if err := hs .pickCipherSuite (); err != nil {
103
+ return err
104
+ }
84
105
if err := hs .doFullHandshake (); err != nil {
85
106
return err
86
107
}
@@ -109,42 +130,47 @@ func (c *Conn) serverHandshake() error {
109
130
return nil
110
131
}
111
132
112
- // readClientHello reads a ClientHello message from the client and decides
113
- // whether we will perform session resumption.
114
- func (hs * serverHandshakeState ) readClientHello () (isResume bool , err error ) {
115
- c := hs .c
116
-
133
+ // readClientHello reads a ClientHello message and selects the protocol version.
134
+ func (c * Conn ) readClientHello () (* clientHelloMsg , error ) {
117
135
msg , err := c .readHandshake ()
118
136
if err != nil {
119
- return false , err
137
+ return nil , err
120
138
}
121
- var ok bool
122
- hs .clientHello , ok = msg .(* clientHelloMsg )
139
+ clientHello , ok := msg .(* clientHelloMsg )
123
140
if ! ok {
124
141
c .sendAlert (alertUnexpectedMessage )
125
- return false , unexpectedMessageError (hs . clientHello , msg )
142
+ return nil , unexpectedMessageError (clientHello , msg )
126
143
}
127
144
128
145
if c .config .GetConfigForClient != nil {
129
- if newConfig , err := c .config .GetConfigForClient (hs .clientHelloInfo ()); err != nil {
146
+ chi := clientHelloInfo (c , clientHello )
147
+ if newConfig , err := c .config .GetConfigForClient (chi ); err != nil {
130
148
c .sendAlert (alertInternalError )
131
- return false , err
149
+ return nil , err
132
150
} else if newConfig != nil {
133
151
newConfig .serverInitOnce .Do (func () { newConfig .serverInit (c .config ) })
134
152
c .config = newConfig
135
153
}
136
154
}
137
155
138
- clientVersions := hs . clientHello .supportedVersions
139
- if len (hs . clientHello .supportedVersions ) == 0 {
140
- clientVersions = supportedVersionsFromMax (hs . clientHello .vers )
156
+ clientVersions := clientHello .supportedVersions
157
+ if len (clientHello .supportedVersions ) == 0 {
158
+ clientVersions = supportedVersionsFromMax (clientHello .vers )
141
159
}
142
160
c .vers , ok = c .config .mutualVersion (false , clientVersions )
143
161
if ! ok {
144
162
c .sendAlert (alertProtocolVersion )
145
- return false , fmt .Errorf ("tls: client offered only unsupported versions: %x" , clientVersions )
163
+ return nil , fmt .Errorf ("tls: client offered only unsupported versions: %x" , clientVersions )
146
164
}
147
165
c .haveVers = true
166
+ c .in .version = c .vers
167
+ c .out .version = c .vers
168
+
169
+ return clientHello , nil
170
+ }
171
+
172
+ func (hs * serverHandshakeState ) processClientHello () error {
173
+ c := hs .c
148
174
149
175
hs .hello = new (serverHelloMsg )
150
176
hs .hello .vers = c .vers
@@ -181,19 +207,19 @@ Curves:
181
207
182
208
if ! foundCompression {
183
209
c .sendAlert (alertHandshakeFailure )
184
- return false , errors .New ("tls: client does not support uncompressed connections" )
210
+ return errors .New ("tls: client does not support uncompressed connections" )
185
211
}
186
212
187
213
hs .hello .random = make ([]byte , 32 )
188
- _ , err = io .ReadFull (c .config .rand (), hs .hello .random )
214
+ _ , err : = io .ReadFull (c .config .rand (), hs .hello .random )
189
215
if err != nil {
190
216
c .sendAlert (alertInternalError )
191
- return false , err
217
+ return err
192
218
}
193
219
194
220
if len (hs .clientHello .secureRenegotiation ) != 0 {
195
221
c .sendAlert (alertHandshakeFailure )
196
- return false , errors .New ("tls: initial handshake had non-empty renegotiation extension" )
222
+ return errors .New ("tls: initial handshake had non-empty renegotiation extension" )
197
223
}
198
224
199
225
hs .hello .secureRenegotiationSupported = hs .clientHello .secureRenegotiationSupported
@@ -218,10 +244,10 @@ Curves:
218
244
}
219
245
}
220
246
221
- hs .cert , err = c .config .getCertificate (hs . clientHelloInfo ())
247
+ hs .cert , err = c .config .getCertificate (clientHelloInfo (c , hs . clientHello ))
222
248
if err != nil {
223
249
c .sendAlert (alertInternalError )
224
- return false , err
250
+ return err
225
251
}
226
252
if hs .clientHello .scts {
227
253
hs .hello .scts = hs .cert .SignedCertificateTimestamps
@@ -235,7 +261,7 @@ Curves:
235
261
hs .rsaSignOk = true
236
262
default :
237
263
c .sendAlert (alertInternalError )
238
- return false , fmt .Errorf ("tls: unsupported signing key type (%T)" , priv .Public ())
264
+ return fmt .Errorf ("tls: unsupported signing key type (%T)" , priv .Public ())
239
265
}
240
266
}
241
267
if priv , ok := hs .cert .PrivateKey .(crypto.Decrypter ); ok {
@@ -244,13 +270,15 @@ Curves:
244
270
hs .rsaDecryptOk = true
245
271
default :
246
272
c .sendAlert (alertInternalError )
247
- return false , fmt .Errorf ("tls: unsupported decryption key type (%T)" , priv .Public ())
273
+ return fmt .Errorf ("tls: unsupported decryption key type (%T)" , priv .Public ())
248
274
}
249
275
}
250
276
251
- if hs .checkForResumption () {
252
- return true , nil
253
- }
277
+ return nil
278
+ }
279
+
280
+ func (hs * serverHandshakeState ) pickCipherSuite () error {
281
+ c := hs .c
254
282
255
283
var preferenceList , supportedList []uint16
256
284
if c .config .PreferServerCipherSuites {
@@ -269,7 +297,7 @@ Curves:
269
297
270
298
if hs .suite == nil {
271
299
c .sendAlert (alertHandshakeFailure )
272
- return false , errors .New ("tls: no cipher suite supported by both client and server" )
300
+ return errors .New ("tls: no cipher suite supported by both client and server" )
273
301
}
274
302
275
303
// See RFC 7507.
@@ -278,13 +306,13 @@ Curves:
278
306
// The client is doing a fallback connection.
279
307
if hs .clientHello .vers < c .config .supportedVersions (false )[0 ] {
280
308
c .sendAlert (alertInappropriateFallback )
281
- return false , errors .New ("tls: client using inappropriate protocol fallback" )
309
+ return errors .New ("tls: client using inappropriate protocol fallback" )
282
310
}
283
311
break
284
312
}
285
313
}
286
314
287
- return false , nil
315
+ return nil
288
316
}
289
317
290
318
// checkForResumption reports whether we should perform resumption on this connection.
@@ -766,26 +794,20 @@ func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites
766
794
return false
767
795
}
768
796
769
- func (hs * serverHandshakeState ) clientHelloInfo () * ClientHelloInfo {
770
- if hs .cachedClientHelloInfo != nil {
771
- return hs .cachedClientHelloInfo
772
- }
773
-
774
- supportedVersions := hs .clientHello .supportedVersions
775
- if len (hs .clientHello .supportedVersions ) == 0 {
776
- supportedVersions = supportedVersionsFromMax (hs .clientHello .vers )
797
+ func clientHelloInfo (c * Conn , clientHello * clientHelloMsg ) * ClientHelloInfo {
798
+ supportedVersions := clientHello .supportedVersions
799
+ if len (clientHello .supportedVersions ) == 0 {
800
+ supportedVersions = supportedVersionsFromMax (clientHello .vers )
777
801
}
778
802
779
- hs . cachedClientHelloInfo = & ClientHelloInfo {
780
- CipherSuites : hs . clientHello .cipherSuites ,
781
- ServerName : hs . clientHello .serverName ,
782
- SupportedCurves : hs . clientHello .supportedCurves ,
783
- SupportedPoints : hs . clientHello .supportedPoints ,
784
- SignatureSchemes : hs . clientHello .supportedSignatureAlgorithms ,
785
- SupportedProtos : hs . clientHello .alpnProtocols ,
803
+ return & ClientHelloInfo {
804
+ CipherSuites : clientHello .cipherSuites ,
805
+ ServerName : clientHello .serverName ,
806
+ SupportedCurves : clientHello .supportedCurves ,
807
+ SupportedPoints : clientHello .supportedPoints ,
808
+ SignatureSchemes : clientHello .supportedSignatureAlgorithms ,
809
+ SupportedProtos : clientHello .alpnProtocols ,
786
810
SupportedVersions : supportedVersions ,
787
- Conn : hs . c .conn ,
811
+ Conn : c .conn ,
788
812
}
789
-
790
- return hs .cachedClientHelloInfo
791
813
}
0 commit comments