forked from quic-go/quic-go
handshake: use new crypto/tls 0-RTT API (#4953)
* handshake: simplify method signature of cryptoSetup.handleEvent * use the new crypto/tls 0-RTT API
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/internal/qerr"
|
||||
"github.com/quic-go/quic-go/internal/qtls"
|
||||
"github.com/quic-go/quic-go/internal/utils"
|
||||
"github.com/quic-go/quic-go/internal/wire"
|
||||
"github.com/quic-go/quic-go/logging"
|
||||
@@ -89,12 +88,13 @@ func NewCryptoSetupClient(
|
||||
|
||||
tlsConf = tlsConf.Clone()
|
||||
tlsConf.MinVersion = tls.VersionTLS13
|
||||
quicConf := &tls.QUICConfig{TLSConfig: tlsConf}
|
||||
qtls.SetupConfigForClient(quicConf, cs.marshalDataForSessionState, cs.handleDataFromSessionState)
|
||||
cs.tlsConf = tlsConf
|
||||
cs.allow0RTT = enable0RTT
|
||||
|
||||
cs.conn = tls.QUICClient(quicConf)
|
||||
cs.conn = tls.QUICClient(&tls.QUICConfig{
|
||||
TLSConfig: tlsConf,
|
||||
EnableSessionEvents: true,
|
||||
})
|
||||
cs.conn.SetTransportParameters(cs.ourParams.Marshal(protocol.PerspectiveClient))
|
||||
|
||||
return cs
|
||||
@@ -123,9 +123,13 @@ func NewCryptoSetupServer(
|
||||
)
|
||||
cs.allow0RTT = allow0RTT
|
||||
|
||||
tlsConf = qtls.SetupConfigForServer(tlsConf, localAddr, remoteAddr, cs.getDataForSessionTicket, cs.handleSessionTicket)
|
||||
tlsConf = setupConfigForServer(tlsConf, localAddr, remoteAddr)
|
||||
|
||||
cs.tlsConf = tlsConf
|
||||
cs.conn = tls.QUICServer(&tls.QUICConfig{TLSConfig: tlsConf})
|
||||
cs.conn = tls.QUICServer(&tls.QUICConfig{
|
||||
TLSConfig: tlsConf,
|
||||
EnableSessionEvents: true,
|
||||
})
|
||||
return cs
|
||||
}
|
||||
|
||||
@@ -178,11 +182,10 @@ func (h *cryptoSetup) StartHandshake(ctx context.Context) error {
|
||||
}
|
||||
for {
|
||||
ev := h.conn.NextEvent()
|
||||
done, err := h.handleEvent(ev)
|
||||
if err != nil {
|
||||
if err := h.handleEvent(ev); err != nil {
|
||||
return wrapError(err)
|
||||
}
|
||||
if done {
|
||||
if ev.Kind == tls.QUICNoEvent {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -213,53 +216,78 @@ func (h *cryptoSetup) HandleMessage(data []byte, encLevel protocol.EncryptionLev
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) handleMessage(data []byte, encLevel protocol.EncryptionLevel) error {
|
||||
if err := h.conn.HandleData(qtls.ToTLSEncryptionLevel(encLevel), data); err != nil {
|
||||
if err := h.conn.HandleData(encLevel.ToTLSEncryptionLevel(), data); err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
ev := h.conn.NextEvent()
|
||||
done, err := h.handleEvent(ev)
|
||||
if err != nil {
|
||||
if err := h.handleEvent(ev); err != nil {
|
||||
return err
|
||||
}
|
||||
if done {
|
||||
if ev.Kind == tls.QUICNoEvent {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *cryptoSetup) handleEvent(ev tls.QUICEvent) (done bool, err error) {
|
||||
//nolint:exhaustive
|
||||
// Go 1.23 added new 0-RTT events, see https://github.com/quic-go/quic-go/issues/4272.
|
||||
// We will start using these events when dropping support for Go 1.22.
|
||||
func (h *cryptoSetup) handleEvent(ev tls.QUICEvent) (err error) {
|
||||
switch ev.Kind {
|
||||
case tls.QUICNoEvent:
|
||||
return true, nil
|
||||
return nil
|
||||
case tls.QUICSetReadSecret:
|
||||
h.setReadKey(ev.Level, ev.Suite, ev.Data)
|
||||
return false, nil
|
||||
return nil
|
||||
case tls.QUICSetWriteSecret:
|
||||
h.setWriteKey(ev.Level, ev.Suite, ev.Data)
|
||||
return false, nil
|
||||
return nil
|
||||
case tls.QUICTransportParameters:
|
||||
return false, h.handleTransportParameters(ev.Data)
|
||||
return h.handleTransportParameters(ev.Data)
|
||||
case tls.QUICTransportParametersRequired:
|
||||
h.conn.SetTransportParameters(h.ourParams.Marshal(h.perspective))
|
||||
return false, nil
|
||||
return nil
|
||||
case tls.QUICRejectedEarlyData:
|
||||
h.rejected0RTT()
|
||||
return false, nil
|
||||
return nil
|
||||
case tls.QUICWriteData:
|
||||
h.writeRecord(ev.Level, ev.Data)
|
||||
return false, nil
|
||||
return nil
|
||||
case tls.QUICHandshakeDone:
|
||||
h.handshakeComplete()
|
||||
return false, nil
|
||||
return nil
|
||||
case tls.QUICStoreSession:
|
||||
if h.perspective == protocol.PerspectiveServer {
|
||||
panic("cryptoSetup BUG: unexpected QUICStoreSession event for the server")
|
||||
}
|
||||
ev.SessionState.Extra = append(
|
||||
ev.SessionState.Extra,
|
||||
addSessionStateExtraPrefix(h.marshalDataForSessionState(ev.SessionState.EarlyData)),
|
||||
)
|
||||
return h.conn.StoreSession(ev.SessionState)
|
||||
case tls.QUICResumeSession:
|
||||
var allowEarlyData bool
|
||||
switch h.perspective {
|
||||
case protocol.PerspectiveClient:
|
||||
// for clients, this event occurs when a session ticket is selected
|
||||
allowEarlyData = h.handleDataFromSessionState(
|
||||
findSessionStateExtraData(ev.SessionState.Extra),
|
||||
ev.SessionState.EarlyData,
|
||||
)
|
||||
case protocol.PerspectiveServer:
|
||||
// for servers, this event occurs when receiving the client's session ticket
|
||||
allowEarlyData = h.handleSessionTicket(
|
||||
findSessionStateExtraData(ev.SessionState.Extra),
|
||||
ev.SessionState.EarlyData,
|
||||
)
|
||||
}
|
||||
if ev.SessionState.EarlyData {
|
||||
ev.SessionState.EarlyData = allowEarlyData
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
// Unknown events should be ignored.
|
||||
// crypto/tls will ensure that this is safe to do.
|
||||
// See the discussion following https://github.com/golang/go/issues/68124#issuecomment-2187042510 for details.
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,7 +378,10 @@ func (h *cryptoSetup) getDataForSessionTicket() []byte {
|
||||
// Due to limitations in crypto/tls, it's only possible to generate a single session ticket per connection.
|
||||
// It is only valid for the server.
|
||||
func (h *cryptoSetup) GetSessionTicket() ([]byte, error) {
|
||||
if err := h.conn.SendSessionTicket(tls.QUICSessionTicketOptions{EarlyData: h.allow0RTT}); err != nil {
|
||||
if err := h.conn.SendSessionTicket(tls.QUICSessionTicketOptions{
|
||||
EarlyData: h.allow0RTT,
|
||||
Extra: [][]byte{addSessionStateExtraPrefix(h.getDataForSessionTicket())},
|
||||
}); err != nil {
|
||||
// Session tickets might be disabled by tls.Config.SessionTicketsDisabled.
|
||||
// We can't check h.tlsConfig here, since the actual config might have been obtained from
|
||||
// the GetConfigForClient callback.
|
||||
@@ -376,9 +407,9 @@ func (h *cryptoSetup) GetSessionTicket() ([]byte, error) {
|
||||
// It reads parameters from the session ticket and checks whether to accept 0-RTT if the session ticket enabled 0-RTT.
|
||||
// Note that the fact that the session ticket allows 0-RTT doesn't mean that the actual TLS handshake enables 0-RTT:
|
||||
// A client may use a 0-RTT enabled session to resume a TLS session without using 0-RTT.
|
||||
func (h *cryptoSetup) handleSessionTicket(sessionTicketData []byte, using0RTT bool) bool {
|
||||
func (h *cryptoSetup) handleSessionTicket(data []byte, using0RTT bool) (allowEarlyData bool) {
|
||||
var t sessionTicket
|
||||
if err := t.Unmarshal(sessionTicketData, using0RTT); err != nil {
|
||||
if err := t.Unmarshal(data, using0RTT); err != nil {
|
||||
h.logger.Debugf("Unmarshalling session ticket failed: %s", err.Error())
|
||||
return false
|
||||
}
|
||||
@@ -446,7 +477,7 @@ func (h *cryptoSetup) setReadKey(el tls.QUICEncryptionLevel, suiteID uint16, tra
|
||||
}
|
||||
h.events = append(h.events, Event{Kind: EventReceivedReadKeys})
|
||||
if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil {
|
||||
h.tracer.UpdatedKeyFromTLS(qtls.FromTLSEncryptionLevel(el), h.perspective.Opposite())
|
||||
h.tracer.UpdatedKeyFromTLS(protocol.FromTLSEncryptionLevel(el), h.perspective.Opposite())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +528,7 @@ func (h *cryptoSetup) setWriteKey(el tls.QUICEncryptionLevel, suiteID uint16, tr
|
||||
panic("unexpected write encryption level")
|
||||
}
|
||||
if h.tracer != nil && h.tracer.UpdatedKeyFromTLS != nil {
|
||||
h.tracer.UpdatedKeyFromTLS(qtls.FromTLSEncryptionLevel(el), h.perspective)
|
||||
h.tracer.UpdatedKeyFromTLS(protocol.FromTLSEncryptionLevel(el), h.perspective)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user