github.com/MerlinKodo/quic-go@v0.39.2/internal/handshake/crypto_setup.go (about) 1 package handshake 2 3 import ( 4 "bytes" 5 "context" 6 "crypto/tls" 7 "errors" 8 "fmt" 9 "net" 10 "strings" 11 "sync" 12 "sync/atomic" 13 "time" 14 15 "github.com/MerlinKodo/quic-go/internal/protocol" 16 "github.com/MerlinKodo/quic-go/internal/qerr" 17 "github.com/MerlinKodo/quic-go/internal/qtls" 18 "github.com/MerlinKodo/quic-go/internal/utils" 19 "github.com/MerlinKodo/quic-go/internal/wire" 20 "github.com/MerlinKodo/quic-go/logging" 21 "github.com/MerlinKodo/quic-go/quicvarint" 22 ) 23 24 type quicVersionContextKey struct{} 25 26 var QUICVersionContextKey = &quicVersionContextKey{} 27 28 const clientSessionStateRevision = 3 29 30 type cryptoSetup struct { 31 tlsConf *tls.Config 32 conn *qtls.QUICConn 33 34 events []Event 35 36 version protocol.VersionNumber 37 38 ourParams *wire.TransportParameters 39 peerParams *wire.TransportParameters 40 41 zeroRTTParameters *wire.TransportParameters 42 allow0RTT bool 43 44 rttStats *utils.RTTStats 45 46 tracer *logging.ConnectionTracer 47 logger utils.Logger 48 49 perspective protocol.Perspective 50 51 mutex sync.Mutex // protects all members below 52 53 handshakeCompleteTime time.Time 54 55 zeroRTTOpener LongHeaderOpener // only set for the server 56 zeroRTTSealer LongHeaderSealer // only set for the client 57 58 initialOpener LongHeaderOpener 59 initialSealer LongHeaderSealer 60 61 handshakeOpener LongHeaderOpener 62 handshakeSealer LongHeaderSealer 63 64 used0RTT atomic.Bool 65 66 aead *updatableAEAD 67 has1RTTSealer bool 68 has1RTTOpener bool 69 } 70 71 var _ CryptoSetup = &cryptoSetup{} 72 73 // NewCryptoSetupClient creates a new crypto setup for the client 74 func NewCryptoSetupClient( 75 connID protocol.ConnectionID, 76 tp *wire.TransportParameters, 77 tlsConf *tls.Config, 78 enable0RTT bool, 79 rttStats *utils.RTTStats, 80 tracer *logging.ConnectionTracer, 81 logger utils.Logger, 82 version protocol.VersionNumber, 83 ) CryptoSetup { 84 cs := newCryptoSetup( 85 connID, 86 tp, 87 rttStats, 88 tracer, 89 logger, 90 protocol.PerspectiveClient, 91 version, 92 ) 93 94 tlsConf = tlsConf.Clone() 95 tlsConf.MinVersion = tls.VersionTLS13 96 quicConf := &qtls.QUICConfig{TLSConfig: tlsConf} 97 qtls.SetupConfigForClient(quicConf, cs.marshalDataForSessionState, cs.handleDataFromSessionState) 98 cs.tlsConf = tlsConf 99 100 cs.conn = qtls.QUICClient(quicConf) 101 cs.conn.SetTransportParameters(cs.ourParams.Marshal(protocol.PerspectiveClient)) 102 103 return cs 104 } 105 106 // NewCryptoSetupServer creates a new crypto setup for the server 107 func NewCryptoSetupServer( 108 connID protocol.ConnectionID, 109 localAddr, remoteAddr net.Addr, 110 tp *wire.TransportParameters, 111 tlsConf *tls.Config, 112 allow0RTT bool, 113 rttStats *utils.RTTStats, 114 tracer *logging.ConnectionTracer, 115 logger utils.Logger, 116 version protocol.VersionNumber, 117 ) CryptoSetup { 118 cs := newCryptoSetup( 119 connID, 120 tp, 121 rttStats, 122 tracer, 123 logger, 124 protocol.PerspectiveServer, 125 version, 126 ) 127 cs.allow0RTT = allow0RTT 128 129 quicConf := &qtls.QUICConfig{TLSConfig: tlsConf} 130 qtls.SetupConfigForServer(quicConf, cs.allow0RTT, cs.getDataForSessionTicket, cs.handleSessionTicket) 131 addConnToClientHelloInfo(quicConf.TLSConfig, localAddr, remoteAddr) 132 133 cs.tlsConf = quicConf.TLSConfig 134 cs.conn = qtls.QUICServer(quicConf) 135 136 return cs 137 } 138 139 // The tls.Config contains two callbacks that pass in a tls.ClientHelloInfo. 140 // Since crypto/tls doesn't do it, we need to make sure to set the Conn field with a fake net.Conn 141 // that allows the caller to get the local and the remote address. 142 func addConnToClientHelloInfo(conf *tls.Config, localAddr, remoteAddr net.Addr) { 143 if conf.GetConfigForClient != nil { 144 gcfc := conf.GetConfigForClient 145 conf.GetConfigForClient = func(info *tls.ClientHelloInfo) (*tls.Config, error) { 146 info.Conn = &conn{localAddr: localAddr, remoteAddr: remoteAddr} 147 c, err := gcfc(info) 148 if c != nil { 149 // We're returning a tls.Config here, so we need to apply this recursively. 150 addConnToClientHelloInfo(c, localAddr, remoteAddr) 151 } 152 return c, err 153 } 154 } 155 if conf.GetCertificate != nil { 156 gc := conf.GetCertificate 157 conf.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { 158 info.Conn = &conn{localAddr: localAddr, remoteAddr: remoteAddr} 159 return gc(info) 160 } 161 } 162 } 163 164 func newCryptoSetup( 165 connID protocol.ConnectionID, 166 tp *wire.TransportParameters, 167 rttStats *utils.RTTStats, 168 tracer *logging.ConnectionTracer, 169 logger utils.Logger, 170 perspective protocol.Perspective, 171 version protocol.VersionNumber, 172 ) *cryptoSetup { 173 initialSealer, initialOpener := NewInitialAEAD(connID, perspective, version) 174 if tracer != nil && tracer.UpdatedKeyFromTLS != nil { 175 tracer.UpdatedKeyFromTLS(protocol.EncryptionInitial, protocol.PerspectiveClient) 176 tracer.UpdatedKeyFromTLS(protocol.EncryptionInitial, protocol.PerspectiveServer) 177 } 178 return &cryptoSetup{ 179 initialSealer: initialSealer, 180 initialOpener: initialOpener, 181 aead: newUpdatableAEAD(rttStats, tracer, logger, version), 182 events: make([]Event, 0, 16), 183 ourParams: tp, 184 rttStats: rttStats, 185 tracer: tracer, 186 logger: logger, 187 perspective: perspective, 188 version: version, 189 } 190 } 191 192 func (h *cryptoSetup) ChangeConnectionID(id protocol.ConnectionID) { 193 initialSealer, initialOpener := NewInitialAEAD(id, h.perspective, h.version) 194 h.initialSealer = initialSealer 195 h.initialOpener = initialOpener 196 if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil { 197 h.tracer.UpdatedKeyFromTLS(protocol.EncryptionInitial, protocol.PerspectiveClient) 198 h.tracer.UpdatedKeyFromTLS(protocol.EncryptionInitial, protocol.PerspectiveServer) 199 } 200 } 201 202 func (h *cryptoSetup) SetLargest1RTTAcked(pn protocol.PacketNumber) error { 203 return h.aead.SetLargestAcked(pn) 204 } 205 206 func (h *cryptoSetup) StartHandshake() error { 207 err := h.conn.Start(context.WithValue(context.Background(), QUICVersionContextKey, h.version)) 208 if err != nil { 209 return wrapError(err) 210 } 211 for { 212 ev := h.conn.NextEvent() 213 done, err := h.handleEvent(ev) 214 if err != nil { 215 return wrapError(err) 216 } 217 if done { 218 break 219 } 220 } 221 if h.perspective == protocol.PerspectiveClient { 222 if h.zeroRTTSealer != nil && h.zeroRTTParameters != nil { 223 h.logger.Debugf("Doing 0-RTT.") 224 h.events = append(h.events, Event{Kind: EventRestoredTransportParameters, TransportParameters: h.zeroRTTParameters}) 225 } else { 226 h.logger.Debugf("Not doing 0-RTT. Has sealer: %t, has params: %t", h.zeroRTTSealer != nil, h.zeroRTTParameters != nil) 227 } 228 } 229 return nil 230 } 231 232 // Close closes the crypto setup. 233 // It aborts the handshake, if it is still running. 234 func (h *cryptoSetup) Close() error { 235 return h.conn.Close() 236 } 237 238 // HandleMessage handles a TLS handshake message. 239 // It is called by the crypto streams when a new message is available. 240 func (h *cryptoSetup) HandleMessage(data []byte, encLevel protocol.EncryptionLevel) error { 241 if err := h.handleMessage(data, encLevel); err != nil { 242 return wrapError(err) 243 } 244 return nil 245 } 246 247 func (h *cryptoSetup) handleMessage(data []byte, encLevel protocol.EncryptionLevel) error { 248 if err := h.conn.HandleData(qtls.ToTLSEncryptionLevel(encLevel), data); err != nil { 249 return err 250 } 251 for { 252 ev := h.conn.NextEvent() 253 done, err := h.handleEvent(ev) 254 if err != nil { 255 return err 256 } 257 if done { 258 return nil 259 } 260 } 261 } 262 263 func (h *cryptoSetup) handleEvent(ev qtls.QUICEvent) (done bool, err error) { 264 switch ev.Kind { 265 case qtls.QUICNoEvent: 266 return true, nil 267 case qtls.QUICSetReadSecret: 268 h.SetReadKey(ev.Level, ev.Suite, ev.Data) 269 return false, nil 270 case qtls.QUICSetWriteSecret: 271 h.SetWriteKey(ev.Level, ev.Suite, ev.Data) 272 return false, nil 273 case qtls.QUICTransportParameters: 274 return false, h.handleTransportParameters(ev.Data) 275 case qtls.QUICTransportParametersRequired: 276 h.conn.SetTransportParameters(h.ourParams.Marshal(h.perspective)) 277 return false, nil 278 case qtls.QUICRejectedEarlyData: 279 h.rejected0RTT() 280 return false, nil 281 case qtls.QUICWriteData: 282 h.WriteRecord(ev.Level, ev.Data) 283 return false, nil 284 case qtls.QUICHandshakeDone: 285 h.handshakeComplete() 286 return false, nil 287 default: 288 return false, fmt.Errorf("unexpected event: %d", ev.Kind) 289 } 290 } 291 292 func (h *cryptoSetup) NextEvent() Event { 293 if len(h.events) == 0 { 294 return Event{Kind: EventNoEvent} 295 } 296 ev := h.events[0] 297 h.events = h.events[1:] 298 return ev 299 } 300 301 func (h *cryptoSetup) handleTransportParameters(data []byte) error { 302 var tp wire.TransportParameters 303 if err := tp.Unmarshal(data, h.perspective.Opposite()); err != nil { 304 return err 305 } 306 h.peerParams = &tp 307 h.events = append(h.events, Event{Kind: EventReceivedTransportParameters, TransportParameters: h.peerParams}) 308 return nil 309 } 310 311 // must be called after receiving the transport parameters 312 func (h *cryptoSetup) marshalDataForSessionState() []byte { 313 b := make([]byte, 0, 256) 314 b = quicvarint.Append(b, clientSessionStateRevision) 315 b = quicvarint.Append(b, uint64(h.rttStats.SmoothedRTT().Microseconds())) 316 return h.peerParams.MarshalForSessionTicket(b) 317 } 318 319 func (h *cryptoSetup) handleDataFromSessionState(data []byte) { 320 tp, err := h.handleDataFromSessionStateImpl(data) 321 if err != nil { 322 h.logger.Debugf("Restoring of transport parameters from session ticket failed: %s", err.Error()) 323 return 324 } 325 h.zeroRTTParameters = tp 326 } 327 328 func (h *cryptoSetup) handleDataFromSessionStateImpl(data []byte) (*wire.TransportParameters, error) { 329 r := bytes.NewReader(data) 330 ver, err := quicvarint.Read(r) 331 if err != nil { 332 return nil, err 333 } 334 if ver != clientSessionStateRevision { 335 return nil, fmt.Errorf("mismatching version. Got %d, expected %d", ver, clientSessionStateRevision) 336 } 337 rtt, err := quicvarint.Read(r) 338 if err != nil { 339 return nil, err 340 } 341 h.rttStats.SetInitialRTT(time.Duration(rtt) * time.Microsecond) 342 var tp wire.TransportParameters 343 if err := tp.UnmarshalFromSessionTicket(r); err != nil { 344 return nil, err 345 } 346 return &tp, nil 347 } 348 349 func (h *cryptoSetup) getDataForSessionTicket() []byte { 350 ticket := &sessionTicket{ 351 RTT: h.rttStats.SmoothedRTT(), 352 } 353 if h.allow0RTT { 354 ticket.Parameters = h.ourParams 355 } 356 return ticket.Marshal() 357 } 358 359 // GetSessionTicket generates a new session ticket. 360 // Due to limitations in crypto/tls, it's only possible to generate a single session ticket per connection. 361 // It is only valid for the server. 362 func (h *cryptoSetup) GetSessionTicket() ([]byte, error) { 363 if err := qtls.SendSessionTicket(h.conn, h.allow0RTT); err != nil { 364 // Session tickets might be disabled by tls.Config.SessionTicketsDisabled. 365 // We can't check h.tlsConfig here, since the actual config might have been obtained from 366 // the GetConfigForClient callback. 367 // See https://github.com/golang/go/issues/62032. 368 // Once that issue is resolved, this error assertion can be removed. 369 if strings.Contains(err.Error(), "session ticket keys unavailable") { 370 return nil, nil 371 } 372 return nil, err 373 } 374 ev := h.conn.NextEvent() 375 if ev.Kind != qtls.QUICWriteData || ev.Level != qtls.QUICEncryptionLevelApplication { 376 panic("crypto/tls bug: where's my session ticket?") 377 } 378 ticket := ev.Data 379 if ev := h.conn.NextEvent(); ev.Kind != qtls.QUICNoEvent { 380 panic("crypto/tls bug: why more than one ticket?") 381 } 382 return ticket, nil 383 } 384 385 // handleSessionTicket is called for the server when receiving the client's session ticket. 386 // It reads parameters from the session ticket and decides whether to accept 0-RTT when the session ticket is used for 0-RTT. 387 func (h *cryptoSetup) handleSessionTicket(sessionTicketData []byte, using0RTT bool) bool { 388 var t sessionTicket 389 if err := t.Unmarshal(sessionTicketData, using0RTT); err != nil { 390 h.logger.Debugf("Unmarshalling session ticket failed: %s", err.Error()) 391 return false 392 } 393 h.rttStats.SetInitialRTT(t.RTT) 394 if !using0RTT { 395 return false 396 } 397 valid := h.ourParams.ValidFor0RTT(t.Parameters) 398 if !valid { 399 h.logger.Debugf("Transport parameters changed. Rejecting 0-RTT.") 400 return false 401 } 402 if !h.allow0RTT { 403 h.logger.Debugf("0-RTT not allowed. Rejecting 0-RTT.") 404 return false 405 } 406 h.logger.Debugf("Accepting 0-RTT. Restoring RTT from session ticket: %s", t.RTT) 407 return true 408 } 409 410 // rejected0RTT is called for the client when the server rejects 0-RTT. 411 func (h *cryptoSetup) rejected0RTT() { 412 h.logger.Debugf("0-RTT was rejected. Dropping 0-RTT keys.") 413 414 h.mutex.Lock() 415 had0RTTKeys := h.zeroRTTSealer != nil 416 h.zeroRTTSealer = nil 417 h.mutex.Unlock() 418 419 if had0RTTKeys { 420 h.events = append(h.events, Event{Kind: EventDiscard0RTTKeys}) 421 } 422 } 423 424 func (h *cryptoSetup) SetReadKey(el qtls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { 425 suite := getCipherSuite(suiteID) 426 h.mutex.Lock() 427 //nolint:exhaustive // The TLS stack doesn't export Initial keys. 428 switch el { 429 case qtls.QUICEncryptionLevelEarly: 430 if h.perspective == protocol.PerspectiveClient { 431 panic("Received 0-RTT read key for the client") 432 } 433 h.zeroRTTOpener = newLongHeaderOpener( 434 createAEAD(suite, trafficSecret, h.version), 435 newHeaderProtector(suite, trafficSecret, true, h.version), 436 ) 437 h.used0RTT.Store(true) 438 if h.logger.Debug() { 439 h.logger.Debugf("Installed 0-RTT Read keys (using %s)", tls.CipherSuiteName(suite.ID)) 440 } 441 case qtls.QUICEncryptionLevelHandshake: 442 h.handshakeOpener = newLongHeaderOpener( 443 createAEAD(suite, trafficSecret, h.version), 444 newHeaderProtector(suite, trafficSecret, true, h.version), 445 ) 446 if h.logger.Debug() { 447 h.logger.Debugf("Installed Handshake Read keys (using %s)", tls.CipherSuiteName(suite.ID)) 448 } 449 case qtls.QUICEncryptionLevelApplication: 450 h.aead.SetReadKey(suite, trafficSecret) 451 h.has1RTTOpener = true 452 if h.logger.Debug() { 453 h.logger.Debugf("Installed 1-RTT Read keys (using %s)", tls.CipherSuiteName(suite.ID)) 454 } 455 default: 456 panic("unexpected read encryption level") 457 } 458 h.mutex.Unlock() 459 h.events = append(h.events, Event{Kind: EventReceivedReadKeys}) 460 if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil { 461 h.tracer.UpdatedKeyFromTLS(qtls.FromTLSEncryptionLevel(el), h.perspective.Opposite()) 462 } 463 } 464 465 func (h *cryptoSetup) SetWriteKey(el qtls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { 466 suite := getCipherSuite(suiteID) 467 h.mutex.Lock() 468 //nolint:exhaustive // The TLS stack doesn't export Initial keys. 469 switch el { 470 case qtls.QUICEncryptionLevelEarly: 471 if h.perspective == protocol.PerspectiveServer { 472 panic("Received 0-RTT write key for the server") 473 } 474 h.zeroRTTSealer = newLongHeaderSealer( 475 createAEAD(suite, trafficSecret, h.version), 476 newHeaderProtector(suite, trafficSecret, true, h.version), 477 ) 478 h.mutex.Unlock() 479 if h.logger.Debug() { 480 h.logger.Debugf("Installed 0-RTT Write keys (using %s)", tls.CipherSuiteName(suite.ID)) 481 } 482 if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil { 483 h.tracer.UpdatedKeyFromTLS(protocol.Encryption0RTT, h.perspective) 484 } 485 // don't set used0RTT here. 0-RTT might still get rejected. 486 return 487 case qtls.QUICEncryptionLevelHandshake: 488 h.handshakeSealer = newLongHeaderSealer( 489 createAEAD(suite, trafficSecret, h.version), 490 newHeaderProtector(suite, trafficSecret, true, h.version), 491 ) 492 if h.logger.Debug() { 493 h.logger.Debugf("Installed Handshake Write keys (using %s)", tls.CipherSuiteName(suite.ID)) 494 } 495 case qtls.QUICEncryptionLevelApplication: 496 h.aead.SetWriteKey(suite, trafficSecret) 497 h.has1RTTSealer = true 498 if h.logger.Debug() { 499 h.logger.Debugf("Installed 1-RTT Write keys (using %s)", tls.CipherSuiteName(suite.ID)) 500 } 501 if h.zeroRTTSealer != nil { 502 // Once we receive handshake keys, we know that 0-RTT was not rejected. 503 h.used0RTT.Store(true) 504 h.zeroRTTSealer = nil 505 h.logger.Debugf("Dropping 0-RTT keys.") 506 if h.tracer != nil && h.tracer.DroppedEncryptionLevel != nil { 507 h.tracer.DroppedEncryptionLevel(protocol.Encryption0RTT) 508 } 509 } 510 default: 511 panic("unexpected write encryption level") 512 } 513 h.mutex.Unlock() 514 if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil { 515 h.tracer.UpdatedKeyFromTLS(qtls.FromTLSEncryptionLevel(el), h.perspective) 516 } 517 } 518 519 // WriteRecord is called when TLS writes data 520 func (h *cryptoSetup) WriteRecord(encLevel qtls.QUICEncryptionLevel, p []byte) { 521 //nolint:exhaustive // handshake records can only be written for Initial and Handshake. 522 switch encLevel { 523 case qtls.QUICEncryptionLevelInitial: 524 h.events = append(h.events, Event{Kind: EventWriteInitialData, Data: p}) 525 case qtls.QUICEncryptionLevelHandshake: 526 h.events = append(h.events, Event{Kind: EventWriteHandshakeData, Data: p}) 527 case qtls.QUICEncryptionLevelApplication: 528 panic("unexpected write") 529 default: 530 panic(fmt.Sprintf("unexpected write encryption level: %s", encLevel)) 531 } 532 } 533 534 func (h *cryptoSetup) DiscardInitialKeys() { 535 h.mutex.Lock() 536 dropped := h.initialOpener != nil 537 h.initialOpener = nil 538 h.initialSealer = nil 539 h.mutex.Unlock() 540 if dropped { 541 h.logger.Debugf("Dropping Initial keys.") 542 } 543 } 544 545 func (h *cryptoSetup) handshakeComplete() { 546 h.handshakeCompleteTime = time.Now() 547 h.events = append(h.events, Event{Kind: EventHandshakeComplete}) 548 } 549 550 func (h *cryptoSetup) SetHandshakeConfirmed() { 551 h.aead.SetHandshakeConfirmed() 552 // drop Handshake keys 553 var dropped bool 554 h.mutex.Lock() 555 if h.handshakeOpener != nil { 556 h.handshakeOpener = nil 557 h.handshakeSealer = nil 558 dropped = true 559 } 560 h.mutex.Unlock() 561 if dropped { 562 h.logger.Debugf("Dropping Handshake keys.") 563 } 564 } 565 566 func (h *cryptoSetup) GetInitialSealer() (LongHeaderSealer, error) { 567 h.mutex.Lock() 568 defer h.mutex.Unlock() 569 570 if h.initialSealer == nil { 571 return nil, ErrKeysDropped 572 } 573 return h.initialSealer, nil 574 } 575 576 func (h *cryptoSetup) Get0RTTSealer() (LongHeaderSealer, error) { 577 h.mutex.Lock() 578 defer h.mutex.Unlock() 579 580 if h.zeroRTTSealer == nil { 581 return nil, ErrKeysDropped 582 } 583 return h.zeroRTTSealer, nil 584 } 585 586 func (h *cryptoSetup) GetHandshakeSealer() (LongHeaderSealer, error) { 587 h.mutex.Lock() 588 defer h.mutex.Unlock() 589 590 if h.handshakeSealer == nil { 591 if h.initialSealer == nil { 592 return nil, ErrKeysDropped 593 } 594 return nil, ErrKeysNotYetAvailable 595 } 596 return h.handshakeSealer, nil 597 } 598 599 func (h *cryptoSetup) Get1RTTSealer() (ShortHeaderSealer, error) { 600 h.mutex.Lock() 601 defer h.mutex.Unlock() 602 603 if !h.has1RTTSealer { 604 return nil, ErrKeysNotYetAvailable 605 } 606 return h.aead, nil 607 } 608 609 func (h *cryptoSetup) GetInitialOpener() (LongHeaderOpener, error) { 610 h.mutex.Lock() 611 defer h.mutex.Unlock() 612 613 if h.initialOpener == nil { 614 return nil, ErrKeysDropped 615 } 616 return h.initialOpener, nil 617 } 618 619 func (h *cryptoSetup) Get0RTTOpener() (LongHeaderOpener, error) { 620 h.mutex.Lock() 621 defer h.mutex.Unlock() 622 623 if h.zeroRTTOpener == nil { 624 if h.initialOpener != nil { 625 return nil, ErrKeysNotYetAvailable 626 } 627 // if the initial opener is also not available, the keys were already dropped 628 return nil, ErrKeysDropped 629 } 630 return h.zeroRTTOpener, nil 631 } 632 633 func (h *cryptoSetup) GetHandshakeOpener() (LongHeaderOpener, error) { 634 h.mutex.Lock() 635 defer h.mutex.Unlock() 636 637 if h.handshakeOpener == nil { 638 if h.initialOpener != nil { 639 return nil, ErrKeysNotYetAvailable 640 } 641 // if the initial opener is also not available, the keys were already dropped 642 return nil, ErrKeysDropped 643 } 644 return h.handshakeOpener, nil 645 } 646 647 func (h *cryptoSetup) Get1RTTOpener() (ShortHeaderOpener, error) { 648 h.mutex.Lock() 649 defer h.mutex.Unlock() 650 651 if h.zeroRTTOpener != nil && time.Since(h.handshakeCompleteTime) > 3*h.rttStats.PTO(true) { 652 h.zeroRTTOpener = nil 653 h.logger.Debugf("Dropping 0-RTT keys.") 654 if h.tracer != nil && h.tracer.DroppedEncryptionLevel != nil { 655 h.tracer.DroppedEncryptionLevel(protocol.Encryption0RTT) 656 } 657 } 658 659 if !h.has1RTTOpener { 660 return nil, ErrKeysNotYetAvailable 661 } 662 return h.aead, nil 663 } 664 665 func (h *cryptoSetup) ConnectionState() ConnectionState { 666 return ConnectionState{ 667 ConnectionState: h.conn.ConnectionState(), 668 Used0RTT: h.used0RTT.Load(), 669 } 670 } 671 672 func wrapError(err error) error { 673 // alert 80 is an internal error 674 if alertErr := qtls.AlertError(0); errors.As(err, &alertErr) && alertErr != 80 { 675 return qerr.NewLocalCryptoError(uint8(alertErr), err) 676 } 677 return &qerr.TransportError{ErrorCode: qerr.InternalError, ErrorMessage: err.Error()} 678 }