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