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  }