validate length of crypto message

refs #123
This commit is contained in:
Lucas Clemente
2016-05-27 23:25:51 +02:00
parent 7c23ba7b07
commit a4773eb5ff
3 changed files with 37 additions and 2 deletions

View File

@@ -7,6 +7,8 @@ import (
"io"
"sort"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/utils"
)
@@ -22,6 +24,10 @@ func ParseHandshakeMessage(r utils.ReadStream) (Tag, map[Tag][]byte, error) {
return 0, nil, err
}
if nPairs > protocol.CryptoMaxParams {
return 0, nil, qerr.CryptoTooManyEntries
}
index := make([]byte, nPairs*8)
_, err = io.ReadFull(r, index)
if err != nil {
@@ -32,11 +38,15 @@ func ParseHandshakeMessage(r utils.ReadStream) (Tag, map[Tag][]byte, error) {
dataStart := 0
for indexPos := 0; indexPos < int(nPairs)*8; indexPos += 8 {
// We know from the check above that data is long enough for the index
tag := Tag(binary.LittleEndian.Uint32(index[indexPos : indexPos+4]))
dataEnd := int(binary.LittleEndian.Uint32(index[indexPos+4 : indexPos+8]))
data := make([]byte, dataEnd-dataStart)
dataLen := dataEnd - dataStart
if dataLen > protocol.CryptoParameterMaxLength {
return 0, nil, qerr.Error(qerr.CryptoInvalidValueLength, "value too long")
}
data := make([]byte, dataLen)
_, err = io.ReadFull(r, data)
if err != nil {
return 0, nil, err

View File

@@ -3,6 +3,7 @@ package handshake
import (
"bytes"
"github.com/lucas-clemente/quic-go/qerr"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -15,6 +16,23 @@ var _ = Describe("Handshake Message", func() {
Expect(tag).To(Equal(TagCHLO))
Expect(msg).To(Equal(sampleCHLOMap))
})
It("rejects large numbers of pairs", func() {
r := bytes.NewReader([]byte("CHLO\xff\xff\xff\xff"))
_, _, err := ParseHandshakeMessage(r)
Expect(err).To(MatchError(qerr.CryptoTooManyEntries))
})
It("rejects too long values", func() {
r := bytes.NewReader([]byte{
'C', 'H', 'L', 'O',
1, 0, 0, 0,
0, 0, 0, 0,
0xff, 0xff, 0xff, 0xff,
})
_, _, err := ParseHandshakeMessage(r)
Expect(err).To(MatchError(qerr.Error(qerr.CryptoInvalidValueLength, "value too long")))
})
})
Context("when writing", func() {

View File

@@ -58,3 +58,10 @@ const STKExpiryTimeSec = 24 * 60 * 60
// TODO: find a reasonable value here
// TODO: decrease this value after dropping support for QUIC 33 and earlier
const MaxTrackedSentPackets uint32 = 2000
// CryptoMaxParams is the upper limit for the number of parameters in a crypto message.
// Value taken from Chrome.
const CryptoMaxParams = 128
// CryptoParameterMaxLength is the upper limit for the length of a parameter in a crypto message.
const CryptoParameterMaxLength = ClientHelloMinimumSize