add a version to marshaled transport parameters in the session ticket

This commit is contained in:
Marten Seemann
2019-12-30 18:21:52 +04:00
parent 00150e1d94
commit 052508e8c2
3 changed files with 65 additions and 21 deletions

View File

@@ -1,6 +1,7 @@
package handshake
import (
"bytes"
"crypto/tls"
"errors"
"fmt"
@@ -448,12 +449,28 @@ func (h *cryptoSetup) marshalPeerParamsForSessionState() []byte {
}
func (h *cryptoSetup) handlePeerParamsFromSessionState(data []byte) {
var tp TransportParameters
if err := tp.Unmarshal(data, protocol.PerspectiveServer); err != nil {
tp, err := h.handlePeerParamsFromSessionStateImpl(data)
if err != nil {
h.logger.Debugf("Restoring of transport parameters from session ticket failed: %s", err.Error())
return
}
h.zeroRTTParameters = &tp
h.zeroRTTParameters = tp
}
func (h *cryptoSetup) handlePeerParamsFromSessionStateImpl(data []byte) (*TransportParameters, error) {
r := bytes.NewReader(data)
version, err := utils.ReadVarInt(r)
if err != nil {
return nil, err
}
if version != transportParameterMarshalingVersion {
return nil, fmt.Errorf("unknown transport parameter marshaling version: %d", version)
}
var tp TransportParameters
if err := tp.Unmarshal(data[len(data)-r.Len():], protocol.PerspectiveServer); err != nil {
return nil, err
}
return &tp, nil
}
// only valid for the server
@@ -469,7 +486,12 @@ func (h *cryptoSetup) maybeSendSessionTicket() {
}
func (h *cryptoSetup) accept0RTT(sessionTicketData []byte) bool {
return h.ourParams.ValidFromSessionTicket(sessionTicketData)
var tp TransportParameters
if err := tp.UnmarshalFromSessionTicket(sessionTicketData); err != nil {
h.logger.Debugf("Unmarshaling transport parameters from session ticket failed: %s", err.Error())
return false
}
return h.ourParams.ValidFor0RTT(&tp)
}
func (h *cryptoSetup) handlePostHandshakeMessage() {

View File

@@ -3,6 +3,7 @@ package handshake
import (
"bytes"
"encoding/binary"
"fmt"
"math"
"math/rand"
"net"
@@ -341,13 +342,21 @@ var _ = Describe("Transport Parameters", func() {
MaxBidiStreamNum: protocol.StreamNum(getRandomValue()),
MaxUniStreamNum: protocol.StreamNum(getRandomValue()),
}
data := params.MarshalForSessionTicket()
Expect(params.ValidFromSessionTicket(data)).To(BeTrue())
Expect(params.ValidFor0RTT(params)).To(BeTrue())
})
It("rejects the parameters if it can't parse them", func() {
params := &TransportParameters{}
Expect(params.ValidFromSessionTicket([]byte("foobar"))).To(BeFalse())
var p TransportParameters
Expect(p.UnmarshalFromSessionTicket([]byte("foobar"))).ToNot(Succeed())
})
It("rejects the parameters if the version changed", func() {
var p TransportParameters
data := p.MarshalForSessionTicket()
b := &bytes.Buffer{}
utils.WriteVarInt(b, transportParameterMarshalingVersion+1)
b.Write(data[utils.VarIntLen(transportParameterMarshalingVersion):])
Expect(p.UnmarshalFromSessionTicket(b.Bytes())).To(MatchError(fmt.Sprintf("unknown transport parameter marshaling version: %d", transportParameterMarshalingVersion+1)))
})
Context("rejects the parameters if they changed", func() {
@@ -370,37 +379,37 @@ var _ = Describe("Transport Parameters", func() {
MaxBidiStreamNum: 5,
MaxUniStreamNum: 6,
}
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeTrue())
Expect(params.ValidFor0RTT(p)).To(BeTrue())
})
It("rejects the parameters if the InitialMaxStreamDataBidiLocal changed", func() {
p.InitialMaxStreamDataBidiLocal = 0
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
Expect(params.ValidFor0RTT(p)).To(BeFalse())
})
It("rejects the parameters if the InitialMaxStreamDataBidiRemote changed", func() {
p.InitialMaxStreamDataBidiRemote = 0
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
Expect(params.ValidFor0RTT(p)).To(BeFalse())
})
It("rejects the parameters if the InitialMaxStreamDataUni changed", func() {
p.InitialMaxStreamDataUni = 0
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
Expect(params.ValidFor0RTT(p)).To(BeFalse())
})
It("rejects the parameters if the InitialMaxData changed", func() {
p.InitialMaxData = 0
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
Expect(params.ValidFor0RTT(p)).To(BeFalse())
})
It("rejects the parameters if the MaxBidiStreamNum changed", func() {
p.MaxBidiStreamNum = 0
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
Expect(params.ValidFor0RTT(p)).To(BeFalse())
})
It("rejects the parameters if the MaxUniStreamNum changed", func() {
p.MaxUniStreamNum = 0
Expect(params.ValidFromSessionTicket(p.Marshal())).To(BeFalse())
Expect(params.ValidFor0RTT(p)).To(BeFalse())
})
})
})

View File

@@ -17,6 +17,8 @@ import (
"github.com/lucas-clemente/quic-go/internal/utils"
)
const transportParameterMarshalingVersion = 1
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}
@@ -379,6 +381,8 @@ func (p *TransportParameters) marshalVarintParam(b *bytes.Buffer, id transportPa
// For convenience, we use the same format that we also use for sending the transport parameters.
func (p *TransportParameters) MarshalForSessionTicket() []byte {
b := &bytes.Buffer{}
utils.WriteVarInt(b, transportParameterMarshalingVersion)
startLen := b.Len()
b.Write([]byte{0, 0}) // length. Will be replaced later
// initial_max_stream_data_bidi_local
@@ -395,17 +399,26 @@ func (p *TransportParameters) MarshalForSessionTicket() []byte {
p.marshalVarintParam(b, initialMaxStreamsUniParameterID, uint64(p.MaxUniStreamNum))
data := b.Bytes()
binary.BigEndian.PutUint16(data[:2], uint16(b.Len()-2))
binary.BigEndian.PutUint16(data[startLen:startLen+2], uint16(b.Len()-2-startLen))
return data
}
// ValidFromSessionTicket checks if the transport parameters match those saved in the session ticket.
func (p *TransportParameters) ValidFromSessionTicket(data []byte) bool {
tp := &TransportParameters{}
if err := tp.Unmarshal(data, protocol.PerspectiveServer); err != nil {
return false
// UnmarshalFromSessionTicket unmarshals transport parameters from a session ticket.
func (p *TransportParameters) UnmarshalFromSessionTicket(data []byte) error {
r := bytes.NewReader(data)
version, err := utils.ReadVarInt(r)
if err != nil {
return err
}
if version != transportParameterMarshalingVersion {
return fmt.Errorf("unknown transport parameter marshaling version: %d", version)
}
tp := &TransportParameters{}
return tp.Unmarshal(data[len(data)-r.Len():], protocol.PerspectiveServer)
}
// ValidFor0RTT checks if the transport parameters match those saved in the session ticket.
func (p *TransportParameters) ValidFor0RTT(tp *TransportParameters) bool {
return p.InitialMaxStreamDataBidiLocal == tp.InitialMaxStreamDataBidiLocal &&
p.InitialMaxStreamDataBidiRemote == tp.InitialMaxStreamDataBidiRemote &&
p.InitialMaxStreamDataUni == tp.InitialMaxStreamDataUni &&