From d5255a4075c8f58c58c6195c81094679fcafef10 Mon Sep 17 00:00:00 2001 From: Lucas Clemente Date: Tue, 26 Jul 2016 14:51:19 +0200 Subject: [PATCH] update AEADs to allow in-place encryption and decryption ref #217 --- crypto/AEAD.go | 4 +- crypto/aesgcm_aead.go | 8 ++-- crypto/aesgcm_aead_test.go | 14 +++---- crypto/chacha20poly1305_aead.go | 8 ++-- crypto/chacha20poly1305_aead_test.go | 14 +++---- crypto/null_aead.go | 30 ++++++++------- crypto/null_aead_test.go | 18 +++++++-- handshake/crypto_setup.go | 16 ++++---- handshake/crypto_setup_test.go | 55 ++++++++++++++++------------ packet_packer.go | 2 +- packet_unpacker.go | 2 +- packet_unpacker_test.go | 4 +- server_test.go | 2 +- 13 files changed, 99 insertions(+), 78 deletions(-) diff --git a/crypto/AEAD.go b/crypto/AEAD.go index 35772764..a59ce6e8 100644 --- a/crypto/AEAD.go +++ b/crypto/AEAD.go @@ -4,6 +4,6 @@ import "github.com/lucas-clemente/quic-go/protocol" // An AEAD implements QUIC's authenticated encryption and associated data type AEAD interface { - Open(packetNumber protocol.PacketNumber, associatedData []byte, ciphertext []byte) ([]byte, error) - Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte + Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) + Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte } diff --git a/crypto/aesgcm_aead.go b/crypto/aesgcm_aead.go index 40f9a938..a738cc2b 100644 --- a/crypto/aesgcm_aead.go +++ b/crypto/aesgcm_aead.go @@ -49,10 +49,10 @@ func NewAEADAESGCM(otherKey []byte, myKey []byte, otherIV []byte, myIV []byte) ( }, nil } -func (aead *aeadAESGCM) Open(packetNumber protocol.PacketNumber, associatedData []byte, ciphertext []byte) ([]byte, error) { - return aead.decrypter.Open(nil, makeNonce(aead.otherIV, packetNumber), ciphertext, associatedData) +func (aead *aeadAESGCM) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { + return aead.decrypter.Open(dst, makeNonce(aead.otherIV, packetNumber), src, associatedData) } -func (aead *aeadAESGCM) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte { - return aead.encrypter.Seal(nil, makeNonce(aead.myIV, packetNumber), plaintext, associatedData) +func (aead *aeadAESGCM) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { + return aead.encrypter.Seal(dst, makeNonce(aead.myIV, packetNumber), src, associatedData) } diff --git a/crypto/aesgcm_aead_test.go b/crypto/aesgcm_aead_test.go index d41235e1..c5e4c4da 100644 --- a/crypto/aesgcm_aead_test.go +++ b/crypto/aesgcm_aead_test.go @@ -30,27 +30,27 @@ var _ = Describe("AES-GCM", func() { }) It("seals and opens", func() { - b := alice.Seal(42, []byte("aad"), []byte("foobar")) - text, err := bob.Open(42, []byte("aad"), b) + b := alice.Seal(nil, []byte("foobar"), 42, []byte("aad")) + text, err := bob.Open(nil, b, 42, []byte("aad")) Expect(err).ToNot(HaveOccurred()) Expect(text).To(Equal([]byte("foobar"))) }) It("seals and opens reverse", func() { - b := bob.Seal(42, []byte("aad"), []byte("foobar")) - text, err := alice.Open(42, []byte("aad"), b) + b := bob.Seal(nil, []byte("foobar"), 42, []byte("aad")) + text, err := alice.Open(nil, b, 42, []byte("aad")) Expect(err).ToNot(HaveOccurred()) Expect(text).To(Equal([]byte("foobar"))) }) It("has the proper length", func() { - b := bob.Seal(42, []byte("aad"), []byte("foobar")) + b := bob.Seal(nil, []byte("foobar"), 42, []byte("aad")) Expect(b).To(HaveLen(6 + 12)) }) It("fails with wrong aad", func() { - b := alice.Seal(42, []byte("aad"), []byte("foobar")) - _, err := bob.Open(42, []byte("aad2"), b) + b := alice.Seal(nil, []byte("foobar"), 42, []byte("aad")) + _, err := bob.Open(nil, b, 42, []byte("aad2")) Expect(err).To(HaveOccurred()) }) diff --git a/crypto/chacha20poly1305_aead.go b/crypto/chacha20poly1305_aead.go index 7903d2f3..c2388cfd 100644 --- a/crypto/chacha20poly1305_aead.go +++ b/crypto/chacha20poly1305_aead.go @@ -43,12 +43,12 @@ func NewAEADChacha20Poly1305(otherKey []byte, myKey []byte, otherIV []byte, myIV }, nil } -func (aead *aeadChacha20Poly1305) Open(packetNumber protocol.PacketNumber, associatedData []byte, ciphertext []byte) ([]byte, error) { - return aead.decrypter.Open(nil, makeNonce(aead.otherIV, packetNumber), ciphertext, associatedData) +func (aead *aeadChacha20Poly1305) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { + return aead.decrypter.Open(dst, makeNonce(aead.otherIV, packetNumber), src, associatedData) } -func (aead *aeadChacha20Poly1305) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte { - return aead.encrypter.Seal(nil, makeNonce(aead.myIV, packetNumber), plaintext, associatedData) +func (aead *aeadChacha20Poly1305) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { + return aead.encrypter.Seal(dst, makeNonce(aead.myIV, packetNumber), src, associatedData) } func makeNonce(iv []byte, packetNumber protocol.PacketNumber) []byte { diff --git a/crypto/chacha20poly1305_aead_test.go b/crypto/chacha20poly1305_aead_test.go index 96bb39c9..63d8b638 100644 --- a/crypto/chacha20poly1305_aead_test.go +++ b/crypto/chacha20poly1305_aead_test.go @@ -30,27 +30,27 @@ var _ = Describe("Chacha20poly1305", func() { }) It("seals and opens", func() { - b := alice.Seal(42, []byte("aad"), []byte("foobar")) - text, err := bob.Open(42, []byte("aad"), b) + b := alice.Seal(nil, []byte("foobar"), 42, []byte("aad")) + text, err := bob.Open(nil, b, 42, []byte("aad")) Expect(err).ToNot(HaveOccurred()) Expect(text).To(Equal([]byte("foobar"))) }) It("seals and opens reverse", func() { - b := bob.Seal(42, []byte("aad"), []byte("foobar")) - text, err := alice.Open(42, []byte("aad"), b) + b := bob.Seal(nil, []byte("foobar"), 42, []byte("aad")) + text, err := alice.Open(nil, b, 42, []byte("aad")) Expect(err).ToNot(HaveOccurred()) Expect(text).To(Equal([]byte("foobar"))) }) It("has the proper length", func() { - b := bob.Seal(42, []byte("aad"), []byte("foobar")) + b := bob.Seal(nil, []byte("foobar"), 42, []byte("aad")) Expect(b).To(HaveLen(6 + 12)) }) It("fails with wrong aad", func() { - b := alice.Seal(42, []byte("aad"), []byte("foobar")) - _, err := bob.Open(42, []byte("aad2"), b) + b := alice.Seal(nil, []byte("foobar"), 42, []byte("aad")) + _, err := bob.Open(nil, b, 42, []byte("aad2")) Expect(err).To(HaveOccurred()) }) diff --git a/crypto/null_aead.go b/crypto/null_aead.go index cc3f05ed..5aa198ce 100644 --- a/crypto/null_aead.go +++ b/crypto/null_aead.go @@ -14,36 +14,40 @@ type NullAEAD struct{} var _ AEAD = &NullAEAD{} // Open and verify the ciphertext -func (NullAEAD) Open(packetNumber protocol.PacketNumber, associatedData []byte, ciphertext []byte) ([]byte, error) { - if len(ciphertext) < 12 { +func (NullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { + if len(src) < 12 { return nil, errors.New("NullAEAD: ciphertext cannot be less than 12 bytes long") } hash := fnv128a.New() hash.Write(associatedData) - hash.Write(ciphertext[12:]) + hash.Write(src[12:]) testHigh, testLow := hash.Sum128() - low := binary.LittleEndian.Uint64(ciphertext) - high := binary.LittleEndian.Uint32(ciphertext[8:]) + low := binary.LittleEndian.Uint64(src) + high := binary.LittleEndian.Uint32(src[8:]) if uint32(testHigh&0xffffffff) != high || testLow != low { return nil, errors.New("NullAEAD: failed to authenticate received data") } - return ciphertext[12:], nil + return src[12:], nil } // Seal writes hash and ciphertext to the buffer -func (NullAEAD) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte { - res := make([]byte, 12+len(plaintext)) +func (NullAEAD) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { + if cap(dst) < 12+len(src) { + dst = make([]byte, 12+len(src)) + } else { + dst = dst[:12+len(src)] + } hash := fnv128a.New() hash.Write(associatedData) - hash.Write(plaintext) + hash.Write(src) high, low := hash.Sum128() - binary.LittleEndian.PutUint64(res, low) - binary.LittleEndian.PutUint32(res[8:], uint32(high)) - copy(res[12:], plaintext) - return res + copy(dst[12:], src) + binary.LittleEndian.PutUint64(dst, low) + binary.LittleEndian.PutUint32(dst[8:], uint32(high)) + return dst } diff --git a/crypto/null_aead_test.go b/crypto/null_aead_test.go index b4865a1c..14be9f4f 100644 --- a/crypto/null_aead_test.go +++ b/crypto/null_aead_test.go @@ -12,7 +12,7 @@ var _ = Describe("Crypto/NullAEAD", func() { hash := []byte{0x98, 0x9b, 0x33, 0x3f, 0xe8, 0xde, 0x32, 0x5c, 0xa6, 0x7f, 0x9c, 0xf7} cipherText := append(hash, plainText...) aead := &NullAEAD{} - res, err := aead.Open(0, aad, cipherText) + res, err := aead.Open(nil, cipherText, 0, aad) Expect(err).ToNot(HaveOccurred()) Expect(res).To(Equal([]byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood."))) }) @@ -23,7 +23,7 @@ var _ = Describe("Crypto/NullAEAD", func() { hash := []byte{0x98, 0x9b, 0x33, 0x3f, 0xe8, 0xde, 0x32, 0x5c, 0xa6, 0x7f, 0x9c, 0xf7} cipherText := append(hash, plainText...) aead := &NullAEAD{} - _, err := aead.Open(0, aad, cipherText) + _, err := aead.Open(nil, cipherText, 0, aad) Expect(err).To(HaveOccurred()) }) @@ -31,11 +31,21 @@ var _ = Describe("Crypto/NullAEAD", func() { aad := []byte("All human beings are born free and equal in dignity and rights.") plainText := []byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.") aead := &NullAEAD{} - Expect(aead.Seal(0, aad, plainText)).To(Equal(append([]byte{0x98, 0x9b, 0x33, 0x3f, 0xe8, 0xde, 0x32, 0x5c, 0xa6, 0x7f, 0x9c, 0xf7}, []byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.")...))) + Expect(aead.Seal(nil, plainText, 0, aad)).To(Equal(append([]byte{0x98, 0x9b, 0x33, 0x3f, 0xe8, 0xde, 0x32, 0x5c, 0xa6, 0x7f, 0x9c, 0xf7}, []byte("They are endowed with reason and conscience and should act towards one another in a spirit of brotherhood.")...))) }) It("rejects short ciphertexts", func() { - _, err := NullAEAD{}.Open(0, nil, nil) + _, err := NullAEAD{}.Open(nil, nil, 0, nil) Expect(err).To(MatchError("NullAEAD: ciphertext cannot be less than 12 bytes long")) }) + + It("seals in-place", func() { + aead := &NullAEAD{} + buf := make([]byte, 6, 12+6) + copy(buf, []byte("foobar")) + res := aead.Seal(buf[0:0], buf, 0, nil) + buf = buf[:12+6] + Expect(buf[12:]).To(Equal([]byte("foobar"))) + Expect(res[12:]).To(Equal([]byte("foobar"))) + }) }) diff --git a/handshake/crypto_setup.go b/handshake/crypto_setup.go index 0705376f..41c16a60 100644 --- a/handshake/crypto_setup.go +++ b/handshake/crypto_setup.go @@ -142,12 +142,12 @@ func (h *CryptoSetup) handleMessage(chloData []byte, cryptoData map[Tag][]byte) } // Open a message -func (h *CryptoSetup) Open(packetNumber protocol.PacketNumber, associatedData []byte, ciphertext []byte) ([]byte, error) { +func (h *CryptoSetup) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { h.mutex.RLock() defer h.mutex.RUnlock() if h.forwardSecureAEAD != nil { - res, err := h.forwardSecureAEAD.Open(packetNumber, associatedData, ciphertext) + res, err := h.forwardSecureAEAD.Open(dst, src, packetNumber, associatedData) if err == nil { h.receivedForwardSecurePacket = true return res, nil @@ -157,7 +157,7 @@ func (h *CryptoSetup) Open(packetNumber protocol.PacketNumber, associatedData [] } } if h.secureAEAD != nil { - res, err := h.secureAEAD.Open(packetNumber, associatedData, ciphertext) + res, err := h.secureAEAD.Open(dst, src, packetNumber, associatedData) if err == nil { h.receivedSecurePacket = true return res, nil @@ -166,17 +166,17 @@ func (h *CryptoSetup) Open(packetNumber protocol.PacketNumber, associatedData [] return nil, err } } - return (&crypto.NullAEAD{}).Open(packetNumber, associatedData, ciphertext) + return (&crypto.NullAEAD{}).Open(dst, src, packetNumber, associatedData) } // Seal a message, call LockForSealing() before! -func (h *CryptoSetup) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte { +func (h *CryptoSetup) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { if h.receivedForwardSecurePacket { - return h.forwardSecureAEAD.Seal(packetNumber, associatedData, plaintext) + return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData) } else if h.secureAEAD != nil { - return h.secureAEAD.Seal(packetNumber, associatedData, plaintext) + return h.secureAEAD.Seal(dst, src, packetNumber, associatedData) } else { - return (&crypto.NullAEAD{}).Seal(packetNumber, associatedData, plaintext) + return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData) } } diff --git a/handshake/crypto_setup_test.go b/handshake/crypto_setup_test.go index 9090bf95..aef8e9e1 100644 --- a/handshake/crypto_setup_test.go +++ b/handshake/crypto_setup_test.go @@ -52,17 +52,24 @@ type mockAEAD struct { sharedSecret []byte } -func (m *mockAEAD) Seal(packetNumber protocol.PacketNumber, associatedData []byte, plaintext []byte) []byte { - if m.forwardSecure { - return []byte("forward secure encrypted") +func (m *mockAEAD) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { + if cap(dst) < len(src)+12 { + dst = make([]byte, len(src)+12) } - return []byte("encrypted") + dst = dst[:len(src)+12] + copy(dst, src) + if !m.forwardSecure { + copy(dst[len(src):], []byte(" normal sec")) + } else { + copy(dst[len(src):], []byte(" forward sec")) + } + return dst } -func (m *mockAEAD) Open(packetNumber protocol.PacketNumber, associatedData []byte, ciphertext []byte) ([]byte, error) { - if m.forwardSecure && string(ciphertext) == "forward secure encrypted" { +func (m *mockAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { + if m.forwardSecure && string(src) == "forward secure encrypted" { return []byte("decrypted"), nil - } else if !m.forwardSecure && string(ciphertext) == "encrypted" { + } else if !m.forwardSecure && string(src) == "encrypted" { return []byte("decrypted"), nil } return nil, errors.New("authentication failed") @@ -296,11 +303,11 @@ var _ = Describe("Crypto setup", func() { Context("null encryption", func() { It("is used initially", func() { - Expect(cs.Seal(0, []byte{}, []byte("foobar"))).To(Equal(foobarFNVSigned)) + Expect(cs.Seal(nil, []byte("foobar"), 0, []byte{})).To(Equal(foobarFNVSigned)) }) It("is accepted initially", func() { - d, err := cs.Open(0, []byte{}, foobarFNVSigned) + d, err := cs.Open(nil, foobarFNVSigned, 0, []byte{}) Expect(err).ToNot(HaveOccurred()) Expect(d).To(Equal([]byte("foobar"))) }) @@ -308,23 +315,23 @@ var _ = Describe("Crypto setup", func() { It("is still accepted after CHLO", func() { doCHLO() Expect(cs.secureAEAD).ToNot(BeNil()) - _, err := cs.Open(0, []byte{}, foobarFNVSigned) + _, err := cs.Open(nil, foobarFNVSigned, 0, []byte{}) Expect(err).ToNot(HaveOccurred()) }) It("is not accepted after receiving secure packet", func() { doCHLO() Expect(cs.secureAEAD).ToNot(BeNil()) - d, err := cs.Open(0, []byte{}, []byte("encrypted")) + d, err := cs.Open(nil, []byte("encrypted"), 0, []byte{}) Expect(err).ToNot(HaveOccurred()) Expect(d).To(Equal([]byte("decrypted"))) - _, err = cs.Open(0, []byte{}, foobarFNVSigned) + _, err = cs.Open(nil, foobarFNVSigned, 0, []byte{}) Expect(err).To(MatchError("authentication failed")) }) It("is not used after CHLO", func() { doCHLO() - d := cs.Seal(0, []byte{}, []byte("foobar")) + d := cs.Seal(nil, []byte("foobar"), 0, []byte{}) Expect(d).ToNot(Equal(foobarFNVSigned)) }) }) @@ -332,30 +339,30 @@ var _ = Describe("Crypto setup", func() { Context("initial encryption", func() { It("is used after CHLO", func() { doCHLO() - d := cs.Seal(0, []byte{}, []byte("foobar")) - Expect(d).To(Equal([]byte("encrypted"))) + d := cs.Seal(nil, []byte("foobar"), 0, []byte{}) + Expect(d).To(Equal([]byte("foobar normal sec"))) }) It("is accepted after CHLO", func() { doCHLO() - d, err := cs.Open(0, []byte{}, []byte("encrypted")) + d, err := cs.Open(nil, []byte("encrypted"), 0, []byte{}) Expect(err).ToNot(HaveOccurred()) Expect(d).To(Equal([]byte("decrypted"))) }) It("is not used after receiving forward secure packet", func() { doCHLO() - _, err := cs.Open(0, []byte{}, []byte("forward secure encrypted")) + _, err := cs.Open(nil, []byte("forward secure encrypted"), 0, []byte{}) Expect(err).ToNot(HaveOccurred()) - d := cs.Seal(0, []byte{}, []byte("foobar")) - Expect(d).To(Equal([]byte("forward secure encrypted"))) + d := cs.Seal(nil, []byte("foobar"), 0, []byte{}) + Expect(d).To(Equal([]byte("foobar forward sec"))) }) It("is not accepted after receiving forward secure packet", func() { doCHLO() - _, err := cs.Open(0, []byte{}, []byte("forward secure encrypted")) + _, err := cs.Open(nil, []byte("forward secure encrypted"), 0, []byte{}) Expect(err).ToNot(HaveOccurred()) - _, err = cs.Open(0, []byte{}, []byte("encrypted")) + _, err = cs.Open(nil, []byte("encrypted"), 0, []byte{}) Expect(err).To(MatchError("authentication failed")) }) }) @@ -363,10 +370,10 @@ var _ = Describe("Crypto setup", func() { Context("forward secure encryption", func() { It("is used after receiving forward secure packet", func() { doCHLO() - _, err := cs.Open(0, []byte{}, []byte("forward secure encrypted")) + _, err := cs.Open(nil, []byte("forward secure encrypted"), 0, []byte{}) Expect(err).ToNot(HaveOccurred()) - d := cs.Seal(0, []byte{}, []byte("foobar")) - Expect(d).To(Equal([]byte("forward secure encrypted"))) + d := cs.Seal(nil, []byte("foobar"), 0, []byte{}) + Expect(d).To(Equal([]byte("foobar forward sec"))) }) }) }) diff --git a/packet_packer.go b/packet_packer.go index 6ba4bc72..897e5257 100644 --- a/packet_packer.go +++ b/packet_packer.go @@ -132,7 +132,7 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, con return nil, err } - ciphertext := p.cryptoSetup.Seal(currentPacketNumber, raw.Bytes(), payload) + ciphertext := p.cryptoSetup.Seal(nil, payload, currentPacketNumber, raw.Bytes()) raw.Write(ciphertext) if protocol.ByteCount(raw.Len()) > protocol.MaxPacketSize { diff --git a/packet_unpacker.go b/packet_unpacker.go index d3678c04..dd9650a2 100644 --- a/packet_unpacker.go +++ b/packet_unpacker.go @@ -24,7 +24,7 @@ type packetUnpacker struct { func (u *packetUnpacker) Unpack(publicHeaderBinary []byte, hdr *publicHeader, r *bytes.Reader) (*unpackedPacket, error) { ciphertext, _ := ioutil.ReadAll(r) - plaintext, err := u.aead.Open(hdr.PacketNumber, publicHeaderBinary, ciphertext) + plaintext, err := u.aead.Open(nil, ciphertext, hdr.PacketNumber, publicHeaderBinary) if err != nil { // Wrap err in quicError so that public reset is sent by session return nil, qerr.Error(qerr.DecryptionFailure, err.Error()) diff --git a/packet_unpacker_test.go b/packet_unpacker_test.go index 0533e8a8..519309a7 100644 --- a/packet_unpacker_test.go +++ b/packet_unpacker_test.go @@ -38,13 +38,13 @@ var _ = Describe("Packet unpacker", func() { if unpacker.version < protocol.Version34 { // add private flag data = append([]byte{0x01}, data...) } - r = bytes.NewReader(aead.Seal(0, hdrBin, data)) + r = bytes.NewReader(aead.Seal(nil, data, 0, hdrBin)) } It("returns an error for empty packets that don't have a private flag, for QUIC Version < 34", func() { // don't use setReader here, since it adds a private flag unpacker.version = protocol.Version33 - r = bytes.NewReader(aead.Seal(0, hdrBin, []byte{})) + r = bytes.NewReader(aead.Seal(nil, nil, 0, hdrBin)) _, err := unpacker.Unpack(hdrBin, hdr, r) Expect(err).To(MatchError(qerr.MissingPayload)) }) diff --git a/server_test.go b/server_test.go index dbaf7034..3f4e6abb 100644 --- a/server_test.go +++ b/server_test.go @@ -72,7 +72,7 @@ var _ = Describe("Server", func() { It("closes and deletes sessions", func() { pheader := []byte{0x09, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c, 0x51, 0x30, 0x33, 0x32, 0x01} - err := server.handlePacket(nil, nil, append(pheader, (&crypto.NullAEAD{}).Seal(0, pheader, nil)...)) + err := server.handlePacket(nil, nil, append(pheader, (&crypto.NullAEAD{}).Seal(nil, nil, 0, pheader)...)) Expect(err).ToNot(HaveOccurred()) Expect(server.sessions).To(HaveLen(1)) server.closeCallback(0x4cfa9f9b668619f6)