github.com/mikelsr/quic-go@v0.36.1-0.20230701132136-1d9415b66898/internal/handshake/crypto_setup.go (about)

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