handshake: optimize AEAD handling for long header sealers and openers (#4323)

This commit is contained in:
Marten Seemann 2024-03-03 23:03:10 +10:30 committed by GitHub
parent f856163f1e
commit 71f5ae5ecb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 23 additions and 26 deletions

View file

@ -1,13 +1,12 @@
package handshake package handshake
import ( import (
"crypto/cipher"
"encoding/binary" "encoding/binary"
"github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/protocol"
) )
func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.Version) cipher.AEAD { func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.Version) *xorNonceAEAD {
keyLabel := hkdfLabelKeyV1 keyLabel := hkdfLabelKeyV1
ivLabel := hkdfLabelIVV1 ivLabel := hkdfLabelIVV1
if v == protocol.Version2 { if v == protocol.Version2 {
@ -20,28 +19,26 @@ func createAEAD(suite *cipherSuite, trafficSecret []byte, v protocol.Version) ci
} }
type longHeaderSealer struct { type longHeaderSealer struct {
aead cipher.AEAD aead *xorNonceAEAD
headerProtector headerProtector headerProtector headerProtector
nonceBuf [8]byte
// use a single slice to avoid allocations
nonceBuf []byte
} }
var _ LongHeaderSealer = &longHeaderSealer{} var _ LongHeaderSealer = &longHeaderSealer{}
func newLongHeaderSealer(aead cipher.AEAD, headerProtector headerProtector) LongHeaderSealer { func newLongHeaderSealer(aead *xorNonceAEAD, headerProtector headerProtector) LongHeaderSealer {
if aead.NonceSize() != 8 {
panic("unexpected nonce size")
}
return &longHeaderSealer{ return &longHeaderSealer{
aead: aead, aead: aead,
headerProtector: headerProtector, headerProtector: headerProtector,
nonceBuf: make([]byte, aead.NonceSize()),
} }
} }
func (s *longHeaderSealer) Seal(dst, src []byte, pn protocol.PacketNumber, ad []byte) []byte { func (s *longHeaderSealer) Seal(dst, src []byte, pn protocol.PacketNumber, ad []byte) []byte {
binary.BigEndian.PutUint64(s.nonceBuf[len(s.nonceBuf)-8:], uint64(pn)) binary.BigEndian.PutUint64(s.nonceBuf[:], uint64(pn))
// The AEAD we're using here will be the qtls.aeadAESGCM13. return s.aead.Seal(dst, s.nonceBuf[:], src, ad)
// It uses the nonce provided here and XOR it with the IV.
return s.aead.Seal(dst, s.nonceBuf, src, ad)
} }
func (s *longHeaderSealer) EncryptHeader(sample []byte, firstByte *byte, pnBytes []byte) { func (s *longHeaderSealer) EncryptHeader(sample []byte, firstByte *byte, pnBytes []byte) {
@ -53,21 +50,23 @@ func (s *longHeaderSealer) Overhead() int {
} }
type longHeaderOpener struct { type longHeaderOpener struct {
aead cipher.AEAD aead *xorNonceAEAD
headerProtector headerProtector headerProtector headerProtector
highestRcvdPN protocol.PacketNumber // highest packet number received (which could be successfully unprotected) highestRcvdPN protocol.PacketNumber // highest packet number received (which could be successfully unprotected)
// use a single slice to avoid allocations // use a single array to avoid allocations
nonceBuf []byte nonceBuf [8]byte
} }
var _ LongHeaderOpener = &longHeaderOpener{} var _ LongHeaderOpener = &longHeaderOpener{}
func newLongHeaderOpener(aead cipher.AEAD, headerProtector headerProtector) LongHeaderOpener { func newLongHeaderOpener(aead *xorNonceAEAD, headerProtector headerProtector) LongHeaderOpener {
if aead.NonceSize() != 8 {
panic("unexpected nonce size")
}
return &longHeaderOpener{ return &longHeaderOpener{
aead: aead, aead: aead,
headerProtector: headerProtector, headerProtector: headerProtector,
nonceBuf: make([]byte, aead.NonceSize()),
} }
} }
@ -76,10 +75,8 @@ func (o *longHeaderOpener) DecodePacketNumber(wirePN protocol.PacketNumber, wire
} }
func (o *longHeaderOpener) Open(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error) { func (o *longHeaderOpener) Open(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error) {
binary.BigEndian.PutUint64(o.nonceBuf[len(o.nonceBuf)-8:], uint64(pn)) binary.BigEndian.PutUint64(o.nonceBuf[:], uint64(pn))
// The AEAD we're using here will be the qtls.aeadAESGCM13. dec, err := o.aead.Open(dst, o.nonceBuf[:], src, ad)
// It uses the nonce provided here and XOR it with the IV.
dec, err := o.aead.Open(dst, o.nonceBuf, src, ad)
if err == nil { if err == nil {
o.highestRcvdPN = max(o.highestRcvdPN, pn) o.highestRcvdPN = max(o.highestRcvdPN, pn)
} else { } else {

View file

@ -33,8 +33,8 @@ var _ = Describe("Long Header AEAD", func() {
aead, err := cipher.NewGCM(block) aead, err := cipher.NewGCM(block)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
return newLongHeaderSealer(aead, newHeaderProtector(cs, hpKey, true, v)), return newLongHeaderSealer(&xorNonceAEAD{aead: aead}, newHeaderProtector(cs, hpKey, true, v)),
newLongHeaderOpener(aead, newHeaderProtector(cs, hpKey, true, v)) newLongHeaderOpener(&xorNonceAEAD{aead: aead}, newHeaderProtector(cs, hpKey, true, v))
} }
Context("message encryption", func() { Context("message encryption", func() {

View file

@ -18,7 +18,7 @@ type cipherSuite struct {
ID uint16 ID uint16
Hash crypto.Hash Hash crypto.Hash
KeyLen int KeyLen int
AEAD func(key, nonceMask []byte) cipher.AEAD AEAD func(key, nonceMask []byte) *xorNonceAEAD
} }
func (s cipherSuite) IVLen() int { return aeadNonceLength } func (s cipherSuite) IVLen() int { return aeadNonceLength }
@ -36,7 +36,7 @@ func getCipherSuite(id uint16) *cipherSuite {
} }
} }
func aeadAESGCMTLS13(key, nonceMask []byte) cipher.AEAD { func aeadAESGCMTLS13(key, nonceMask []byte) *xorNonceAEAD {
if len(nonceMask) != aeadNonceLength { if len(nonceMask) != aeadNonceLength {
panic("tls: internal error: wrong nonce length") panic("tls: internal error: wrong nonce length")
} }
@ -54,7 +54,7 @@ func aeadAESGCMTLS13(key, nonceMask []byte) cipher.AEAD {
return ret return ret
} }
func aeadChaCha20Poly1305(key, nonceMask []byte) cipher.AEAD { func aeadChaCha20Poly1305(key, nonceMask []byte) *xorNonceAEAD {
if len(nonceMask) != aeadNonceLength { if len(nonceMask) != aeadNonceLength {
panic("tls: internal error: wrong nonce length") panic("tls: internal error: wrong nonce length")
} }