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