github.com/sagernet/quic-go@v0.43.1-beta.1/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/sagernet/quic-go/internal/protocol" 15 "github.com/sagernet/quic-go/internal/qerr" 16 "github.com/sagernet/quic-go/internal/qtls" 17 "github.com/sagernet/quic-go/internal/utils" 18 "github.com/sagernet/quic-go/internal/wire" 19 "github.com/sagernet/quic-go/logging" 20 "github.com/sagernet/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 *qtls.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 := &qtls.QUICConfig{TLSConfig: tlsConf} 94 qtls.SetupConfigForClient(quicConf, cs.marshalDataForSessionState, cs.handleDataFromSessionState) 95 cs.tlsConf = tlsConf 96 cs.allow0RTT = enable0RTT 97 98 cs.conn = qtls.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 := &qtls.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 = qtls.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 qtls.QUICEvent) (done bool, err error) { 265 switch ev.Kind { 266 case qtls.QUICNoEvent: 267 return true, nil 268 case qtls.QUICSetReadSecret: 269 h.setReadKey(ev.Level, ev.Suite, ev.Data) 270 return false, nil 271 case qtls.QUICSetWriteSecret: 272 h.setWriteKey(ev.Level, ev.Suite, ev.Data) 273 return false, nil 274 case qtls.QUICTransportParameters: 275 return false, h.handleTransportParameters(ev.Data) 276 case qtls.QUICTransportParametersRequired: 277 h.conn.SetTransportParameters(h.ourParams.Marshal(h.perspective)) 278 return false, nil 279 case qtls.QUICRejectedEarlyData: 280 h.rejected0RTT() 281 return false, nil 282 case qtls.QUICWriteData: 283 h.writeRecord(ev.Level, ev.Data) 284 return false, nil 285 case qtls.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 := qtls.SendSessionTicket(h.conn, h.allow0RTT); err != nil { 380 // Session tickets might be disabled by tls.Config.SessionTicketsDisabled. 381 // We can't check h.tlsConfig here, since the actual config might have been obtained from 382 // the GetConfigForClient callback. 383 // See https://github.com/golang/go/issues/62032. 384 // Once that issue is resolved, this error assertion can be removed. 385 if strings.Contains(err.Error(), "session ticket keys unavailable") { 386 return nil, nil 387 } 388 return nil, err 389 } 390 ev := h.conn.NextEvent() 391 if ev.Kind != qtls.QUICWriteData || ev.Level != qtls.QUICEncryptionLevelApplication { 392 panic("crypto/tls bug: where's my session ticket?") 393 } 394 ticket := ev.Data 395 if ev := h.conn.NextEvent(); ev.Kind != qtls.QUICNoEvent { 396 panic("crypto/tls bug: why more than one ticket?") 397 } 398 return ticket, nil 399 } 400 401 // handleSessionTicket is called for the server when receiving the client's session ticket. 402 // It reads parameters from the session ticket and checks whether to accept 0-RTT if the session ticket enabled 0-RTT. 403 // Note that the fact that the session ticket allows 0-RTT doesn't mean that the actual TLS handshake enables 0-RTT: 404 // A client may use a 0-RTT enabled session to resume a TLS session without using 0-RTT. 405 func (h *cryptoSetup) handleSessionTicket(sessionTicketData []byte, using0RTT bool) bool { 406 var t sessionTicket 407 if err := t.Unmarshal(sessionTicketData, using0RTT); err != nil { 408 h.logger.Debugf("Unmarshalling session ticket failed: %s", err.Error()) 409 return false 410 } 411 h.rttStats.SetInitialRTT(t.RTT) 412 if !using0RTT { 413 return false 414 } 415 valid := h.ourParams.ValidFor0RTT(t.Parameters) 416 if !valid { 417 h.logger.Debugf("Transport parameters changed. Rejecting 0-RTT.") 418 return false 419 } 420 if !h.allow0RTT { 421 h.logger.Debugf("0-RTT not allowed. Rejecting 0-RTT.") 422 return false 423 } 424 h.logger.Debugf("Accepting 0-RTT. Restoring RTT from session ticket: %s", t.RTT) 425 return true 426 } 427 428 // rejected0RTT is called for the client when the server rejects 0-RTT. 429 func (h *cryptoSetup) rejected0RTT() { 430 h.logger.Debugf("0-RTT was rejected. Dropping 0-RTT keys.") 431 432 had0RTTKeys := h.zeroRTTSealer != nil 433 h.zeroRTTSealer = nil 434 435 if had0RTTKeys { 436 h.events = append(h.events, Event{Kind: EventDiscard0RTTKeys}) 437 } 438 } 439 440 func (h *cryptoSetup) setReadKey(el qtls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { 441 suite := getCipherSuite(suiteID) 442 //nolint:exhaustive // The TLS stack doesn't export Initial keys. 443 switch el { 444 case qtls.QUICEncryptionLevelEarly: 445 if h.perspective == protocol.PerspectiveClient { 446 panic("Received 0-RTT read key for the client") 447 } 448 h.zeroRTTOpener = newLongHeaderOpener( 449 createAEAD(suite, trafficSecret, h.version), 450 newHeaderProtector(suite, trafficSecret, true, h.version), 451 ) 452 h.used0RTT.Store(true) 453 if h.logger.Debug() { 454 h.logger.Debugf("Installed 0-RTT Read keys (using %s)", tls.CipherSuiteName(suite.ID)) 455 } 456 case qtls.QUICEncryptionLevelHandshake: 457 h.handshakeOpener = newLongHeaderOpener( 458 createAEAD(suite, trafficSecret, h.version), 459 newHeaderProtector(suite, trafficSecret, true, h.version), 460 ) 461 if h.logger.Debug() { 462 h.logger.Debugf("Installed Handshake Read keys (using %s)", tls.CipherSuiteName(suite.ID)) 463 } 464 case qtls.QUICEncryptionLevelApplication: 465 h.aead.SetReadKey(suite, trafficSecret) 466 h.has1RTTOpener = true 467 if h.logger.Debug() { 468 h.logger.Debugf("Installed 1-RTT Read keys (using %s)", tls.CipherSuiteName(suite.ID)) 469 } 470 default: 471 panic("unexpected read encryption level") 472 } 473 h.events = append(h.events, Event{Kind: EventReceivedReadKeys}) 474 if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil { 475 h.tracer.UpdatedKeyFromTLS(qtls.FromTLSEncryptionLevel(el), h.perspective.Opposite()) 476 } 477 } 478 479 func (h *cryptoSetup) setWriteKey(el qtls.QUICEncryptionLevel, suiteID uint16, trafficSecret []byte) { 480 suite := getCipherSuite(suiteID) 481 //nolint:exhaustive // The TLS stack doesn't export Initial keys. 482 switch el { 483 case qtls.QUICEncryptionLevelEarly: 484 if h.perspective == protocol.PerspectiveServer { 485 panic("Received 0-RTT write key for the server") 486 } 487 h.zeroRTTSealer = newLongHeaderSealer( 488 createAEAD(suite, trafficSecret, h.version), 489 newHeaderProtector(suite, trafficSecret, true, h.version), 490 ) 491 if h.logger.Debug() { 492 h.logger.Debugf("Installed 0-RTT Write keys (using %s)", tls.CipherSuiteName(suite.ID)) 493 } 494 if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil { 495 h.tracer.UpdatedKeyFromTLS(protocol.Encryption0RTT, h.perspective) 496 } 497 // don't set used0RTT here. 0-RTT might still get rejected. 498 return 499 case qtls.QUICEncryptionLevelHandshake: 500 h.handshakeSealer = newLongHeaderSealer( 501 createAEAD(suite, trafficSecret, h.version), 502 newHeaderProtector(suite, trafficSecret, true, h.version), 503 ) 504 if h.logger.Debug() { 505 h.logger.Debugf("Installed Handshake Write keys (using %s)", tls.CipherSuiteName(suite.ID)) 506 } 507 case qtls.QUICEncryptionLevelApplication: 508 h.aead.SetWriteKey(suite, trafficSecret) 509 h.has1RTTSealer = true 510 if h.logger.Debug() { 511 h.logger.Debugf("Installed 1-RTT Write keys (using %s)", tls.CipherSuiteName(suite.ID)) 512 } 513 if h.zeroRTTSealer != nil { 514 // Once we receive handshake keys, we know that 0-RTT was not rejected. 515 h.used0RTT.Store(true) 516 h.zeroRTTSealer = nil 517 h.logger.Debugf("Dropping 0-RTT keys.") 518 if h.tracer != nil && h.tracer.DroppedEncryptionLevel != nil { 519 h.tracer.DroppedEncryptionLevel(protocol.Encryption0RTT) 520 } 521 } 522 default: 523 panic("unexpected write encryption level") 524 } 525 if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil { 526 h.tracer.UpdatedKeyFromTLS(qtls.FromTLSEncryptionLevel(el), h.perspective) 527 } 528 } 529 530 // writeRecord is called when TLS writes data 531 func (h *cryptoSetup) writeRecord(encLevel qtls.QUICEncryptionLevel, p []byte) { 532 //nolint:exhaustive // handshake records can only be written for Initial and Handshake. 533 switch encLevel { 534 case qtls.QUICEncryptionLevelInitial: 535 h.events = append(h.events, Event{Kind: EventWriteInitialData, Data: p}) 536 case qtls.QUICEncryptionLevelHandshake: 537 h.events = append(h.events, Event{Kind: EventWriteHandshakeData, Data: p}) 538 case qtls.QUICEncryptionLevelApplication: 539 panic("unexpected write") 540 default: 541 panic(fmt.Sprintf("unexpected write encryption level: %s", encLevel)) 542 } 543 } 544 545 func (h *cryptoSetup) DiscardInitialKeys() { 546 dropped := h.initialOpener != nil 547 h.initialOpener = nil 548 h.initialSealer = nil 549 if dropped { 550 h.logger.Debugf("Dropping Initial keys.") 551 } 552 } 553 554 func (h *cryptoSetup) handshakeComplete() { 555 h.handshakeCompleteTime = time.Now() 556 h.events = append(h.events, Event{Kind: EventHandshakeComplete}) 557 } 558 559 func (h *cryptoSetup) SetHandshakeConfirmed() { 560 h.aead.SetHandshakeConfirmed() 561 // drop Handshake keys 562 var dropped bool 563 if h.handshakeOpener != nil { 564 h.handshakeOpener = nil 565 h.handshakeSealer = nil 566 dropped = true 567 } 568 if dropped { 569 h.logger.Debugf("Dropping Handshake keys.") 570 } 571 } 572 573 func (h *cryptoSetup) GetInitialSealer() (LongHeaderSealer, error) { 574 if h.initialSealer == nil { 575 return nil, ErrKeysDropped 576 } 577 return h.initialSealer, nil 578 } 579 580 func (h *cryptoSetup) Get0RTTSealer() (LongHeaderSealer, error) { 581 if h.zeroRTTSealer == nil { 582 return nil, ErrKeysDropped 583 } 584 return h.zeroRTTSealer, nil 585 } 586 587 func (h *cryptoSetup) GetHandshakeSealer() (LongHeaderSealer, error) { 588 if h.handshakeSealer == nil { 589 if h.initialSealer == nil { 590 return nil, ErrKeysDropped 591 } 592 return nil, ErrKeysNotYetAvailable 593 } 594 return h.handshakeSealer, nil 595 } 596 597 func (h *cryptoSetup) Get1RTTSealer() (ShortHeaderSealer, error) { 598 if !h.has1RTTSealer { 599 return nil, ErrKeysNotYetAvailable 600 } 601 return h.aead, nil 602 } 603 604 func (h *cryptoSetup) GetInitialOpener() (LongHeaderOpener, error) { 605 if h.initialOpener == nil { 606 return nil, ErrKeysDropped 607 } 608 return h.initialOpener, nil 609 } 610 611 func (h *cryptoSetup) Get0RTTOpener() (LongHeaderOpener, error) { 612 if h.zeroRTTOpener == nil { 613 if h.initialOpener != nil { 614 return nil, ErrKeysNotYetAvailable 615 } 616 // if the initial opener is also not available, the keys were already dropped 617 return nil, ErrKeysDropped 618 } 619 return h.zeroRTTOpener, nil 620 } 621 622 func (h *cryptoSetup) GetHandshakeOpener() (LongHeaderOpener, error) { 623 if h.handshakeOpener == 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.handshakeOpener, nil 631 } 632 633 func (h *cryptoSetup) Get1RTTOpener() (ShortHeaderOpener, error) { 634 if h.zeroRTTOpener != nil && time.Since(h.handshakeCompleteTime) > 3*h.rttStats.PTO(true) { 635 h.zeroRTTOpener = nil 636 h.logger.Debugf("Dropping 0-RTT keys.") 637 if h.tracer != nil && h.tracer.DroppedEncryptionLevel != nil { 638 h.tracer.DroppedEncryptionLevel(protocol.Encryption0RTT) 639 } 640 } 641 642 if !h.has1RTTOpener { 643 return nil, ErrKeysNotYetAvailable 644 } 645 return h.aead, nil 646 } 647 648 func (h *cryptoSetup) ConnectionState() ConnectionState { 649 return ConnectionState{ 650 ConnectionState: h.conn.ConnectionState(), 651 Used0RTT: h.used0RTT.Load(), 652 } 653 } 654 655 func wrapError(err error) error { 656 // alert 80 is an internal error 657 if alertErr := qtls.AlertError(0); errors.As(err, &alertErr) && alertErr != 80 { 658 return qerr.NewLocalCryptoError(uint8(alertErr), err) 659 } 660 return &qerr.TransportError{ErrorCode: qerr.InternalError, ErrorMessage: err.Error()} 661 }