github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/handshake_client_tls13.go (about) 1 // Copyright 2018 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 "bytes" 9 "crypto" 10 "crypto/hmac" 11 "crypto/rsa" 12 "errors" 13 "hash" 14 "sync/atomic" 15 "time" 16 ) 17 18 type clientHandshakeStateTLS13 struct { 19 c *Conn 20 serverHello *serverHelloMsg 21 hello *clientHelloMsg 22 ecdheParams ecdheParameters 23 24 session *ClientSessionState 25 earlySecret []byte 26 binderKey []byte 27 28 certReq *certificateRequestMsgTLS13 29 usingPSK bool 30 sentDummyCCS bool 31 suite *cipherSuiteTLS13 32 transcript hash.Hash 33 masterSecret []byte 34 trafficSecret []byte // client_application_traffic_secret_0 35 } 36 37 // handshake requires hs.c, hs.hello, hs.serverHello, hs.ecdheParams, and, 38 // optionally, hs.session, hs.earlySecret and hs.binderKey to be set. 39 func (hs *clientHandshakeStateTLS13) handshake() error { 40 c := hs.c 41 42 // The server must not select TLS 1.3 in a renegotiation. See RFC 8446, 43 // sections 4.1.2 and 4.1.3. 44 if c.handshakes > 0 { 45 c.sendAlert(alertProtocolVersion) 46 return errors.New("tls: server selected TLS 1.3 in a renegotiation") 47 } 48 49 // Consistency check on the presence of a keyShare and its parameters. 50 if hs.ecdheParams == nil || len(hs.hello.keyShares) != 1 { 51 return c.sendAlert(alertInternalError) 52 } 53 54 if err := hs.checkServerHelloOrHRR(); err != nil { 55 return err 56 } 57 58 hs.transcript = hs.suite.hash.New() 59 hs.transcript.Write(hs.hello.marshal()) 60 61 if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { 62 if err := hs.sendDummyChangeCipherSpec(); err != nil { 63 return err 64 } 65 if err := hs.processHelloRetryRequest(); err != nil { 66 return err 67 } 68 } 69 70 hs.transcript.Write(hs.serverHello.marshal()) 71 72 c.buffering = true 73 if err := hs.processServerHello(); err != nil { 74 return err 75 } 76 if err := hs.sendDummyChangeCipherSpec(); err != nil { 77 return err 78 } 79 if err := hs.establishHandshakeKeys(); err != nil { 80 return err 81 } 82 if err := hs.readServerParameters(); err != nil { 83 return err 84 } 85 if err := hs.readServerCertificate(); err != nil { 86 return err 87 } 88 if err := hs.readServerFinished(); err != nil { 89 return err 90 } 91 if err := hs.sendClientCertificate(); err != nil { 92 return err 93 } 94 if err := hs.sendClientFinished(); err != nil { 95 return err 96 } 97 if _, err := c.flush(); err != nil { 98 return err 99 } 100 101 atomic.StoreUint32(&c.handshakeStatus, 1) 102 103 return nil 104 } 105 106 // checkServerHelloOrHRR does validity checks that apply to both ServerHello and 107 // HelloRetryRequest messages. It sets hs.suite. 108 func (hs *clientHandshakeStateTLS13) checkServerHelloOrHRR() error { 109 c := hs.c 110 111 if hs.serverHello.supportedVersion == 0 { 112 c.sendAlert(alertMissingExtension) 113 return errors.New("tls: server selected TLS 1.3 using the legacy version field") 114 } 115 116 if hs.serverHello.supportedVersion != VersionTLS13 { 117 c.sendAlert(alertIllegalParameter) 118 return errors.New("tls: server selected an invalid version after a HelloRetryRequest") 119 } 120 121 if hs.serverHello.vers != VersionTLS12 { 122 c.sendAlert(alertIllegalParameter) 123 return errors.New("tls: server sent an incorrect legacy version") 124 } 125 126 if hs.serverHello.nextProtoNeg || 127 len(hs.serverHello.nextProtos) != 0 || 128 hs.serverHello.ocspStapling || 129 hs.serverHello.ticketSupported || 130 hs.serverHello.secureRenegotiationSupported || 131 len(hs.serverHello.secureRenegotiation) != 0 || 132 len(hs.serverHello.alpnProtocol) != 0 || 133 len(hs.serverHello.scts) != 0 { 134 c.sendAlert(alertUnsupportedExtension) 135 return errors.New("tls: server sent a ServerHello extension forbidden in TLS 1.3") 136 } 137 138 if !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) { 139 c.sendAlert(alertIllegalParameter) 140 return errors.New("tls: server did not echo the legacy session ID") 141 } 142 143 if hs.serverHello.compressionMethod != compressionNone { 144 c.sendAlert(alertIllegalParameter) 145 return errors.New("tls: server selected unsupported compression format") 146 } 147 148 selectedSuite := mutualCipherSuiteTLS13(hs.hello.cipherSuites, hs.serverHello.cipherSuite) 149 if hs.suite != nil && selectedSuite != hs.suite { 150 c.sendAlert(alertIllegalParameter) 151 return errors.New("tls: server changed cipher suite after a HelloRetryRequest") 152 } 153 if selectedSuite == nil { 154 c.sendAlert(alertIllegalParameter) 155 return errors.New("tls: server chose an unconfigured cipher suite") 156 } 157 hs.suite = selectedSuite 158 c.cipherSuite = hs.suite.id 159 160 return nil 161 } 162 163 // sendDummyChangeCipherSpec sends a ChangeCipherSpec record for compatibility 164 // with middleboxes that didn't implement TLS correctly. See RFC 8446, Appendix D.4. 165 func (hs *clientHandshakeStateTLS13) sendDummyChangeCipherSpec() error { 166 if hs.sentDummyCCS { 167 return nil 168 } 169 hs.sentDummyCCS = true 170 171 _, err := hs.c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) 172 return err 173 } 174 175 // processHelloRetryRequest handles the HRR in hs.serverHello, modifies and 176 // resends hs.hello, and reads the new ServerHello into hs.serverHello. 177 func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { 178 c := hs.c 179 180 // The first ClientHello gets double-hashed into the transcript upon a 181 // HelloRetryRequest. See RFC 8446, Section 4.4.1. 182 chHash := hs.transcript.Sum(nil) 183 hs.transcript.Reset() 184 hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) 185 hs.transcript.Write(chHash) 186 hs.transcript.Write(hs.serverHello.marshal()) 187 188 if hs.serverHello.serverShare.group != 0 { 189 c.sendAlert(alertDecodeError) 190 return errors.New("tls: received malformed key_share extension") 191 } 192 193 curveID := hs.serverHello.selectedGroup 194 if curveID == 0 { 195 c.sendAlert(alertMissingExtension) 196 return errors.New("tls: received HelloRetryRequest without selected group") 197 } 198 curveOK := false 199 for _, id := range hs.hello.supportedCurves { 200 if id == curveID { 201 curveOK = true 202 break 203 } 204 } 205 if !curveOK { 206 c.sendAlert(alertIllegalParameter) 207 return errors.New("tls: server selected unsupported group") 208 } 209 if hs.ecdheParams.CurveID() == curveID { 210 c.sendAlert(alertIllegalParameter) 211 return errors.New("tls: server sent an unnecessary HelloRetryRequest message") 212 } 213 if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok { 214 c.sendAlert(alertInternalError) 215 return errors.New("tls: CurvePreferences includes unsupported curve") 216 } 217 params, err := generateECDHEParameters(c.config.rand(), curveID) 218 if err != nil { 219 c.sendAlert(alertInternalError) 220 return err 221 } 222 hs.ecdheParams = params 223 hs.hello.keyShares = []keyShare{{group: curveID, data: params.PublicKey()}} 224 225 hs.hello.cookie = hs.serverHello.cookie 226 227 hs.hello.raw = nil 228 if len(hs.hello.pskIdentities) > 0 { 229 pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite) 230 if pskSuite == nil { 231 return c.sendAlert(alertInternalError) 232 } 233 if pskSuite.hash == hs.suite.hash { 234 // Update binders and obfuscated_ticket_age. 235 ticketAge := uint32(c.config.time().Sub(hs.session.receivedAt) / time.Millisecond) 236 hs.hello.pskIdentities[0].obfuscatedTicketAge = ticketAge + hs.session.ageAdd 237 238 transcript := hs.suite.hash.New() 239 transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))}) 240 transcript.Write(chHash) 241 transcript.Write(hs.serverHello.marshal()) 242 transcript.Write(hs.hello.marshalWithoutBinders()) 243 pskBinders := [][]byte{hs.suite.finishedHash(hs.binderKey, transcript)} 244 hs.hello.updateBinders(pskBinders) 245 } else { 246 // Server selected a cipher suite incompatible with the PSK. 247 hs.hello.pskIdentities = nil 248 hs.hello.pskBinders = nil 249 } 250 } 251 252 hs.transcript.Write(hs.hello.marshal()) 253 if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { 254 return err 255 } 256 257 msg, err := c.readHandshake() 258 if err != nil { 259 return err 260 } 261 262 serverHello, ok := msg.(*serverHelloMsg) 263 if !ok { 264 c.sendAlert(alertUnexpectedMessage) 265 return unexpectedMessageError(serverHello, msg) 266 } 267 hs.serverHello = serverHello 268 269 if err := hs.checkServerHelloOrHRR(); err != nil { 270 return err 271 } 272 273 return nil 274 } 275 276 func (hs *clientHandshakeStateTLS13) processServerHello() error { 277 c := hs.c 278 279 if bytes.Equal(hs.serverHello.random, helloRetryRequestRandom) { 280 c.sendAlert(alertUnexpectedMessage) 281 return errors.New("tls: server sent two HelloRetryRequest messages") 282 } 283 284 if len(hs.serverHello.cookie) != 0 { 285 c.sendAlert(alertUnsupportedExtension) 286 return errors.New("tls: server sent a cookie in a normal ServerHello") 287 } 288 289 if hs.serverHello.selectedGroup != 0 { 290 c.sendAlert(alertDecodeError) 291 return errors.New("tls: malformed key_share extension") 292 } 293 294 if hs.serverHello.serverShare.group == 0 { 295 c.sendAlert(alertIllegalParameter) 296 return errors.New("tls: server did not send a key share") 297 } 298 if hs.serverHello.serverShare.group != hs.ecdheParams.CurveID() { 299 c.sendAlert(alertIllegalParameter) 300 return errors.New("tls: server selected unsupported group") 301 } 302 303 if !hs.serverHello.selectedIdentityPresent { 304 return nil 305 } 306 307 if int(hs.serverHello.selectedIdentity) >= len(hs.hello.pskIdentities) { 308 c.sendAlert(alertIllegalParameter) 309 return errors.New("tls: server selected an invalid PSK") 310 } 311 312 if len(hs.hello.pskIdentities) != 1 || hs.session == nil { 313 return c.sendAlert(alertInternalError) 314 } 315 pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite) 316 if pskSuite == nil { 317 return c.sendAlert(alertInternalError) 318 } 319 if pskSuite.hash != hs.suite.hash { 320 c.sendAlert(alertIllegalParameter) 321 return errors.New("tls: server selected an invalid PSK and cipher suite pair") 322 } 323 324 hs.usingPSK = true 325 c.didResume = true 326 c.peerCertificates = hs.session.serverCertificates 327 c.verifiedChains = hs.session.verifiedChains 328 return nil 329 } 330 331 func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { 332 c := hs.c 333 334 sharedKey := hs.ecdheParams.SharedKey(hs.serverHello.serverShare.data) 335 if sharedKey == nil { 336 c.sendAlert(alertIllegalParameter) 337 return errors.New("tls: invalid server key share") 338 } 339 340 earlySecret := hs.earlySecret 341 if !hs.usingPSK { 342 earlySecret = hs.suite.extract(nil, nil) 343 } 344 handshakeSecret := hs.suite.extract(sharedKey, 345 hs.suite.deriveSecret(earlySecret, "derived", nil)) 346 347 clientSecret := hs.suite.deriveSecret(handshakeSecret, 348 clientHandshakeTrafficLabel, hs.transcript) 349 c.out.setTrafficSecret(hs.suite, clientSecret) 350 serverSecret := hs.suite.deriveSecret(handshakeSecret, 351 serverHandshakeTrafficLabel, hs.transcript) 352 c.in.setTrafficSecret(hs.suite, serverSecret) 353 354 err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.hello.random, clientSecret) 355 if err != nil { 356 c.sendAlert(alertInternalError) 357 return err 358 } 359 err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.hello.random, serverSecret) 360 if err != nil { 361 c.sendAlert(alertInternalError) 362 return err 363 } 364 365 hs.masterSecret = hs.suite.extract(nil, 366 hs.suite.deriveSecret(handshakeSecret, "derived", nil)) 367 368 return nil 369 } 370 371 func (hs *clientHandshakeStateTLS13) readServerParameters() error { 372 c := hs.c 373 374 msg, err := c.readHandshake() 375 if err != nil { 376 return err 377 } 378 379 encryptedExtensions, ok := msg.(*encryptedExtensionsMsg) 380 if !ok { 381 c.sendAlert(alertUnexpectedMessage) 382 return unexpectedMessageError(encryptedExtensions, msg) 383 } 384 hs.transcript.Write(encryptedExtensions.marshal()) 385 386 if len(encryptedExtensions.alpnProtocol) != 0 && len(hs.hello.alpnProtocols) == 0 { 387 c.sendAlert(alertUnsupportedExtension) 388 return errors.New("tls: server advertised unrequested ALPN extension") 389 } 390 c.clientProtocol = encryptedExtensions.alpnProtocol 391 392 return nil 393 } 394 395 func (hs *clientHandshakeStateTLS13) readServerCertificate() error { 396 c := hs.c 397 398 // Either a PSK or a certificate is always used, but not both. 399 // See RFC 8446, Section 4.1.1. 400 if hs.usingPSK { 401 return nil 402 } 403 404 msg, err := c.readHandshake() 405 if err != nil { 406 return err 407 } 408 409 certReq, ok := msg.(*certificateRequestMsgTLS13) 410 if ok { 411 hs.transcript.Write(certReq.marshal()) 412 413 hs.certReq = certReq 414 415 msg, err = c.readHandshake() 416 if err != nil { 417 return err 418 } 419 } 420 421 certMsg, ok := msg.(*certificateMsgTLS13) 422 if !ok { 423 c.sendAlert(alertUnexpectedMessage) 424 return unexpectedMessageError(certMsg, msg) 425 } 426 if len(certMsg.certificate.Certificate) == 0 { 427 c.sendAlert(alertDecodeError) 428 return errors.New("tls: received empty certificates message") 429 } 430 hs.transcript.Write(certMsg.marshal()) 431 432 c.scts = certMsg.certificate.SignedCertificateTimestamps 433 c.ocspResponse = certMsg.certificate.OCSPStaple 434 435 if err := c.verifyServerCertificate(certMsg.certificate.Certificate); err != nil { 436 return err 437 } 438 439 msg, err = c.readHandshake() 440 if err != nil { 441 return err 442 } 443 444 certVerify, ok := msg.(*certificateVerifyMsg) 445 if !ok { 446 c.sendAlert(alertUnexpectedMessage) 447 return unexpectedMessageError(certVerify, msg) 448 } 449 450 // See RFC 8446, Section 4.4.3. 451 if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) { 452 c.sendAlert(alertIllegalParameter) 453 return errors.New("tls: invalid certificate signature algorithm") 454 } 455 sigType := signatureFromSignatureScheme(certVerify.signatureAlgorithm) 456 sigHash, err := hashFromSignatureScheme(certVerify.signatureAlgorithm) 457 if sigType == 0 || err != nil { 458 c.sendAlert(alertInternalError) 459 return err 460 } 461 if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 { 462 c.sendAlert(alertIllegalParameter) 463 return errors.New("tls: invalid certificate signature algorithm") 464 } 465 h := sigHash.New() 466 writeSignedMessage(h, serverSignatureContext, hs.transcript) 467 if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey, 468 sigHash, h.Sum(nil), certVerify.signature); err != nil { 469 c.sendAlert(alertDecryptError) 470 return errors.New("tls: invalid certificate signature") 471 } 472 473 hs.transcript.Write(certVerify.marshal()) 474 475 return nil 476 } 477 478 func (hs *clientHandshakeStateTLS13) readServerFinished() error { 479 c := hs.c 480 481 msg, err := c.readHandshake() 482 if err != nil { 483 return err 484 } 485 486 finished, ok := msg.(*finishedMsg) 487 if !ok { 488 c.sendAlert(alertUnexpectedMessage) 489 return unexpectedMessageError(finished, msg) 490 } 491 492 expectedMAC := hs.suite.finishedHash(c.in.trafficSecret, hs.transcript) 493 if !hmac.Equal(expectedMAC, finished.verifyData) { 494 c.sendAlert(alertDecryptError) 495 return errors.New("tls: invalid server finished hash") 496 } 497 498 hs.transcript.Write(finished.marshal()) 499 500 // Derive secrets that take context through the server Finished. 501 502 hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret, 503 clientApplicationTrafficLabel, hs.transcript) 504 serverSecret := hs.suite.deriveSecret(hs.masterSecret, 505 serverApplicationTrafficLabel, hs.transcript) 506 c.in.setTrafficSecret(hs.suite, serverSecret) 507 508 err = c.config.writeKeyLog(keyLogLabelClientTraffic, hs.hello.random, hs.trafficSecret) 509 if err != nil { 510 c.sendAlert(alertInternalError) 511 return err 512 } 513 err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.hello.random, serverSecret) 514 if err != nil { 515 c.sendAlert(alertInternalError) 516 return err 517 } 518 519 c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript) 520 521 return nil 522 } 523 524 func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { 525 c := hs.c 526 527 if hs.certReq == nil { 528 return nil 529 } 530 531 cert, err := c.getClientCertificate(&CertificateRequestInfo{ 532 AcceptableCAs: hs.certReq.certificateAuthorities, 533 SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, 534 }) 535 if err != nil { 536 return err 537 } 538 539 certMsg := new(certificateMsgTLS13) 540 541 certMsg.certificate = *cert 542 certMsg.scts = hs.certReq.scts && len(cert.SignedCertificateTimestamps) > 0 543 certMsg.ocspStapling = hs.certReq.ocspStapling && len(cert.OCSPStaple) > 0 544 545 hs.transcript.Write(certMsg.marshal()) 546 if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { 547 return err 548 } 549 550 // If we sent an empty certificate message, skip the CertificateVerify. 551 if len(cert.Certificate) == 0 { 552 return nil 553 } 554 555 certVerifyMsg := new(certificateVerifyMsg) 556 certVerifyMsg.hasSignatureAlgorithm = true 557 558 supportedAlgs := signatureSchemesForCertificate(c.vers, cert) 559 if supportedAlgs == nil { 560 c.sendAlert(alertInternalError) 561 return unsupportedCertificateError(cert) 562 } 563 // Pick signature scheme in server preference order, as the client 564 // preference order is not configurable. 565 for _, preferredAlg := range hs.certReq.supportedSignatureAlgorithms { 566 if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) { 567 certVerifyMsg.signatureAlgorithm = preferredAlg 568 break 569 } 570 } 571 if certVerifyMsg.signatureAlgorithm == 0 { 572 // getClientCertificate returned a certificate incompatible with the 573 // CertificateRequestInfo supported signature algorithms. 574 c.sendAlert(alertHandshakeFailure) 575 return errors.New("tls: server doesn't support selected certificate") 576 } 577 578 sigType := signatureFromSignatureScheme(certVerifyMsg.signatureAlgorithm) 579 sigHash, err := hashFromSignatureScheme(certVerifyMsg.signatureAlgorithm) 580 if sigType == 0 || err != nil { 581 return c.sendAlert(alertInternalError) 582 } 583 h := sigHash.New() 584 writeSignedMessage(h, clientSignatureContext, hs.transcript) 585 586 signOpts := crypto.SignerOpts(sigHash) 587 if sigType == signatureRSAPSS { 588 signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} 589 } 590 sig, err := cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), h.Sum(nil), signOpts) 591 if err != nil { 592 c.sendAlert(alertInternalError) 593 return errors.New("tls: failed to sign handshake: " + err.Error()) 594 } 595 certVerifyMsg.signature = sig 596 597 hs.transcript.Write(certVerifyMsg.marshal()) 598 if _, err := c.writeRecord(recordTypeHandshake, certVerifyMsg.marshal()); err != nil { 599 return err 600 } 601 602 return nil 603 } 604 605 func (hs *clientHandshakeStateTLS13) sendClientFinished() error { 606 c := hs.c 607 608 finished := &finishedMsg{ 609 verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript), 610 } 611 612 hs.transcript.Write(finished.marshal()) 613 if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { 614 return err 615 } 616 617 c.out.setTrafficSecret(hs.suite, hs.trafficSecret) 618 619 if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil { 620 c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret, 621 resumptionLabel, hs.transcript) 622 } 623 624 return nil 625 } 626 627 func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { 628 if !c.isClient { 629 c.sendAlert(alertUnexpectedMessage) 630 return errors.New("tls: received new session ticket from a client") 631 } 632 633 if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { 634 return nil 635 } 636 637 // See RFC 8446, Section 4.6.1. 638 if msg.lifetime == 0 { 639 return nil 640 } 641 lifetime := time.Duration(msg.lifetime) * time.Second 642 if lifetime > maxSessionTicketLifetime { 643 c.sendAlert(alertIllegalParameter) 644 return errors.New("tls: received a session ticket with invalid lifetime") 645 } 646 647 cipherSuite := cipherSuiteTLS13ByID(c.cipherSuite) 648 if cipherSuite == nil || c.resumptionSecret == nil { 649 return c.sendAlert(alertInternalError) 650 } 651 652 // Save the resumption_master_secret and nonce instead of deriving the PSK 653 // to do the least amount of work on NewSessionTicket messages before we 654 // know if the ticket will be used. Forward secrecy of resumed connections 655 // is guaranteed by the requirement for pskModeDHE. 656 session := &ClientSessionState{ 657 sessionTicket: msg.label, 658 vers: c.vers, 659 cipherSuite: c.cipherSuite, 660 masterSecret: c.resumptionSecret, 661 serverCertificates: c.peerCertificates, 662 verifiedChains: c.verifiedChains, 663 receivedAt: c.config.time(), 664 nonce: msg.nonce, 665 useBy: c.config.time().Add(lifetime), 666 ageAdd: msg.ageAdd, 667 } 668 669 cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config) 670 c.config.ClientSessionCache.Put(cacheKey, session) 671 672 return nil 673 }