github.com/quic-go/quic-go@v0.44.0/internal/handshake/crypto_setup.go (about) 1 package handshake 2 3 import ( 4 "context" 5 "crypto/tls" 6 "errors" 7 "fmt" 8 "net" 9 "strings" 10 "sync/atomic" 11 "time" 12 13 "github.com/quic-go/quic-go/internal/protocol" 14 "github.com/quic-go/quic-go/internal/qerr" 15 "github.com/quic-go/quic-go/internal/qtls" 16 "github.com/quic-go/quic-go/internal/utils" 17 "github.com/quic-go/quic-go/internal/wire" 18 "github.com/quic-go/quic-go/logging" 19 "github.com/quic-go/quic-go/quicvarint" 20 ) 21 22 type quicVersionContextKey struct{} 23 24 var QUICVersionContextKey = &quicVersionContextKey{} 25 26 const clientSessionStateRevision = 4 27 28 type cryptoSetup struct { 29 tlsConf *tls.Config 30 conn *tls.QUICConn 31 32 events []Event 33 34 version protocol.Version 35 36 ourParams *wire.TransportParameters 37 peerParams *wire.TransportParameters 38 39 zeroRTTParameters *wire.TransportParameters 40 allow0RTT bool 41 42 rttStats *utils.RTTStats 43 44 tracer *logging.ConnectionTracer 45 logger utils.Logger 46 47 perspective protocol.Perspective 48 49 handshakeCompleteTime time.Time 50 51 zeroRTTOpener LongHeaderOpener // only set for the server 52 zeroRTTSealer LongHeaderSealer // only set for the client 53 54 initialOpener LongHeaderOpener 55 initialSealer LongHeaderSealer 56 57 handshakeOpener LongHeaderOpener 58 handshakeSealer LongHeaderSealer 59 60 used0RTT atomic.Bool 61 62 aead *updatableAEAD 63 has1RTTSealer bool 64 has1RTTOpener bool 65 } 66 67 var _ CryptoSetup = &cryptoSetup{} 68 69 // NewCryptoSetupClient creates a new crypto setup for the client 70 func NewCryptoSetupClient( 71 connID protocol.ConnectionID, 72 tp *wire.TransportParameters, 73 tlsConf *tls.Config, 74 enable0RTT bool, 75 rttStats *utils.RTTStats, 76 tracer *logging.ConnectionTracer, 77 logger utils.Logger, 78 version protocol.Version, 79 ) CryptoSetup { 80 cs := newCryptoSetup( 81 connID, 82 tp, 83 rttStats, 84 tracer, 85 logger, 86 protocol.PerspectiveClient, 87 version, 88 ) 89 90 tlsConf = tlsConf.Clone() 91 tlsConf.MinVersion = tls.VersionTLS13 92 quicConf := &tls.QUICConfig{TLSConfig: tlsConf} 93 qtls.SetupConfigForClient(quicConf, cs.marshalDataForSessionState, cs.handleDataFromSessionState) 94 cs.tlsConf = tlsConf 95 cs.allow0RTT = enable0RTT 96 97 cs.conn = tls.QUICClient(quicConf) 98 cs.conn.SetTransportParameters(cs.ourParams.Marshal(protocol.PerspectiveClient)) 99 100 return cs 101 } 102 103 // NewCryptoSetupServer creates a new crypto setup for the server 104 func NewCryptoSetupServer( 105 connID protocol.ConnectionID, 106 localAddr, remoteAddr net.Addr, 107 tp *wire.TransportParameters, 108 tlsConf *tls.Config, 109 allow0RTT bool, 110 rttStats *utils.RTTStats, 111 tracer *logging.ConnectionTracer, 112 logger utils.Logger, 113 version protocol.Version, 114 ) CryptoSetup { 115 cs := newCryptoSetup( 116 connID, 117 tp, 118 rttStats, 119 tracer, 120 logger, 121 protocol.PerspectiveServer, 122 version, 123 ) 124 cs.allow0RTT = allow0RTT 125 126 quicConf := &tls.QUICConfig{TLSConfig: tlsConf} 127 qtls.SetupConfigForServer(quicConf, cs.allow0RTT, cs.getDataForSessionTicket, cs.handleSessionTicket) 128 addConnToClientHelloInfo(quicConf.TLSConfig, localAddr, remoteAddr) 129 130 cs.tlsConf = quicConf.TLSConfig 131 cs.conn = tls.QUICServer(quicConf) 132 133 return cs 134 } 135 136 // The tls.Config contains two callbacks that pass in a tls.ClientHelloInfo. 137 // Since crypto/tls doesn't do it, we need to make sure to set the Conn field with a fake net.Conn 138 // that allows the caller to get the local and the remote address. 139 func addConnToClientHelloInfo(conf *tls.Config, localAddr, remoteAddr net.Addr) { 140 if conf.GetConfigForClient != nil { 141 gcfc := conf.GetConfigForClient 142 conf.GetConfigForClient = func(info *tls.ClientHelloInfo) (*tls.Config, error) { 143 info.Conn = &conn{localAddr: localAddr, remoteAddr: remoteAddr} 144 c, err := gcfc(info) 145 if c != nil { 146 c = c.Clone() 147 // This won't be necessary anymore once https://github.com/golang/go/issues/63722 is accepted. 148 c.MinVersion = tls.VersionTLS13 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.Version, 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 tls.QUICEvent) (done bool, err error) { 264 switch ev.Kind { 265 case tls.QUICNoEvent: 266 return true, nil 267 case tls.QUICSetReadSecret: 268 h.setReadKey(ev.Level, ev.Suite, ev.Data) 269 return false, nil 270 case tls.QUICSetWriteSecret: 271 h.setWriteKey(ev.Level, ev.Suite, ev.Data) 272 return false, nil 273 case tls.QUICTransportParameters: 274 return false, h.handleTransportParameters(ev.Data) 275 case tls.QUICTransportParametersRequired: 276 h.conn.SetTransportParameters(h.ourParams.Marshal(h.perspective)) 277 return false, nil 278 case tls.QUICRejectedEarlyData: 279 h.rejected0RTT() 280 return false, nil 281 case tls.QUICWriteData: 282 h.writeRecord(ev.Level, ev.Data) 283 return false, nil 284 case tls.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(earlyData bool) []byte { 313 b := make([]byte, 0, 256) 314 b = quicvarint.Append(b, clientSessionStateRevision) 315 b = quicvarint.Append(b, uint64(h.rttStats.SmoothedRTT().Microseconds())) 316 if earlyData { 317 // only save the transport parameters for 0-RTT enabled session tickets 318 return h.peerParams.MarshalForSessionTicket(b) 319 } 320 return b 321 } 322 323 func (h *cryptoSetup) handleDataFromSessionState(data []byte, earlyData bool) (allowEarlyData bool) { 324 rtt, tp, err := decodeDataFromSessionState(data, earlyData) 325 if err != nil { 326 h.logger.Debugf("Restoring of transport parameters from session ticket failed: %s", err.Error()) 327 return 328 } 329 h.rttStats.SetInitialRTT(rtt) 330 // The session ticket might have been saved from a connection that allowed 0-RTT, 331 // and therefore contain transport parameters. 332 // Only use them if 0-RTT is actually used on the new connection. 333 if tp != nil && h.allow0RTT { 334 h.zeroRTTParameters = tp 335 return true 336 } 337 return false 338 } 339 340 func decodeDataFromSessionState(b []byte, earlyData bool) (time.Duration, *wire.TransportParameters, error) { 341 ver, l, err := quicvarint.Parse(b) 342 if err != nil { 343 return 0, nil, err 344 } 345 b = b[l:] 346 if ver != clientSessionStateRevision { 347 return 0, nil, fmt.Errorf("mismatching version. Got %d, expected %d", ver, clientSessionStateRevision) 348 } 349 rttEncoded, l, err := quicvarint.Parse(b) 350 if err != nil { 351 return 0, nil, err 352 } 353 b = b[l:] 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(b); 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 }