forked from quic-go/quic-go
@@ -41,7 +41,7 @@ func compressChain(chain [][]byte, pCommonSetHashes, pCachedHashes []byte) ([]by
|
||||
|
||||
chainHashes := make([]uint64, len(chain))
|
||||
for i := range chain {
|
||||
chainHashes[i] = hashCert(chain[i])
|
||||
chainHashes[i] = HashCert(chain[i])
|
||||
}
|
||||
|
||||
entries := buildEntries(chain, chainHashes, cachedHashes, setHashes)
|
||||
@@ -149,7 +149,8 @@ func splitHashes(hashes []byte) ([]uint64, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func hashCert(cert []byte) uint64 {
|
||||
// HashCert calculates the FNV1a hash of a certificate
|
||||
func HashCert(cert []byte) uint64 {
|
||||
h := fnv.New64a()
|
||||
h.Write(cert)
|
||||
return h.Sum64()
|
||||
|
||||
@@ -121,7 +121,13 @@ func (h *CryptoSetup) handleMessage(chloData []byte, cryptoData map[Tag][]byte)
|
||||
|
||||
var reply []byte
|
||||
var err error
|
||||
if !h.isInchoateCHLO(cryptoData) {
|
||||
|
||||
certUncompressed, err := h.scfg.signer.GetLeafCert(sni)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !h.isInchoateCHLO(cryptoData, certUncompressed) {
|
||||
// We have a CHLO with a proper server config ID, do a 0-RTT handshake
|
||||
reply, err = h.handleCHLO(sni, chloData, cryptoData)
|
||||
if err != nil {
|
||||
@@ -185,12 +191,20 @@ func (h *CryptoSetup) Seal(dst, src []byte, packetNumber protocol.PacketNumber,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *CryptoSetup) isInchoateCHLO(cryptoData map[Tag][]byte) bool {
|
||||
func (h *CryptoSetup) isInchoateCHLO(cryptoData map[Tag][]byte, cert []byte) bool {
|
||||
if _, ok := cryptoData[TagPUBS]; !ok {
|
||||
return true
|
||||
}
|
||||
scid, ok := cryptoData[TagSCID]
|
||||
if !ok || !bytes.Equal(h.scfg.ID, scid) {
|
||||
return true
|
||||
}
|
||||
if _, ok := cryptoData[TagPUBS]; !ok {
|
||||
xlctTag, ok := cryptoData[TagXLCT]
|
||||
if !ok || len(xlctTag) != 8 {
|
||||
return true
|
||||
}
|
||||
xlct := binary.LittleEndian.Uint64(xlctTag)
|
||||
if crypto.HashCert(cert) != xlct {
|
||||
return true
|
||||
}
|
||||
if err := h.scfg.stkSource.VerifyToken(h.ip, cryptoData[TagSTK]); err != nil {
|
||||
|
||||
@@ -204,6 +204,17 @@ var _ = Describe("Crypto setup", func() {
|
||||
})
|
||||
|
||||
Context("when responding to client messages", func() {
|
||||
var cert []byte
|
||||
var xlct []byte
|
||||
|
||||
BeforeEach(func() {
|
||||
xlct = make([]byte, 8)
|
||||
var err error
|
||||
cert, err = cs.scfg.signer.GetLeafCert("")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
binary.LittleEndian.PutUint64(xlct, crypto.HashCert(cert))
|
||||
})
|
||||
|
||||
It("generates REJ messages", func() {
|
||||
response, err := cs.handleInchoateCHLO("", bytes.Repeat([]byte{'a'}, protocol.ClientHelloMinimumSize), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@@ -265,6 +276,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagSNI: []byte("quic.clemente.io"),
|
||||
TagNONC: nonce32,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagAEAD: aead,
|
||||
TagKEXS: kexs,
|
||||
TagPUBS: nil,
|
||||
@@ -283,6 +295,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagSNI: []byte("quic.clemente.io"),
|
||||
TagNONC: []byte("too short client nonce"),
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagPUBS: nil,
|
||||
TagVER: versionTag,
|
||||
})
|
||||
@@ -297,6 +310,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagSNI: []byte("quic.clemente.io"),
|
||||
TagNONC: nonce,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagPUBS: nil,
|
||||
TagVER: versionTag,
|
||||
})
|
||||
@@ -310,6 +324,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagSNI: []byte("quic.clemente.io"),
|
||||
TagNONC: nonce32,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagAEAD: aead,
|
||||
TagKEXS: kexs,
|
||||
TagPUBS: nil,
|
||||
@@ -323,18 +338,50 @@ var _ = Describe("Crypto setup", func() {
|
||||
})
|
||||
|
||||
It("recognizes inchoate CHLOs missing SCID", func() {
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{TagPUBS: nil, TagSTK: validSTK})).To(BeTrue())
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{
|
||||
TagPUBS: nil,
|
||||
TagSTK: validSTK,
|
||||
}, cert)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("recognizes inchoate CHLOs missing PUBS", func() {
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{TagSCID: scfg.ID, TagSTK: validSTK})).To(BeTrue())
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{
|
||||
TagSCID: scfg.ID,
|
||||
TagSTK: validSTK,
|
||||
}, cert)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("recognizes inchoate CHLOs with invalid tokens", func() {
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{
|
||||
TagSCID: scfg.ID,
|
||||
TagPUBS: nil,
|
||||
})).To(BeTrue())
|
||||
}, cert)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("recognizes inchoate CHLOs with missing XLCT", func() {
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{
|
||||
TagSCID: scfg.ID,
|
||||
TagPUBS: nil,
|
||||
TagSTK: validSTK,
|
||||
}, cert)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("recognizes inchoate CHLOs with wrong length XLCT", func() {
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{
|
||||
TagSCID: scfg.ID,
|
||||
TagPUBS: nil,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct[1:],
|
||||
}, cert)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("recognizes inchoate CHLOs with wrong XLCT", func() {
|
||||
Expect(cs.isInchoateCHLO(map[Tag][]byte{
|
||||
TagSCID: scfg.ID,
|
||||
TagPUBS: nil,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: bytes.Repeat([]byte{'f'}, 8),
|
||||
}, cert)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("recognizes proper CHLOs", func() {
|
||||
@@ -342,7 +389,8 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagSCID: scfg.ID,
|
||||
TagPUBS: nil,
|
||||
TagSTK: validSTK,
|
||||
})).To(BeFalse())
|
||||
TagXLCT: xlct,
|
||||
}, cert)).To(BeFalse())
|
||||
})
|
||||
|
||||
It("errors on too short inchoate CHLOs", func() {
|
||||
@@ -408,6 +456,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagPUBS: []byte("pubs"),
|
||||
TagNONC: nonce32,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagKEXS: kexs,
|
||||
TagAEAD: aead,
|
||||
TagVER: b,
|
||||
@@ -423,6 +472,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagPUBS: []byte("pubs"),
|
||||
TagNONC: nonce32,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagKEXS: kexs,
|
||||
TagVER: versionTag,
|
||||
})
|
||||
@@ -437,6 +487,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagPUBS: []byte("pubs"),
|
||||
TagNONC: nonce32,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagAEAD: []byte("wrong"),
|
||||
TagKEXS: kexs,
|
||||
TagVER: versionTag,
|
||||
@@ -452,6 +503,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagPUBS: []byte("pubs"),
|
||||
TagNONC: nonce32,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagAEAD: aead,
|
||||
TagVER: versionTag,
|
||||
})
|
||||
@@ -466,6 +518,7 @@ var _ = Describe("Crypto setup", func() {
|
||||
TagPUBS: []byte("pubs"),
|
||||
TagNONC: nonce32,
|
||||
TagSTK: validSTK,
|
||||
TagXLCT: xlct,
|
||||
TagAEAD: aead,
|
||||
TagKEXS: []byte("wrong"),
|
||||
TagVER: versionTag,
|
||||
|
||||
@@ -59,6 +59,8 @@ const (
|
||||
|
||||
// TagNONC is the client nonce
|
||||
TagNONC Tag = 'N' + 'O'<<8 + 'N'<<16 + 'C'<<24
|
||||
// TagXLCT is the expected leaf certificate
|
||||
TagXLCT Tag = 'X' + 'L'<<8 + 'C'<<16 + 'T'<<24
|
||||
|
||||
// TagSCID is the server config ID
|
||||
TagSCID Tag = 'S' + 'C'<<8 + 'I'<<16 + 'D'<<24
|
||||
|
||||
Reference in New Issue
Block a user