Merge pull request #612 from Eichhoernchen/master

Added parsing of PUBS tag and filtering according to KEXS
This commit is contained in:
Lucas Clemente
2017-05-12 15:32:08 +02:00
committed by GitHub
2 changed files with 60 additions and 9 deletions

View File

@@ -57,7 +57,6 @@ func (s *serverConfigClient) parseValues(tagMap map[Tag][]byte) error {
s.ID = scfgID
// KEXS
// TODO: allow for P256 in the list
// TODO: setup Key Exchange
kexs, ok := tagMap[TagKEXS]
if !ok {
@@ -66,8 +65,16 @@ func (s *serverConfigClient) parseValues(tagMap map[Tag][]byte) error {
if len(kexs)%4 != 0 {
return qerr.Error(qerr.CryptoInvalidValueLength, "KEXS")
}
if !bytes.Equal(kexs, []byte("C255")) {
return qerr.Error(qerr.CryptoNoSupport, "KEXS")
c255Foundat := -1
for i := 0; i < len(kexs)/4; i++ {
if bytes.Equal(kexs[4*i:4*i+4], []byte("C255")) {
c255Foundat = i
break
}
}
if c255Foundat < 0 {
return qerr.Error(qerr.CryptoNoSupport, "KEXS: Could not find C255, other key exchanges are not supported")
}
// AEAD
@@ -90,12 +97,37 @@ func (s *serverConfigClient) parseValues(tagMap map[Tag][]byte) error {
}
// PUBS
// TODO: save this value
pubs, ok := tagMap[TagPUBS]
if !ok {
return qerr.Error(qerr.CryptoMessageParameterNotFound, "PUBS")
}
if len(pubs) != 35 {
var pubs_kexs []struct{Length uint32; Value []byte}
var last_len uint32
for i := 0; i < len(pubs)-3; i += int(last_len)+3 {
// the PUBS value is always prepended by 3 byte little endian length field
err := binary.Read(bytes.NewReader([]byte{pubs[i], pubs[i+1], pubs[i+2], 0x00}), binary.LittleEndian, &last_len);
if err != nil {
return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS not decodable")
}
if last_len == 0 {
return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS")
}
if i+3+int(last_len) > len(pubs) {
return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS")
}
pubs_kexs = append(pubs_kexs, struct{Length uint32; Value []byte}{last_len, pubs[i+3:i+3+int(last_len)]})
}
if c255Foundat >= len(pubs_kexs) {
return qerr.Error(qerr.CryptoMessageParameterNotFound, "KEXS not in PUBS")
}
if pubs_kexs[c255Foundat].Length != 32 {
return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS")
}
@@ -105,8 +137,8 @@ func (s *serverConfigClient) parseValues(tagMap map[Tag][]byte) error {
return err
}
// the PUBS value is always prepended by []byte{0x20, 0x00, 0x00}
s.sharedSecret, err = s.kex.CalculateSharedKey(pubs[3:])
s.sharedSecret, err = s.kex.CalculateSharedKey(pubs_kexs[c255Foundat].Value)
if err != nil {
return err
}

View File

@@ -15,7 +15,7 @@ func getDefaultServerConfigClient() map[Tag][]byte {
TagSCID: bytes.Repeat([]byte{'F'}, 16),
TagKEXS: []byte("C255"),
TagAEAD: []byte("AESG"),
TagPUBS: bytes.Repeat([]byte{0}, 35),
TagPUBS: append([]byte{0x20, 0x00, 0x00}, bytes.Repeat([]byte{0}, 32)...),
TagOBIT: bytes.Repeat([]byte{0}, 8),
TagEXPY: []byte{0x0, 0x6c, 0x57, 0x78, 0, 0, 0, 0}, // 2033-12-24
}
@@ -124,7 +124,7 @@ var _ = Describe("Server Config", func() {
It("rejects KEXS values other than C255", func() {
tagMap[TagKEXS] = []byte("P256")
err := scfg.parseValues(tagMap)
Expect(err).To(MatchError("CryptoNoSupport: KEXS"))
Expect(err).To(MatchError("CryptoNoSupport: KEXS: Could not find C255, other key exchanges are not supported"))
})
It("errors if the KEXS is missing", func() {
@@ -184,6 +184,25 @@ var _ = Describe("Server Config", func() {
Expect(err).To(MatchError("CryptoInvalidValueLength: PUBS"))
})
It("rejects PUBS values that have a zero length", func() {
tagMap[TagPUBS] = bytes.Repeat([]byte{0}, 100) // completely wrong length
err := scfg.parseValues(tagMap)
Expect(err).To(MatchError("CryptoInvalidValueLength: PUBS"))
})
It("ensure that C255 Pubs must not be at the first index", func() {
serverKex, err := crypto.NewCurve25519KEX()
Expect(err).ToNot(HaveOccurred())
tagMap[TagKEXS] = []byte("P256C255") // have another KEXS before C255
// 3 byte len + 1 byte empty + C255
tagMap[TagPUBS] = append([]byte{0x01, 0x00, 0x00, 0x00}, append([]byte{0x20, 0x00, 0x00}, serverKex.PublicKey()...)...)
err = scfg.parseValues(tagMap)
Expect(err).ToNot(HaveOccurred())
sharedSecret, err := serverKex.CalculateSharedKey(scfg.kex.PublicKey())
Expect(err).ToNot(HaveOccurred())
Expect(scfg.sharedSecret).To(Equal(sharedSecret))
})
It("errors if the PUBS is missing", func() {
delete(tagMap, TagPUBS)
err := scfg.parseValues(tagMap)