update the ChaCha implementation, remove 0xffffffff workaround

This commit is contained in:
Marten Seemann
2020-04-24 09:58:55 +07:00
parent 02d869a28f
commit 97e191f3b4
4 changed files with 22 additions and 19 deletions

View File

@@ -1,6 +1,7 @@
package handshake
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
@@ -79,6 +80,24 @@ var _ = Describe("Long Header AEAD", func() {
Expect(lastFourBitsDifferent).To(BeNumerically(">", 75))
})
It("encrypts and encrypts the header, for a 0xfff..fff sample", func() {
sealer, opener := getSealerAndOpener()
var lastFourBitsDifferent int
for i := 0; i < 100; i++ {
sample := bytes.Repeat([]byte{0xff}, 16)
header := []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}
sealer.EncryptHeader(sample, &header[0], header[9:13])
if header[0]&0xf != 0xb5&0xf {
lastFourBitsDifferent++
}
Expect(header[0] & 0xf0).To(Equal(byte(0xb5 & 0xf0)))
Expect(header[1:9]).To(Equal([]byte{1, 2, 3, 4, 5, 6, 7, 8}))
Expect(header[9:13]).ToNot(Equal([]byte{0xde, 0xad, 0xbe, 0xef}))
opener.DecryptHeader(sample, &header[0], header[9:13])
Expect(header).To(Equal([]byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}))
}
})
It("fails to decrypt the header when using a different sample", func() {
sealer, opener := getSealerAndOpener()
header := []byte{0xb5, 1, 2, 3, 4, 5, 6, 7, 8, 0xde, 0xad, 0xbe, 0xef}

View File

@@ -3,7 +3,6 @@ package handshake
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"fmt"
@@ -93,27 +92,10 @@ func newChaChaHeaderProtector(suite *qtls.CipherSuiteTLS13, trafficSecret []byte
}
func (p *chachaHeaderProtector) DecryptHeader(sample []byte, firstByte *byte, hdrBytes []byte) {
// Workaround for https://github.com/lucas-clemente/quic-go/issues/2326.
// The ChaCha20 implementation panics when the nonce is 0xffffffff.
// Don't apply header protection in that case.
// The packet will end up undecryptable, but it only applies to 1 in 2^32 packets.
if sample[0] == 0xff && sample[1] == 0xff && sample[2] == 0xff && sample[3] == 0xff {
return
}
p.apply(sample, firstByte, hdrBytes)
}
func (p *chachaHeaderProtector) EncryptHeader(sample []byte, firstByte *byte, hdrBytes []byte) {
// Workaround for https://github.com/lucas-clemente/quic-go/issues/2326.
// The ChaCha20 implementation panics when the nonce is 0xffffffff.
// Apply header protection with a random mask, in order to not leak any data.
// The packet will end up undecryptable, but this only applies to 1 in 2^32 packets.
if sample[0] == 0xff && sample[1] == 0xff && sample[2] == 0xff && sample[3] == 0xff {
if _, err := rand.Read(p.mask[:]); err != nil {
panic("couldn't get rand for ChaCha20 bug workaround")
}
p.applyMask(firstByte, hdrBytes)
}
p.apply(sample, firstByte, hdrBytes)
}