github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/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/apernet/quic-go/internal/protocol"
    15  	"github.com/apernet/quic-go/internal/qerr"
    16  	"github.com/apernet/quic-go/internal/qtls"
    17  	"github.com/apernet/quic-go/internal/utils"
    18  	"github.com/apernet/quic-go/internal/wire"
    19  	"github.com/apernet/quic-go/logging"
    20  	"github.com/apernet/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  }