Fix encryption of stream data

This commit splits up handling of the crypto stream and the other streams in the framer, crypto setup, and the packer.

- Crypto stream data is handled separately and should never be sent unencrypted or FW-secure. Fixes #544.
- Non-crypto stream data is only sent with FW encryption on the server and only with non-FW or FW encryption on the client. Fixes #611.

The crypto stream is current excluded from flow control (#657), but that shouldn't be an issue in practice for now.
This commit is contained in:
Lucas Clemente 2017-06-09 16:06:18 +02:00
parent 4ea2ccd526
commit e43b91f633
10 changed files with 183 additions and 135 deletions

View file

@ -332,7 +332,6 @@ func (h *cryptoSetupClient) Open(dst, src []byte, packetNumber protocol.PacketNu
func (h *cryptoSetupClient) GetSealer() (protocol.EncryptionLevel, Sealer) { func (h *cryptoSetupClient) GetSealer() (protocol.EncryptionLevel, Sealer) {
h.mutex.RLock() h.mutex.RLock()
defer h.mutex.RUnlock() defer h.mutex.RUnlock()
if h.forwardSecureAEAD != nil { if h.forwardSecureAEAD != nil {
return protocol.EncryptionForwardSecure, h.sealForwardSecure return protocol.EncryptionForwardSecure, h.sealForwardSecure
} else if h.secureAEAD != nil { } else if h.secureAEAD != nil {
@ -342,6 +341,10 @@ func (h *cryptoSetupClient) GetSealer() (protocol.EncryptionLevel, Sealer) {
} }
} }
func (h *cryptoSetupClient) GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) {
return protocol.EncryptionUnencrypted, h.sealUnencrypted
}
func (h *cryptoSetupClient) GetSealerWithEncryptionLevel(encLevel protocol.EncryptionLevel) (Sealer, error) { func (h *cryptoSetupClient) GetSealerWithEncryptionLevel(encLevel protocol.EncryptionLevel) (Sealer, error) {
h.mutex.RLock() h.mutex.RLock()
defer h.mutex.RUnlock() defer h.mutex.RUnlock()

View file

@ -686,6 +686,13 @@ var _ = Describe("Client Crypto Setup", func() {
Expect(d).To(Equal(foobarFNVSigned)) Expect(d).To(Equal(foobarFNVSigned))
}) })
It("is used for the crypto stream", func() {
enc, seal := cs.GetSealerForCryptoStream()
Expect(enc).To(Equal(protocol.EncryptionUnencrypted))
d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal(foobarFNVSigned))
})
It("is accepted initially", func() { It("is accepted initially", func() {
d, enc, err := cs.Open(nil, foobarFNVSigned, 0, []byte{}) d, enc, err := cs.Open(nil, foobarFNVSigned, 0, []byte{})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -744,6 +751,14 @@ var _ = Describe("Client Crypto Setup", func() {
Expect(err).To(MatchError("authentication failed")) Expect(err).To(MatchError("authentication failed"))
Expect(enc).To(Equal(protocol.EncryptionUnspecified)) Expect(enc).To(Equal(protocol.EncryptionUnspecified))
}) })
It("is not used for the crypto stream", func() {
doCompleteREJ()
enc, seal := cs.GetSealerForCryptoStream()
Expect(enc).To(Equal(protocol.EncryptionUnencrypted))
d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal(foobarFNVSigned))
})
}) })
Context("forward-secure encryption", func() { Context("forward-secure encryption", func() {
@ -757,6 +772,14 @@ var _ = Describe("Client Crypto Setup", func() {
d := seal(nil, []byte("foobar"), 0, []byte{}) d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal([]byte("foobar forward sec"))) Expect(d).To(Equal([]byte("foobar forward sec")))
}) })
It("is not used for the crypto stream", func() {
doSHLO()
enc, seal := cs.GetSealerForCryptoStream()
Expect(enc).To(Equal(protocol.EncryptionUnencrypted))
d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal(foobarFNVSigned))
})
}) })
Context("forcing encryption levels", func() { Context("forcing encryption levels", func() {

View file

@ -214,12 +214,16 @@ func (h *cryptoSetupServer) Open(dst, src []byte, packetNumber protocol.PacketNu
func (h *cryptoSetupServer) GetSealer() (protocol.EncryptionLevel, Sealer) { func (h *cryptoSetupServer) GetSealer() (protocol.EncryptionLevel, Sealer) {
h.mutex.RLock() h.mutex.RLock()
defer h.mutex.RUnlock() defer h.mutex.RUnlock()
if h.forwardSecureAEAD != nil {
if h.forwardSecureAEAD != nil && h.sentSHLO {
return protocol.EncryptionForwardSecure, h.sealForwardSecure return protocol.EncryptionForwardSecure, h.sealForwardSecure
} else if h.secureAEAD != nil { }
// secureAEAD and forwardSecureAEAD are created at the same time (when receiving the CHLO) return protocol.EncryptionUnencrypted, h.sealUnencrypted
// make sure that the SHLO isn't sent forward-secure }
func (h *cryptoSetupServer) GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) {
h.mutex.RLock()
defer h.mutex.RUnlock()
if h.secureAEAD != nil {
return protocol.EncryptionSecure, h.sealSecure return protocol.EncryptionSecure, h.sealSecure
} }
return protocol.EncryptionUnencrypted, h.sealUnencrypted return protocol.EncryptionUnencrypted, h.sealUnencrypted
@ -251,7 +255,6 @@ func (h *cryptoSetupServer) sealUnencrypted(dst, src []byte, packetNumber protoc
} }
func (h *cryptoSetupServer) sealSecure(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { func (h *cryptoSetupServer) sealSecure(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
h.sentSHLO = true
return h.secureAEAD.Seal(dst, src, packetNumber, associatedData) return h.secureAEAD.Seal(dst, src, packetNumber, associatedData)
} }

View file

@ -551,6 +551,13 @@ var _ = Describe("Server Crypto Setup", func() {
Expect(d).To(Equal(foobarServerFNVSigned)) Expect(d).To(Equal(foobarServerFNVSigned))
}) })
It("is used for crypto stream", func() {
enc, seal := cs.GetSealerForCryptoStream()
Expect(enc).To(Equal(protocol.EncryptionUnencrypted))
d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal(foobarServerFNVSigned))
})
It("is accepted initially", func() { It("is accepted initially", func() {
d, enc, err := cs.Open(nil, foobarClientFNVSigned, 0, []byte{}) d, enc, err := cs.Open(nil, foobarClientFNVSigned, 0, []byte{})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -595,14 +602,6 @@ var _ = Describe("Server Crypto Setup", func() {
}) })
Context("initial encryption", func() { Context("initial encryption", func() {
It("is used after CHLO", func() {
doCHLO()
enc, seal := cs.GetSealer()
Expect(enc).To(Equal(protocol.EncryptionSecure))
d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal([]byte("foobar normal sec")))
})
It("is accepted after CHLO", func() { It("is accepted after CHLO", func() {
doCHLO() doCHLO()
d, enc, err := cs.Open(nil, []byte("encrypted"), 0, []byte{}) d, enc, err := cs.Open(nil, []byte("encrypted"), 0, []byte{})
@ -619,15 +618,20 @@ var _ = Describe("Server Crypto Setup", func() {
Expect(err).To(MatchError("authentication failed")) Expect(err).To(MatchError("authentication failed"))
Expect(enc).To(Equal(protocol.EncryptionUnspecified)) Expect(enc).To(Equal(protocol.EncryptionUnspecified))
}) })
It("is used for crypto stream", func() {
doCHLO()
enc, seal := cs.GetSealerForCryptoStream()
Expect(enc).To(Equal(protocol.EncryptionSecure))
d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal([]byte("foobar normal sec")))
})
}) })
Context("forward secure encryption", func() { Context("forward secure encryption", func() {
It("is used after sending out one packet with initial encryption", func() { It("is used after the CHLO", func() {
doCHLO() doCHLO()
enc, seal := cs.GetSealer() enc, seal := cs.GetSealer()
Expect(enc).To(Equal(protocol.EncryptionSecure))
_ = seal(nil, []byte("SHLO"), 0, []byte{})
enc, seal = cs.GetSealer()
Expect(enc).To(Equal(protocol.EncryptionForwardSecure)) Expect(enc).To(Equal(protocol.EncryptionForwardSecure))
d := seal(nil, []byte("foobar"), 0, []byte{}) d := seal(nil, []byte("foobar"), 0, []byte{})
Expect(d).To(Equal([]byte("foobar forward sec"))) Expect(d).To(Equal([]byte("foobar forward sec")))

View file

@ -15,6 +15,7 @@ type CryptoSetup interface {
GetSealer() (protocol.EncryptionLevel, Sealer) GetSealer() (protocol.EncryptionLevel, Sealer)
GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (Sealer, error) GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (Sealer, error)
GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer)
} }
// TransportParameters are parameters sent to the peer during the handshake // TransportParameters are parameters sent to the peer during the handshake

View file

@ -9,7 +9,6 @@ import (
"github.com/lucas-clemente/quic-go/frames" "github.com/lucas-clemente/quic-go/frames"
"github.com/lucas-clemente/quic-go/handshake" "github.com/lucas-clemente/quic-go/handshake"
"github.com/lucas-clemente/quic-go/protocol" "github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
) )
type packedPacket struct { type packedPacket struct {
@ -24,18 +23,21 @@ type packetPacker struct {
perspective protocol.Perspective perspective protocol.Perspective
version protocol.VersionNumber version protocol.VersionNumber
cryptoSetup handshake.CryptoSetup cryptoSetup handshake.CryptoSetup
// as long as packets are not sent with forward-secure encryption, we limit the MaxPacketSize such that they can be retransmitted as a whole
isForwardSecure bool
packetNumberGenerator *packetNumberGenerator packetNumberGenerator *packetNumberGenerator
connectionParameters handshake.ConnectionParametersManager
streamFramer *streamFramer
connectionParameters handshake.ConnectionParametersManager
streamFramer *streamFramer
controlFrames []frames.Frame controlFrames []frames.Frame
} }
func newPacketPacker(connectionID protocol.ConnectionID, cryptoSetup handshake.CryptoSetup, connectionParameters handshake.ConnectionParametersManager, streamFramer *streamFramer, perspective protocol.Perspective, version protocol.VersionNumber) *packetPacker { func newPacketPacker(connectionID protocol.ConnectionID,
cryptoSetup handshake.CryptoSetup,
connectionParameters handshake.ConnectionParametersManager,
streamFramer *streamFramer,
perspective protocol.Perspective,
version protocol.VersionNumber,
) *packetPacker {
return &packetPacker{ return &packetPacker{
cryptoSetup: cryptoSetup, cryptoSetup: cryptoSetup,
connectionID: connectionID, connectionID: connectionID,
@ -63,7 +65,6 @@ func (p *packetPacker) RetransmitNonForwardSecurePacket(stopWaitingFrame *frames
if stopWaitingFrame == nil { if stopWaitingFrame == nil {
return nil, errors.New("PacketPacker BUG: Handshake retransmissions must contain a StopWaitingFrame") return nil, errors.New("PacketPacker BUG: Handshake retransmissions must contain a StopWaitingFrame")
} }
return p.packPacket(stopWaitingFrame, 0, packet) return p.packPacket(stopWaitingFrame, 0, packet)
} }
@ -78,10 +79,12 @@ func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, con
func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, leastUnacked protocol.PacketNumber, handshakePacketToRetransmit *ackhandler.Packet) (*packedPacket, error) { func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, leastUnacked protocol.PacketNumber, handshakePacketToRetransmit *ackhandler.Packet) (*packedPacket, error) {
// handshakePacketToRetransmit is only set for handshake retransmissions // handshakePacketToRetransmit is only set for handshake retransmissions
isHandshakeRetransmission := (handshakePacketToRetransmit != nil) isHandshakeRetransmission := (handshakePacketToRetransmit != nil)
isCryptoStreamFrame := p.streamFramer.HasCryptoStreamFrame()
var sealer handshake.Sealer var sealer handshake.Sealer
var encLevel protocol.EncryptionLevel var encLevel protocol.EncryptionLevel
// TODO(#656): Only do this for the crypto stream
if isHandshakeRetransmission { if isHandshakeRetransmission {
var err error var err error
encLevel = handshakePacketToRetransmit.EncryptionLevel encLevel = handshakePacketToRetransmit.EncryptionLevel
@ -89,6 +92,8 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, lea
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else if isCryptoStreamFrame {
encLevel, sealer = p.cryptoSetup.GetSealerForCryptoStream()
} else { } else {
encLevel, sealer = p.cryptoSetup.GetSealer() encLevel, sealer = p.cryptoSetup.GetSealer()
} }
@ -125,12 +130,12 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, lea
} }
} else if isConnectionClose { } else if isConnectionClose {
payloadFrames = []frames.Frame{p.controlFrames[0]} payloadFrames = []frames.Frame{p.controlFrames[0]}
} else if isCryptoStreamFrame {
maxLen := protocol.MaxFrameAndPublicHeaderSize - protocol.NonForwardSecurePacketSizeReduction - publicHeaderLength
payloadFrames = []frames.Frame{p.streamFramer.PopCryptoStreamFrame(maxLen)}
} else { } else {
maxSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength maxSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength
if !p.isForwardSecure { payloadFrames, err = p.composeNextPacket(stopWaitingFrame, maxSize, p.canSendData(encLevel))
maxSize -= protocol.NonForwardSecurePacketSizeReduction
}
payloadFrames, err = p.composeNextPacket(stopWaitingFrame, maxSize)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -156,11 +161,7 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, lea
payloadStartIndex := buffer.Len() payloadStartIndex := buffer.Len()
var hasNonCryptoStreamData bool // does this frame contain any stream frame on a stream > 1
for _, frame := range payloadFrames { for _, frame := range payloadFrames {
if sf, ok := frame.(*frames.StreamFrame); ok && sf.StreamID != 1 {
hasNonCryptoStreamData = true
}
err = frame.Write(buffer, p.version) err = frame.Write(buffer, p.version)
if err != nil { if err != nil {
return nil, err return nil, err
@ -175,13 +176,9 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, lea
_ = sealer(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], publicHeader.PacketNumber, raw[:payloadStartIndex]) _ = sealer(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], publicHeader.PacketNumber, raw[:payloadStartIndex])
raw = raw[0 : buffer.Len()+12] raw = raw[0 : buffer.Len()+12]
if hasNonCryptoStreamData && encLevel <= protocol.EncryptionUnencrypted {
return nil, qerr.AttemptToSendUnencryptedStreamData
}
num := p.packetNumberGenerator.Pop() num := p.packetNumberGenerator.Pop()
if num != publicHeader.PacketNumber { if num != publicHeader.PacketNumber {
return nil, errors.New("PacketPacker BUG: Peeked and Popped packet numbers do not match.") return nil, errors.New("packetPacker BUG: Peeked and Popped packet numbers do not match")
} }
return &packedPacket{ return &packedPacket{
@ -192,7 +189,8 @@ func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, lea
}, nil }, nil
} }
func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFrame, maxFrameSize protocol.ByteCount) ([]frames.Frame, error) { func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFrame,
maxFrameSize protocol.ByteCount, canSendStreamFrames bool) ([]frames.Frame, error) {
var payloadLength protocol.ByteCount var payloadLength protocol.ByteCount
var payloadFrames []frames.Frame var payloadFrames []frames.Frame
@ -220,6 +218,10 @@ func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFra
return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize) return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
} }
if !canSendStreamFrames {
return payloadFrames, nil
}
// temporarily increase the maxFrameSize by 2 bytes // temporarily increase the maxFrameSize by 2 bytes
// this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set // this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
// however, for the last StreamFrame in the packet, we can omit the DataLen, thus saving 2 bytes and yielding a packet of exactly the correct size // however, for the last StreamFrame in the packet, we can omit the DataLen, thus saving 2 bytes and yielding a packet of exactly the correct size
@ -246,10 +248,6 @@ func (p *packetPacker) QueueControlFrameForNextPacket(f frames.Frame) {
p.controlFrames = append(p.controlFrames, f) p.controlFrames = append(p.controlFrames, f)
} }
func (p *packetPacker) SetForwardSecure() {
p.isForwardSecure = true
}
func (p *packetPacker) getPublicHeader(leastUnacked protocol.PacketNumber, encLevel protocol.EncryptionLevel) *PublicHeader { func (p *packetPacker) getPublicHeader(leastUnacked protocol.PacketNumber, encLevel protocol.EncryptionLevel) *PublicHeader {
pnum := p.packetNumberGenerator.Peek() pnum := p.packetNumberGenerator.Peek()
packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(pnum, leastUnacked) packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(pnum, leastUnacked)
@ -270,3 +268,10 @@ func (p *packetPacker) getPublicHeader(leastUnacked protocol.PacketNumber, encLe
return publicHeader return publicHeader
} }
func (p *packetPacker) canSendData(encLevel protocol.EncryptionLevel) bool {
if p.perspective == protocol.PerspectiveClient {
return encLevel >= protocol.EncryptionSecure
}
return encLevel == protocol.EncryptionForwardSecure
}

View file

@ -8,15 +8,15 @@ import (
"github.com/lucas-clemente/quic-go/handshake" "github.com/lucas-clemente/quic-go/handshake"
"github.com/lucas-clemente/quic-go/internal/mocks" "github.com/lucas-clemente/quic-go/internal/mocks"
"github.com/lucas-clemente/quic-go/protocol" "github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
type mockCryptoSetup struct { type mockCryptoSetup struct {
handleErr error handleErr error
divNonce []byte divNonce []byte
encLevelSeal protocol.EncryptionLevel encLevelSeal protocol.EncryptionLevel
encLevelSealCrypto protocol.EncryptionLevel
} }
func (m *mockCryptoSetup) HandleCryptoStream() error { func (m *mockCryptoSetup) HandleCryptoStream() error {
@ -30,6 +30,11 @@ func (m *mockCryptoSetup) GetSealer() (protocol.EncryptionLevel, handshake.Seale
return append(src, bytes.Repeat([]byte{0}, 12)...) return append(src, bytes.Repeat([]byte{0}, 12)...)
} }
} }
func (m *mockCryptoSetup) GetSealerForCryptoStream() (protocol.EncryptionLevel, handshake.Sealer) {
return m.encLevelSealCrypto, func(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
return append(src, bytes.Repeat([]byte{0}, 12)...)
}
}
func (m *mockCryptoSetup) GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (handshake.Sealer, error) { func (m *mockCryptoSetup) GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (handshake.Sealer, error) {
return func(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte { return func(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
return append(src, bytes.Repeat([]byte{0}, 12)...) return append(src, bytes.Repeat([]byte{0}, 12)...)
@ -46,13 +51,19 @@ var _ = Describe("Packet packer", func() {
publicHeaderLen protocol.ByteCount publicHeaderLen protocol.ByteCount
maxFrameSize protocol.ByteCount maxFrameSize protocol.ByteCount
streamFramer *streamFramer streamFramer *streamFramer
cryptoStream *stream
) )
BeforeEach(func() { BeforeEach(func() {
mockCpm := mocks.NewMockConnectionParametersManager(mockCtrl) mockCpm := mocks.NewMockConnectionParametersManager(mockCtrl)
mockCpm.EXPECT().TruncateConnectionID().Return(false).AnyTimes() mockCpm.EXPECT().TruncateConnectionID().Return(false).AnyTimes()
streamFramer = newStreamFramer(newStreamsMap(nil, protocol.PerspectiveServer, nil), nil) cryptoStream = &stream{}
streamsMap := newStreamsMap(nil, protocol.PerspectiveServer, nil)
streamsMap.streams[1] = cryptoStream
streamsMap.openStreams = []protocol.StreamID{1}
streamFramer = newStreamFramer(streamsMap, nil)
packer = &packetPacker{ packer = &packetPacker{
cryptoSetup: &mockCryptoSetup{encLevelSeal: protocol.EncryptionForwardSecure}, cryptoSetup: &mockCryptoSetup{encLevelSeal: protocol.EncryptionForwardSecure},
@ -65,7 +76,6 @@ var _ = Describe("Packet packer", func() {
publicHeaderLen = 1 + 8 + 2 // 1 flag byte, 8 connection ID, 2 packet number publicHeaderLen = 1 + 8 + 2 // 1 flag byte, 8 connection ID, 2 packet number
maxFrameSize = protocol.MaxFrameAndPublicHeaderSize - publicHeaderLen maxFrameSize = protocol.MaxFrameAndPublicHeaderSize - publicHeaderLen
packer.version = protocol.VersionWhatever packer.version = protocol.VersionWhatever
packer.isForwardSecure = true
}) })
It("returns nil when no packet is queued", func() { It("returns nil when no packet is queued", func() {
@ -90,7 +100,7 @@ var _ = Describe("Packet packer", func() {
}) })
It("stores the encryption level a packet was sealed with", func() { It("stores the encryption level a packet was sealed with", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionSecure packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionForwardSecure
f := &frames.StreamFrame{ f := &frames.StreamFrame{
StreamID: 5, StreamID: 5,
Data: []byte("foobar"), Data: []byte("foobar"),
@ -98,7 +108,7 @@ var _ = Describe("Packet packer", func() {
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
p, err := packer.PackPacket(nil, []frames.Frame{}, 0) p, err := packer.PackPacket(nil, []frames.Frame{}, 0)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(p.encryptionLevel).To(Equal(protocol.EncryptionSecure)) Expect(p.encryptionLevel).To(Equal(protocol.EncryptionForwardSecure))
}) })
Context("diversificaton nonces", func() { Context("diversificaton nonces", func() {
@ -107,40 +117,27 @@ var _ = Describe("Packet packer", func() {
BeforeEach(func() { BeforeEach(func() {
nonce = bytes.Repeat([]byte{'e'}, 32) nonce = bytes.Repeat([]byte{'e'}, 32)
packer.cryptoSetup.(*mockCryptoSetup).divNonce = nonce packer.cryptoSetup.(*mockCryptoSetup).divNonce = nonce
f := &frames.StreamFrame{
StreamID: 1,
Data: []byte{0xDE, 0xCA, 0xFB, 0xAD},
}
streamFramer.AddFrameForRetransmission(f)
}) })
It("doesn't include a div nonce, when sending a packet with initial encryption", func() { It("doesn't include a div nonce, when sending a packet with initial encryption", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionUnencrypted ph := packer.getPublicHeader(1, protocol.EncryptionUnencrypted)
p, err := packer.PackPacket(nil, []frames.Frame{}, 0) Expect(ph.DiversificationNonce).To(BeEmpty())
Expect(err).ToNot(HaveOccurred())
Expect(p.raw).ToNot(ContainSubstring(string(nonce)))
}) })
It("includes a div nonce, when sending a packet with secure encryption", func() { It("includes a div nonce, when sending a packet with secure encryption", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionSecure ph := packer.getPublicHeader(1, protocol.EncryptionSecure)
p, err := packer.PackPacket(nil, []frames.Frame{}, 0) Expect(ph.DiversificationNonce).To(Equal(nonce))
Expect(err).ToNot(HaveOccurred())
Expect(p.raw).To(ContainSubstring(string(nonce)))
}) })
It("doesn't include a div nonce, when sending a packet with forward-secure encryption", func() { It("doesn't include a div nonce, when sending a packet with forward-secure encryption", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionUnencrypted ph := packer.getPublicHeader(1, protocol.EncryptionForwardSecure)
p, err := packer.PackPacket(nil, []frames.Frame{}, 0) Expect(ph.DiversificationNonce).To(BeEmpty())
Expect(err).ToNot(HaveOccurred())
Expect(p.raw).ToNot(ContainSubstring(string(nonce)))
}) })
It("doesn't send a div nonce as a client", func() { It("doesn't send a div nonce as a client", func() {
packer.perspective = protocol.PerspectiveClient packer.perspective = protocol.PerspectiveClient
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionSecure ph := packer.getPublicHeader(1, protocol.EncryptionSecure)
p, err := packer.PackPacket(nil, []frames.Frame{}, 0) Expect(ph.DiversificationNonce).To(BeEmpty())
Expect(err).ToNot(HaveOccurred())
Expect(p.raw).ToNot(ContainSubstring(string(nonce)))
}) })
}) })
@ -260,10 +257,10 @@ var _ = Describe("Packet packer", func() {
controlFrames = append(controlFrames, f) controlFrames = append(controlFrames, f)
} }
packer.controlFrames = controlFrames packer.controlFrames = controlFrames
payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(maxFramesPerPacket)) Expect(payloadFrames).To(HaveLen(maxFramesPerPacket))
payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(BeEmpty()) Expect(payloadFrames).To(BeEmpty())
}) })
@ -279,10 +276,10 @@ var _ = Describe("Packet packer", func() {
controlFrames = append(controlFrames, blockedFrame) controlFrames = append(controlFrames, blockedFrame)
} }
packer.controlFrames = controlFrames packer.controlFrames = controlFrames
payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(maxFramesPerPacket)) Expect(payloadFrames).To(HaveLen(maxFramesPerPacket))
payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize, false)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(10)) Expect(payloadFrames).To(HaveLen(10))
}) })
@ -316,11 +313,11 @@ var _ = Describe("Packet packer", func() {
maxStreamFrameDataLen := maxFrameSize - minLength maxStreamFrameDataLen := maxFrameSize - minLength
f.Data = bytes.Repeat([]byte{'f'}, int(maxStreamFrameDataLen)) f.Data = bytes.Repeat([]byte{'f'}, int(maxStreamFrameDataLen))
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(1)) Expect(payloadFrames).To(HaveLen(1))
Expect(payloadFrames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse()) Expect(payloadFrames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse())
payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(BeEmpty()) Expect(payloadFrames).To(BeEmpty())
}) })
@ -350,18 +347,6 @@ var _ = Describe("Packet packer", func() {
Expect(p.frames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse()) Expect(p.frames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse())
}) })
It("packs smaller packets when it is not yet forward-secure", func() {
packer.isForwardSecure = false
f := &frames.StreamFrame{
StreamID: 3,
Data: bytes.Repeat([]byte{'f'}, int(protocol.MaxPacketSize)),
}
streamFramer.AddFrameForRetransmission(f)
p, err := packer.PackPacket(nil, nil, 0)
Expect(err).ToNot(HaveOccurred())
Expect(p.raw).To(HaveLen(int(protocol.MaxPacketSize - protocol.NonForwardSecurePacketSizeReduction)))
})
It("packs multiple small stream frames into single packet", func() { It("packs multiple small stream frames into single packet", func() {
f1 := &frames.StreamFrame{ f1 := &frames.StreamFrame{
StreamID: 5, StreamID: 5,
@ -403,17 +388,17 @@ var _ = Describe("Packet packer", func() {
maxStreamFrameDataLen := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLen - minLength maxStreamFrameDataLen := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLen - minLength
f.Data = bytes.Repeat([]byte{'f'}, int(maxStreamFrameDataLen)+200) f.Data = bytes.Repeat([]byte{'f'}, int(maxStreamFrameDataLen)+200)
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(1)) Expect(payloadFrames).To(HaveLen(1))
Expect(payloadFrames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse()) Expect(payloadFrames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse())
Expect(payloadFrames[0].(*frames.StreamFrame).Data).To(HaveLen(int(maxStreamFrameDataLen))) Expect(payloadFrames[0].(*frames.StreamFrame).Data).To(HaveLen(int(maxStreamFrameDataLen)))
payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(1)) Expect(payloadFrames).To(HaveLen(1))
Expect(payloadFrames[0].(*frames.StreamFrame).Data).To(HaveLen(200)) Expect(payloadFrames[0].(*frames.StreamFrame).Data).To(HaveLen(200))
Expect(payloadFrames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse()) Expect(payloadFrames[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse())
payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(BeEmpty()) Expect(payloadFrames).To(BeEmpty())
}) })
@ -476,10 +461,10 @@ var _ = Describe("Packet packer", func() {
f.Data = bytes.Repeat([]byte{'f'}, int(protocol.MaxFrameAndPublicHeaderSize-publicHeaderLen-minLength+2)) // + 2 since MinceLength is 1 bigger than the actual StreamFrame header f.Data = bytes.Repeat([]byte{'f'}, int(protocol.MaxFrameAndPublicHeaderSize-publicHeaderLen-minLength+2)) // + 2 since MinceLength is 1 bigger than the actual StreamFrame header
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err := packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(1)) Expect(payloadFrames).To(HaveLen(1))
payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize) payloadFrames, err = packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(payloadFrames).To(HaveLen(1)) Expect(payloadFrames).To(HaveLen(1))
}) })
@ -491,11 +476,13 @@ var _ = Describe("Packet packer", func() {
Data: []byte("foobar"), Data: []byte("foobar"),
} }
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
_, err := packer.PackPacket(nil, nil, 0) p, err := packer.PackPacket(nil, nil, 0)
Expect(err).To(MatchError(qerr.AttemptToSendUnencryptedStreamData)) Expect(err).NotTo(HaveOccurred())
Expect(p).To(BeNil())
}) })
It("sends encrypted, non forward-secure, stream data on a data stream", func() { It("sends non forward-secure data as the client", func() {
packer.perspective = protocol.PerspectiveClient
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionSecure packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionSecure
f := &frames.StreamFrame{ f := &frames.StreamFrame{
StreamID: 5, StreamID: 5,
@ -508,30 +495,46 @@ var _ = Describe("Packet packer", func() {
Expect(p.frames[0]).To(Equal(f)) Expect(p.frames[0]).To(Equal(f))
}) })
It("sends unencrypted stream data on the crypto stream", func() { It("does not send non forward-secure data as the server", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionUnencrypted packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionSecure
f := &frames.StreamFrame{ f := &frames.StreamFrame{
StreamID: 1, StreamID: 5,
Data: []byte("foobar"), Data: []byte("foobar"),
} }
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
p, err := packer.PackPacket(nil, nil, 0) p, err := packer.PackPacket(nil, nil, 0)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(p).To(BeNil())
})
It("sends unencrypted stream data on the crypto stream", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSealCrypto = protocol.EncryptionUnencrypted
cryptoStream.dataForWriting = []byte("foobar")
p, err := packer.PackPacket(nil, nil, 0)
Expect(err).ToNot(HaveOccurred())
Expect(p.encryptionLevel).To(Equal(protocol.EncryptionUnencrypted)) Expect(p.encryptionLevel).To(Equal(protocol.EncryptionUnencrypted))
Expect(p.frames[0]).To(Equal(f)) Expect(p.frames).To(HaveLen(1))
Expect(p.frames[0]).To(Equal(&frames.StreamFrame{StreamID: 1, Data: []byte("foobar")}))
}) })
It("sends encrypted stream data on the crypto stream", func() { It("sends encrypted stream data on the crypto stream", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionSecure packer.cryptoSetup.(*mockCryptoSetup).encLevelSealCrypto = protocol.EncryptionSecure
f := &frames.StreamFrame{ cryptoStream.dataForWriting = []byte("foobar")
StreamID: 1,
Data: []byte("foobar"),
}
streamFramer.AddFrameForRetransmission(f)
p, err := packer.PackPacket(nil, nil, 0) p, err := packer.PackPacket(nil, nil, 0)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(p.encryptionLevel).To(Equal(protocol.EncryptionSecure)) Expect(p.encryptionLevel).To(Equal(protocol.EncryptionSecure))
Expect(p.frames[0]).To(Equal(f)) Expect(p.frames).To(HaveLen(1))
Expect(p.frames[0]).To(Equal(&frames.StreamFrame{StreamID: 1, Data: []byte("foobar")}))
})
It("does not pack stream frames if not allowed", func() {
packer.cryptoSetup.(*mockCryptoSetup).encLevelSeal = protocol.EncryptionUnencrypted
packer.QueueControlFrameForNextPacket(&frames.AckFrame{})
streamFramer.AddFrameForRetransmission(&frames.StreamFrame{StreamID: 3, Data: []byte("foobar")})
p, err := packer.PackPacket(nil, nil, 0)
Expect(err).ToNot(HaveOccurred())
Expect(p.frames).To(HaveLen(1))
Expect(func() { _ = p.frames[0].(*frames.AckFrame) }).NotTo(Panic())
}) })
}) })
@ -544,7 +547,7 @@ var _ = Describe("Packet packer", func() {
Data: bytes.Repeat([]byte{'f'}, length), Data: bytes.Repeat([]byte{'f'}, length),
} }
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
_, err := packer.composeNextPacket(nil, maxFrameSize) _, err := packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(packer.controlFrames[0]).To(Equal(&frames.BlockedFrame{StreamID: 5})) Expect(packer.controlFrames[0]).To(Equal(&frames.BlockedFrame{StreamID: 5}))
}) })
@ -557,7 +560,7 @@ var _ = Describe("Packet packer", func() {
Data: bytes.Repeat([]byte{'f'}, length), Data: bytes.Repeat([]byte{'f'}, length),
} }
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
p, err := packer.composeNextPacket(nil, maxFrameSize) p, err := packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(p).To(HaveLen(1)) Expect(p).To(HaveLen(1))
Expect(p[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse()) Expect(p[0].(*frames.StreamFrame).DataLenPresent).To(BeFalse())
@ -570,7 +573,7 @@ var _ = Describe("Packet packer", func() {
Data: []byte("foobar"), Data: []byte("foobar"),
} }
streamFramer.AddFrameForRetransmission(f) streamFramer.AddFrameForRetransmission(f)
_, err := packer.composeNextPacket(nil, maxFrameSize) _, err := packer.composeNextPacket(nil, maxFrameSize, true)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(packer.controlFrames[0]).To(Equal(&frames.BlockedFrame{StreamID: 0})) Expect(packer.controlFrames[0]).To(Equal(&frames.BlockedFrame{StreamID: 0}))
}) })

View file

@ -219,7 +219,8 @@ func (s *session) setup(
return nil, nil, err return nil, nil, err
} }
s.packer = newPacketPacker(s.connectionID, s.cryptoSetup, s.connectionParameters, s.streamFramer, s.perspective, s.version) s.packer = newPacketPacker(s.connectionID, s.cryptoSetup, s.connectionParameters, s.streamFramer,
s.perspective, s.version)
s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version} s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version}
return s, handshakeChan, nil return s, handshakeChan, nil
@ -278,9 +279,6 @@ runLoop:
close(s.handshakeChan) close(s.handshakeChan)
close(s.handshakeCompleteChan) close(s.handshakeCompleteChan)
} else { } else {
if l == protocol.EncryptionForwardSecure {
s.packer.SetForwardSecure()
}
s.tryDecryptingQueuedPackets() s.tryDecryptingQueuedPackets()
s.handshakeChan <- handshakeEvent{encLevel: l} s.handshakeChan <- handshakeEvent{encLevel: l}
} }

View file

@ -914,7 +914,7 @@ var _ = Describe("Session", func() {
It("informs the SentPacketHandler about sent packets", func() { It("informs the SentPacketHandler about sent packets", func() {
sess.sentPacketHandler = newMockSentPacketHandler() sess.sentPacketHandler = newMockSentPacketHandler()
sess.packer.packetNumberGenerator.next = 0x1337 + 9 sess.packer.packetNumberGenerator.next = 0x1337 + 9
sess.packer.cryptoSetup = &mockCryptoSetup{encLevelSeal: protocol.EncryptionSecure} sess.packer.cryptoSetup = &mockCryptoSetup{encLevelSeal: protocol.EncryptionForwardSecure}
f := &frames.StreamFrame{ f := &frames.StreamFrame{
StreamID: 5, StreamID: 5,
@ -929,7 +929,7 @@ var _ = Describe("Session", func() {
sentPackets := sess.sentPacketHandler.(*mockSentPacketHandler).sentPackets sentPackets := sess.sentPacketHandler.(*mockSentPacketHandler).sentPackets
Expect(sentPackets).To(HaveLen(1)) Expect(sentPackets).To(HaveLen(1))
Expect(sentPackets[0].Frames).To(ContainElement(f)) Expect(sentPackets[0].Frames).To(ContainElement(f))
Expect(sentPackets[0].EncryptionLevel).To(Equal(protocol.EncryptionSecure)) Expect(sentPackets[0].EncryptionLevel).To(Equal(protocol.EncryptionForwardSecure))
Expect(sentPackets[0].Length).To(BeEquivalentTo(len(mconn.written[0]))) Expect(sentPackets[0].Length).To(BeEquivalentTo(len(mconn.written[0])))
}) })
}) })
@ -994,10 +994,6 @@ var _ = Describe("Session", func() {
}) })
Context("for packets after the handshake", func() { Context("for packets after the handshake", func() {
BeforeEach(func() {
sess.packer.SetForwardSecure()
})
It("sends a StreamFrame from a packet queued for retransmission", func() { It("sends a StreamFrame from a packet queued for retransmission", func() {
f := frames.StreamFrame{ f := frames.StreamFrame{
StreamID: 0x5, StreamID: 0x5,
@ -1252,16 +1248,6 @@ var _ = Describe("Session", func() {
}) })
}) })
It("tells the packetPacker when forward-secure encryption is used", func(done Done) {
go sess.run()
aeadChanged <- protocol.EncryptionSecure
Consistently(func() bool { return sess.packer.isForwardSecure }).Should(BeFalse())
aeadChanged <- protocol.EncryptionForwardSecure
Eventually(func() bool { return sess.packer.isForwardSecure }).Should(BeTrue())
Expect(sess.Close(nil)).To(Succeed())
close(done)
})
It("closes when crypto stream errors", func() { It("closes when crypto stream errors", func() {
testErr := errors.New("crypto setup error") testErr := errors.New("crypto setup error")
cryptoSetup.handleErr = testErr cryptoSetup.handleErr = testErr

View file

@ -45,6 +45,28 @@ func (f *streamFramer) HasFramesForRetransmission() bool {
return len(f.retransmissionQueue) > 0 return len(f.retransmissionQueue) > 0
} }
func (f *streamFramer) HasCryptoStreamFrame() bool {
// TODO(#657): Flow control
cs, _ := f.streamsMap.GetOrOpenStream(1)
return cs.lenOfDataForWriting() > 0
}
// TODO(lclemente): This is somewhat duplicate with the normal path for generating frames.
// TODO(#657): Flow control
func (f *streamFramer) PopCryptoStreamFrame(maxLen protocol.ByteCount) *frames.StreamFrame {
if !f.HasCryptoStreamFrame() {
return nil
}
cs, _ := f.streamsMap.GetOrOpenStream(1)
frame := &frames.StreamFrame{
StreamID: 1,
Offset: cs.writeOffset,
}
frameHeaderBytes, _ := frame.MinLength(protocol.VersionWhatever) // can never error
frame.Data = cs.getDataForWriting(maxLen - frameHeaderBytes)
return frame
}
func (f *streamFramer) maybePopFramesForRetransmission(maxLen protocol.ByteCount) (res []*frames.StreamFrame, currentLen protocol.ByteCount) { func (f *streamFramer) maybePopFramesForRetransmission(maxLen protocol.ByteCount) (res []*frames.StreamFrame, currentLen protocol.ByteCount) {
for len(f.retransmissionQueue) > 0 { for len(f.retransmissionQueue) > 0 {
frame := f.retransmissionQueue[0] frame := f.retransmissionQueue[0]
@ -76,7 +98,7 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
var currentLen protocol.ByteCount var currentLen protocol.ByteCount
fn := func(s *stream) (bool, error) { fn := func(s *stream) (bool, error) {
if s == nil { if s == nil || s.streamID == 1 /* crypto stream is handled separately */ {
return true, nil return true, nil
} }