mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
handshake: optimize AEAD handling for long header sealers and openers (#4323)
This commit is contained in:
parent
f856163f1e
commit
71f5ae5ecb
3 changed files with 23 additions and 26 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue