@@ -31,7 +31,8 @@ type clientHandshakeState struct {
31
31
suite * cipherSuite
32
32
finishedHash finishedHash
33
33
masterSecret []byte
34
- session * ClientSessionState
34
+ session * SessionState // the session being resumed
35
+ ticket []byte // a fresh ticket received during this handshake
35
36
}
36
37
37
38
var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme
@@ -177,11 +178,11 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
177
178
}
178
179
c .serverName = hello .serverName
179
180
180
- cacheKey , session , earlySecret , binderKey , err := c .loadSession (hello )
181
+ session , earlySecret , binderKey , err := c .loadSession (hello )
181
182
if err != nil {
182
183
return err
183
184
}
184
- if cacheKey != "" && session != nil {
185
+ if session != nil {
185
186
defer func () {
186
187
// If we got a handshake failure when resuming a session, throw away
187
188
// the session ticket. See RFC 5077, Section 3.2.
@@ -190,7 +191,9 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
190
191
// does require servers to abort on invalid binders, so we need to
191
192
// delete tickets to recover from a corrupted PSK.
192
193
if err != nil {
193
- c .config .ClientSessionCache .Put (cacheKey , nil )
194
+ if cacheKey := c .clientSessionCacheKey (); cacheKey != "" {
195
+ c .config .ClientSessionCache .Put (cacheKey , nil )
196
+ }
194
197
}
195
198
}()
196
199
}
@@ -255,19 +258,13 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
255
258
return err
256
259
}
257
260
258
- // If we had a successful handshake and hs.session is different from
259
- // the one already cached - cache a new one.
260
- if cacheKey != "" && hs .session != nil && session != hs .session {
261
- c .config .ClientSessionCache .Put (cacheKey , hs .session )
262
- }
263
-
264
261
return nil
265
262
}
266
263
267
- func (c * Conn ) loadSession (hello * clientHelloMsg ) (cacheKey string ,
268
- session * ClientSessionState , earlySecret , binderKey []byte , err error ) {
264
+ func (c * Conn ) loadSession (hello * clientHelloMsg ) (
265
+ session * SessionState , earlySecret , binderKey []byte , err error ) {
269
266
if c .config .SessionTicketsDisabled || c .config .ClientSessionCache == nil {
270
- return "" , nil , nil , nil , nil
267
+ return nil , nil , nil , nil
271
268
}
272
269
273
270
hello .ticketSupported = true
@@ -282,29 +279,30 @@ func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string,
282
279
// renegotiation is primarily used to allow a client to send a client
283
280
// certificate, which would be skipped if session resumption occurred.
284
281
if c .handshakes != 0 {
285
- return "" , nil , nil , nil , nil
282
+ return nil , nil , nil , nil
286
283
}
287
284
288
285
// Try to resume a previously negotiated TLS session, if available.
289
- cacheKey = c .clientSessionCacheKey ()
286
+ cacheKey : = c .clientSessionCacheKey ()
290
287
if cacheKey == "" {
291
- return "" , nil , nil , nil , nil
288
+ return nil , nil , nil , nil
292
289
}
293
- session , ok := c .config .ClientSessionCache .Get (cacheKey )
294
- if ! ok || session == nil {
295
- return cacheKey , nil , nil , nil , nil
290
+ cs , ok := c .config .ClientSessionCache .Get (cacheKey )
291
+ if ! ok || cs == nil {
292
+ return nil , nil , nil , nil
296
293
}
294
+ session = cs .session
297
295
298
296
// Check that version used for the previous session is still valid.
299
297
versOk := false
300
298
for _ , v := range hello .supportedVersions {
301
- if v == session .vers {
299
+ if v == session .version {
302
300
versOk = true
303
301
break
304
302
}
305
303
}
306
304
if ! versOk {
307
- return cacheKey , nil , nil , nil , nil
305
+ return nil , nil , nil , nil
308
306
}
309
307
310
308
// Check that the cached server certificate is not expired, and that it's
@@ -313,41 +311,41 @@ func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string,
313
311
if ! c .config .InsecureSkipVerify {
314
312
if len (session .verifiedChains ) == 0 {
315
313
// The original connection had InsecureSkipVerify, while this doesn't.
316
- return cacheKey , nil , nil , nil , nil
314
+ return nil , nil , nil , nil
317
315
}
318
- serverCert := session .serverCertificates [0 ]
316
+ serverCert := session .peerCertificates [0 ]
319
317
if c .config .time ().After (serverCert .NotAfter ) {
320
318
// Expired certificate, delete the entry.
321
319
c .config .ClientSessionCache .Put (cacheKey , nil )
322
- return cacheKey , nil , nil , nil , nil
320
+ return nil , nil , nil , nil
323
321
}
324
322
if err := serverCert .VerifyHostname (c .config .ServerName ); err != nil {
325
- return cacheKey , nil , nil , nil , nil
323
+ return nil , nil , nil , nil
326
324
}
327
325
}
328
326
329
- if session .vers != VersionTLS13 {
327
+ if session .version != VersionTLS13 {
330
328
// In TLS 1.2 the cipher suite must match the resumed session. Ensure we
331
329
// are still offering it.
332
330
if mutualCipherSuite (hello .cipherSuites , session .cipherSuite ) == nil {
333
- return cacheKey , nil , nil , nil , nil
331
+ return nil , nil , nil , nil
334
332
}
335
333
336
- hello .sessionTicket = session . sessionTicket
334
+ hello .sessionTicket = cs . ticket
337
335
return
338
336
}
339
337
340
338
// Check that the session ticket is not expired.
341
- if c .config .time ().After (session .useBy ) {
339
+ if c .config .time ().After (time . Unix ( int64 ( session .useBy ), 0 ) ) {
342
340
c .config .ClientSessionCache .Put (cacheKey , nil )
343
- return cacheKey , nil , nil , nil , nil
341
+ return nil , nil , nil , nil
344
342
}
345
343
346
344
// In TLS 1.3 the KDF hash must match the resumed session. Ensure we
347
345
// offer at least one cipher suite with that hash.
348
346
cipherSuite := cipherSuiteTLS13ByID (session .cipherSuite )
349
347
if cipherSuite == nil {
350
- return cacheKey , nil , nil , nil , nil
348
+ return nil , nil , nil , nil
351
349
}
352
350
cipherSuiteOk := false
353
351
for _ , offeredID := range hello .cipherSuites {
@@ -358,32 +356,30 @@ func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string,
358
356
}
359
357
}
360
358
if ! cipherSuiteOk {
361
- return cacheKey , nil , nil , nil , nil
359
+ return nil , nil , nil , nil
362
360
}
363
361
364
362
// Set the pre_shared_key extension. See RFC 8446, Section 4.2.11.1.
365
- ticketAge := uint32 ( c .config .time ().Sub (session .receivedAt ) / time . Millisecond )
363
+ ticketAge := c .config .time ().Sub (time . Unix ( int64 ( session .createdAt ), 0 ) )
366
364
identity := pskIdentity {
367
- label : session . sessionTicket ,
368
- obfuscatedTicketAge : ticketAge + session .ageAdd ,
365
+ label : cs . ticket ,
366
+ obfuscatedTicketAge : uint32 ( ticketAge / time . Millisecond ) + session .ageAdd ,
369
367
}
370
368
hello .pskIdentities = []pskIdentity {identity }
371
369
hello .pskBinders = [][]byte {make ([]byte , cipherSuite .hash .Size ())}
372
370
373
371
// Compute the PSK binders. See RFC 8446, Section 4.2.11.2.
374
- psk := cipherSuite .expandLabel (session .masterSecret , "resumption" ,
375
- session .nonce , cipherSuite .hash .Size ())
376
- earlySecret = cipherSuite .extract (psk , nil )
372
+ earlySecret = cipherSuite .extract (session .secret , nil )
377
373
binderKey = cipherSuite .deriveSecret (earlySecret , resumptionBinderLabel , nil )
378
374
transcript := cipherSuite .hash .New ()
379
375
helloBytes , err := hello .marshalWithoutBinders ()
380
376
if err != nil {
381
- return "" , nil , nil , nil , err
377
+ return nil , nil , nil , err
382
378
}
383
379
transcript .Write (helloBytes )
384
380
pskBinders := [][]byte {cipherSuite .finishedHash (binderKey , transcript )}
385
381
if err := hello .updateBinders (pskBinders ); err != nil {
386
- return "" , nil , nil , nil , err
382
+ return nil , nil , nil , err
387
383
}
388
384
389
385
return
@@ -485,6 +481,9 @@ func (hs *clientHandshakeState) handshake() error {
485
481
return err
486
482
}
487
483
}
484
+ if err := hs .saveSessionTicket (); err != nil {
485
+ return err
486
+ }
488
487
489
488
c .ekm = ekmFromMasterSecret (c .vers , hs .suite , hs .masterSecret , hs .hello .random , hs .serverHello .random )
490
489
c .isHandshakeComplete .Store (true )
@@ -752,7 +751,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
752
751
return false , nil
753
752
}
754
753
755
- if hs .session .vers != c .vers {
754
+ if hs .session .version != c .vers {
756
755
c .sendAlert (alertHandshakeFailure )
757
756
return false , errors .New ("tls: server resumed a session with a different version" )
758
757
}
@@ -762,9 +761,10 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
762
761
return false , errors .New ("tls: server resumed a session with a different cipher suite" )
763
762
}
764
763
765
- // Restore masterSecret, peerCerts, and ocspResponse from previous state
766
- hs .masterSecret = hs .session .masterSecret
767
- c .peerCertificates = hs .session .serverCertificates
764
+ // Restore master secret and certificates from previous state
765
+ hs .masterSecret = hs .session .secret
766
+ c .peerCertificates = hs .session .peerCertificates
767
+ c .activeCertHandles = hs .c .activeCertHandles
768
768
c .verifiedChains = hs .session .verifiedChains
769
769
c .ocspResponse = hs .session .ocspResponse
770
770
// Let the ServerHello SCTs override the session SCTs from the original
@@ -836,8 +836,13 @@ func (hs *clientHandshakeState) readSessionTicket() error {
836
836
if ! hs .serverHello .ticketSupported {
837
837
return nil
838
838
}
839
-
840
839
c := hs .c
840
+
841
+ if ! hs .hello .ticketSupported {
842
+ c .sendAlert (alertIllegalParameter )
843
+ return errors .New ("tls: server sent unrequested session ticket" )
844
+ }
845
+
841
846
msg , err := c .readHandshake (& hs .finishedHash )
842
847
if err != nil {
843
848
return err
@@ -848,18 +853,29 @@ func (hs *clientHandshakeState) readSessionTicket() error {
848
853
return unexpectedMessageError (sessionTicketMsg , msg )
849
854
}
850
855
851
- hs .session = & ClientSessionState {
852
- sessionTicket : sessionTicketMsg .ticket ,
853
- vers : c .vers ,
854
- cipherSuite : hs .suite .id ,
855
- masterSecret : hs .masterSecret ,
856
- serverCertificates : c .peerCertificates ,
857
- verifiedChains : c .verifiedChains ,
858
- receivedAt : c .config .time (),
859
- ocspResponse : c .ocspResponse ,
860
- scts : c .scts ,
856
+ hs .ticket = sessionTicketMsg .ticket
857
+ return nil
858
+ }
859
+
860
+ func (hs * clientHandshakeState ) saveSessionTicket () error {
861
+ if hs .ticket == nil {
862
+ return nil
863
+ }
864
+ c := hs .c
865
+
866
+ cacheKey := c .clientSessionCacheKey ()
867
+ if cacheKey == "" {
868
+ return nil
869
+ }
870
+
871
+ session , err := c .sessionState ()
872
+ if err != nil {
873
+ return err
861
874
}
875
+ session .secret = hs .masterSecret
862
876
877
+ cs := & ClientSessionState {ticket : hs .ticket , session : session }
878
+ c .config .ClientSessionCache .Put (cacheKey , cs )
863
879
return nil
864
880
}
865
881
@@ -885,7 +901,7 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
885
901
activeHandles := make ([]* activeCert , len (certificates ))
886
902
certs := make ([]* x509.Certificate , len (certificates ))
887
903
for i , asn1Data := range certificates {
888
- cert , err := clientCertCache .newCert (asn1Data )
904
+ cert , err := globalCertCache .newCert (asn1Data )
889
905
if err != nil {
890
906
c .sendAlert (alertBadCertificate )
891
907
return errors .New ("tls: failed to parse certificate from server: " + err .Error ())
0 commit comments