diff --git a/go.mod b/go.mod index 78fb85ae..4de19ee0 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/golang/protobuf v1.3.0 github.com/marten-seemann/chacha20 v0.2.0 github.com/marten-seemann/qpack v0.1.0 - github.com/marten-seemann/qtls v0.4.1 + github.com/marten-seemann/qtls v0.5.0 github.com/onsi/ginkgo v1.7.0 github.com/onsi/gomega v1.4.3 golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 diff --git a/go.sum b/go.sum index a0157b15..eea70312 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,8 @@ github.com/marten-seemann/chacha20 v0.2.0 h1:f40vqzzx+3GdOmzQoItkLX5WLvHgPgyYqFF github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= github.com/marten-seemann/qpack v0.1.0 h1:/0M7lkda/6mus9B8u34Asqm8ZhHAAt9Ho0vniNuVSVg= github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= -github.com/marten-seemann/qtls v0.4.1 h1:YlT8QP3WCCvvok7MGEZkMldXbyqgr8oFg5/n8Gtbkks= -github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= +github.com/marten-seemann/qtls v0.5.0 h1:psje4bHl6372lku0pTIt2PZ9HcVJyBIuW9pZn+u2vhY= +github.com/marten-seemann/qtls v0.5.0/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -34,6 +34,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/internal/handshake/crypto_setup.go b/internal/handshake/crypto_setup.go index 9c28683e..48dc8f34 100644 --- a/internal/handshake/crypto_setup.go +++ b/internal/handshake/crypto_setup.go @@ -66,6 +66,7 @@ type cryptoSetup struct { messageChan chan []byte + ourParams *TransportParameters paramsChan <-chan []byte runner handshakeRunner @@ -124,6 +125,7 @@ func NewCryptoSetupClient( tp *TransportParameters, runner handshakeRunner, tlsConf *tls.Config, + enable0RTT bool, rttStats *congestion.RTTStats, logger utils.Logger, ) (CryptoSetup, <-chan struct{} /* ClientHello written */) { @@ -135,6 +137,7 @@ func NewCryptoSetupClient( tp, runner, tlsConf, + enable0RTT, rttStats, logger, protocol.PerspectiveClient, @@ -153,6 +156,7 @@ func NewCryptoSetupServer( tp *TransportParameters, runner handshakeRunner, tlsConf *tls.Config, + enable0RTT bool, rttStats *congestion.RTTStats, logger utils.Logger, ) CryptoSetup { @@ -164,6 +168,7 @@ func NewCryptoSetupServer( tp, runner, tlsConf, + enable0RTT, rttStats, logger, protocol.PerspectiveServer, @@ -180,6 +185,7 @@ func newCryptoSetup( tp *TransportParameters, runner handshakeRunner, tlsConf *tls.Config, + enable0RTT bool, rttStats *congestion.RTTStats, logger utils.Logger, perspective protocol.Perspective, @@ -196,6 +202,7 @@ func newCryptoSetup( readEncLevel: protocol.EncryptionInitial, writeEncLevel: protocol.EncryptionInitial, runner: runner, + ourParams: tp, paramsChan: extHandler.TransportParameters(), logger: logger, perspective: perspective, @@ -208,7 +215,7 @@ func newCryptoSetup( writeRecord: make(chan struct{}, 1), closeChan: make(chan struct{}), } - qtlsConf := tlsConfigToQtlsConfig(tlsConf, cs, extHandler) + qtlsConf := tlsConfigToQtlsConfig(tlsConf, cs, extHandler, cs.accept0RTT, enable0RTT) cs.tlsConf = qtlsConf return cs, cs.clientHelloWrittenChan } @@ -423,7 +430,7 @@ func (h *cryptoSetup) handleMessageForClient(msgType messageType) bool { // only valid for the server func (h *cryptoSetup) maybeSendSessionTicket() { - ticket, err := h.conn.GetSessionTicket() + ticket, err := h.conn.GetSessionTicket(h.ourParams.MarshalForSessionTicket()) if err != nil { h.onError(alertInternalError, err.Error()) return @@ -433,6 +440,10 @@ func (h *cryptoSetup) maybeSendSessionTicket() { } } +func (h *cryptoSetup) accept0RTT(sessionTicketData []byte) bool { + return h.ourParams.ValidFromSessionTicket(sessionTicketData) +} + func (h *cryptoSetup) handlePostHandshakeMessage() { // make sure the handshake has already completed <-h.handshakeDone diff --git a/internal/handshake/crypto_setup_test.go b/internal/handshake/crypto_setup_test.go index a870ac2b..20fa7385 100644 --- a/internal/handshake/crypto_setup_test.go +++ b/internal/handshake/crypto_setup_test.go @@ -95,6 +95,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, NewMockHandshakeRunner(mockCtrl), tlsConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -126,6 +127,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, runner, testdata.GetTLSConfig(), + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -163,6 +165,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, runner, testdata.GetTLSConfig(), + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -203,6 +206,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, runner, serverConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -236,6 +240,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, NewMockHandshakeRunner(mockCtrl), serverConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -324,6 +329,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, cRunner, clientConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("client"), ) @@ -345,6 +351,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{StatelessResetToken: &token}, sRunner, serverConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -397,6 +404,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, runner, &tls.Config{InsecureSkipVerify: true}, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("client"), ) @@ -437,6 +445,7 @@ var _ = Describe("Crypto Setup TLS", func() { cTransportParameters, cRunner, clientConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("client"), ) @@ -459,6 +468,7 @@ var _ = Describe("Crypto Setup TLS", func() { sTransportParameters, sRunner, serverConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -495,6 +505,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, cRunner, clientConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("client"), ) @@ -512,6 +523,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, sRunner, serverConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) @@ -550,6 +562,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, cRunner, clientConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("client"), ) @@ -567,6 +580,7 @@ var _ = Describe("Crypto Setup TLS", func() { &TransportParameters{}, sRunner, serverConf, + false, &congestion.RTTStats{}, utils.DefaultLogger.WithPrefix("server"), ) diff --git a/internal/handshake/qtls.go b/internal/handshake/qtls.go index 67ed90a6..9b8ec31f 100644 --- a/internal/handshake/qtls.go +++ b/internal/handshake/qtls.go @@ -70,6 +70,8 @@ func tlsConfigToQtlsConfig( c *tls.Config, recordLayer qtls.RecordLayer, extHandler tlsExtensionHandler, + accept0RTT func([]byte) bool, + enable0RTT bool, ) *qtls.Config { if c == nil { c = &tls.Config{} @@ -96,14 +98,14 @@ func tlsConfigToQtlsConfig( if tlsConf == nil { return nil, nil } - return tlsConfigToQtlsConfig(tlsConf, recordLayer, extHandler), nil + return tlsConfigToQtlsConfig(tlsConf, recordLayer, extHandler, accept0RTT, enable0RTT), nil } } var csc qtls.ClientSessionCache if c.ClientSessionCache != nil { csc = &clientSessionCache{c.ClientSessionCache} } - return &qtls.Config{ + conf := &qtls.Config{ Rand: c.Rand, Time: c.Time, Certificates: c.Certificates, @@ -133,7 +135,13 @@ func tlsConfigToQtlsConfig( AlternativeRecordLayer: recordLayer, GetExtensions: extHandler.GetExtensions, ReceivedExtensions: extHandler.ReceivedExtensions, + Accept0RTT: accept0RTT, } + if enable0RTT { + conf.Enable0RTT = true + conf.MaxEarlyData = 0xffffffff + } + return conf } func cipherSuiteName(id uint16) string { diff --git a/internal/handshake/qtls_test.go b/internal/handshake/qtls_test.go index 481b407d..55ea1acf 100644 --- a/internal/handshake/qtls_test.go +++ b/internal/handshake/qtls_test.go @@ -28,19 +28,19 @@ func (*mockExtensionHandler) TransportParameters() <-chan []byte { panic("not im var _ = Describe("qtls.Config generation", func() { It("sets MinVersion and MaxVersion", func() { tlsConf := &tls.Config{MinVersion: tls.VersionTLS11, MaxVersion: tls.VersionTLS12} - qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}, nil, false) Expect(qtlsConf.MinVersion).To(BeEquivalentTo(tls.VersionTLS13)) Expect(qtlsConf.MaxVersion).To(BeEquivalentTo(tls.VersionTLS13)) }) It("works when called with a nil config", func() { - qtlsConf := tlsConfigToQtlsConfig(nil, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(nil, nil, &mockExtensionHandler{}, nil, false) Expect(qtlsConf).ToNot(BeNil()) }) It("sets the setter and getter function for TLS extensions", func() { extHandler := &mockExtensionHandler{} - qtlsConf := tlsConfigToQtlsConfig(&tls.Config{}, nil, extHandler) + qtlsConf := tlsConfigToQtlsConfig(&tls.Config{}, nil, extHandler, nil, false) Expect(extHandler.get).To(BeFalse()) qtlsConf.GetExtensions(10) Expect(extHandler.get).To(BeTrue()) @@ -49,17 +49,33 @@ var _ = Describe("qtls.Config generation", func() { Expect(extHandler.received).To(BeTrue()) }) + It("sets the Accept0RTT callback", func() { + accept0RTT := func([]byte) bool { return true } + qtlsConf := tlsConfigToQtlsConfig(nil, nil, &mockExtensionHandler{}, accept0RTT, false) + Expect(qtlsConf.Accept0RTT).ToNot(BeNil()) + Expect(qtlsConf.Accept0RTT(nil)).To(BeTrue()) + }) + + It("enables 0-RTT", func() { + qtlsConf := tlsConfigToQtlsConfig(nil, nil, &mockExtensionHandler{}, nil, false) + Expect(qtlsConf.Enable0RTT).To(BeFalse()) + Expect(qtlsConf.MaxEarlyData).To(BeZero()) + qtlsConf = tlsConfigToQtlsConfig(nil, nil, &mockExtensionHandler{}, nil, true) + Expect(qtlsConf.Enable0RTT).To(BeTrue()) + Expect(qtlsConf.MaxEarlyData).To(Equal(uint32(0xffffffff))) + }) + It("initializes such that the session ticket key remains constant", func() { tlsConf := &tls.Config{} - qtlsConf1 := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}) - qtlsConf2 := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}) + qtlsConf1 := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}, nil, false) + qtlsConf2 := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}, nil, false) Expect(qtlsConf1.SessionTicketKey).ToNot(BeZero()) // should now contain a random value Expect(qtlsConf1.SessionTicketKey).To(Equal(qtlsConf2.SessionTicketKey)) }) Context("GetConfigForClient callback", func() { It("doesn't set it if absent", func() { - qtlsConf := tlsConfigToQtlsConfig(&tls.Config{}, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(&tls.Config{}, nil, &mockExtensionHandler{}, nil, false) Expect(qtlsConf.GetConfigForClient).To(BeNil()) }) @@ -70,7 +86,7 @@ var _ = Describe("qtls.Config generation", func() { }, } extHandler := &mockExtensionHandler{} - qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, extHandler) + qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, extHandler, nil, false) Expect(qtlsConf.GetConfigForClient).ToNot(BeNil()) confForClient, err := qtlsConf.GetConfigForClient(nil) Expect(err).ToNot(HaveOccurred()) @@ -90,7 +106,7 @@ var _ = Describe("qtls.Config generation", func() { return nil, testErr }, } - qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}, nil, false) _, err := qtlsConf.GetConfigForClient(nil) Expect(err).To(MatchError(testErr)) }) @@ -101,21 +117,21 @@ var _ = Describe("qtls.Config generation", func() { return nil, nil }, } - qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}, nil, false) Expect(qtlsConf.GetConfigForClient(nil)).To(BeNil()) }) }) Context("ClientSessionCache", func() { It("doesn't set if absent", func() { - qtlsConf := tlsConfigToQtlsConfig(&tls.Config{}, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(&tls.Config{}, nil, &mockExtensionHandler{}, nil, false) Expect(qtlsConf.ClientSessionCache).To(BeNil()) }) It("sets it, and puts and gets session states", func() { csc := NewMockClientSessionCache(mockCtrl) tlsConf := &tls.Config{ClientSessionCache: csc} - qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}, nil, false) Expect(qtlsConf.ClientSessionCache).ToNot(BeNil()) // put something csc.EXPECT().Put("foobar", gomock.Any()) @@ -129,7 +145,7 @@ var _ = Describe("qtls.Config generation", func() { It("puts a nil session state", func() { csc := NewMockClientSessionCache(mockCtrl) tlsConf := &tls.Config{ClientSessionCache: csc} - qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}) + qtlsConf := tlsConfigToQtlsConfig(tlsConf, nil, &mockExtensionHandler{}, nil, false) // put something csc.EXPECT().Put("foobar", nil) qtlsConf.ClientSessionCache.Put("foobar", nil) diff --git a/session.go b/session.go index 6756eb73..fd3cf3d5 100644 --- a/session.go +++ b/session.go @@ -274,6 +274,7 @@ var newSession = func( }, }, tlsConf, + true, // TODO: make 0-RTT support configurable s.rttStats, logger, ) @@ -370,6 +371,7 @@ var newClientSession = func( onHandshakeComplete: func() { close(s.handshakeCompleteChan) }, }, tlsConf, + true, // TODO: make 0-RTT support configurable s.rttStats, logger, )