Subject: Payload length 0

From: Marten Seemann <[email-masked]>
Date: Fri, 18 May 2018 14:08:00 +0900

Jana asked me to raise this issue on the list, after we already had a bit
of discussion in https://github.com/quicwg/base-drafts/pull/1301.

The proposal is to make a payload length of 0 a special value, indicating
that the packet is not a coalesced packet, i.e. that the whole payload of
the UDP packet is the QUIC packet. This would eliminate an invalid value of
the payload length (there are no empty packets), save one byte for packet
lengths where varint encoding would result in a two byte number, and
apparently also simplify (some) implementations.

Kazuho argued creating two versions of each Long Header type (one with and
one without a payload length) is the better solution, since all values
below the AEAD tag length + 1 are invalid values anyway, and it would save
one more byte.

We should make a decision if and what we want to do about this.

---

From: Martin Thomson <[email-masked]>
Date: Fri, 18 May 2018 15:34:12 +1000

Having just implemented this (and gotten it wrong once), I don't want more
special cases.  Both of these options need extra code.  As Kazuho points
out, filling in a two octet length is trivial.

It's true that a length of 0 is invalid, but so is 1 through 16.

Yes, this saves an octet, on about 4 packets per connection in the common
case, more like 2 if you actually take advantage of compound packets.
On Fri, May 18, 2018 at 3:08 PM Marten Seemann <[email-masked]>

> Kazuho argued creating two versions of each Long Header type (one with
and one without a payload length) is the better solution, since all values
below the AEAD tag length + 1 are invalid values anyway, and it would save
one more byte.

---

From: Ian Swett <[email-masked]>
Date: Fri, 18 May 2018 08:06:01 -0400

I would also prefer to not do either of these, because I think it adds
complexity and the byte savings are tiny.

---

From: Dmitri Tikhonov <[email-masked]>
Date: Fri, 18 May 2018 09:44:01 -0400

I agree with Martin and Ian.  We should keep the payload length field
and its value should be the actual length of the payload.

In addition to being simple, this allows some flexibility when packet
generattion is far away (in time or code) from actually sending a
packet.  That is to say, it is easier not to have to make the decision
which version of the payload length value to use when the packet is
created.

  - Dmitri.

---

From: "Deval, Manasi" <[email-masked]>
Date: Fri, 18 May 2018 14:05:49 +0000

Agree with keeping payload length in the header.

-----Original Message-----
From: QUIC [mailto:[email-masked]] On Behalf Of Dmitri Tikhonov
Sent: Friday, May 18, 2018 6:44 AM
To: Ian Swett <[email-masked]>
Cc: Marten Seemann <[email-masked]>; IETF QUIC WG <[email-masked]>; Martin Thomson <[email-masked]>
Subject: Re: Payload length 0

I agree with Martin and Ian.  We should keep the payload length field and its value should be the actual length of the payload.

In addition to being simple, this allows some flexibility when packet generattion is far away (in time or code) from actually sending a packet.  That is to say, it is easier not to have to make the decision which version of the payload length value to use when the packet is created.

  - Dmitri.

On Fri, May 18, 2018 at 08:06:01AM -0400, Ian Swett wrote:
> > Having just implemented this (and gotten it wrong once), I don't 
> > want more special cases.  Both of these options need extra code.  As 
> > Kazuho points out, filling in a two octet length is trivial.
> >
> > Yes, this saves an octet, on about 4 packets per connection in the 
> > common case, more like 2 if you actually take advantage of compound packets.
> > that the packet is not a coalesced packet, i.e. that the whole 
> > payload of the UDP packet is the QUIC packet. This would eliminate 
> > an invalid value of the payload length (there are no empty packets), 
> > save one byte for packet lengths where varint encoding would result 
> > in a two byte number, and apparently also simplify (some) implementations.
> >
> > and one without a payload length) is the better solution, since all 
> > values below the AEAD tag length + 1 are invalid values anyway, and 
> > it would save one more byte.
> >

---

From: Jana Iyengar <[email-masked]>
Date: Sat, 19 May 2018 17:50:16 -0700

I don't have a strong preference, but a weak one: It seems silly to have a
length field in non-coalesced packets, and non-coalesced packets will be
the common case.

There may be a slightly more compelling reason though. I've been thinking
about optimizing loss recovery for coalesced packets, and I keep running up
against the possibility that a future middlebox might split coalesced QUIC
packets, if it is allowed. I have been thinking about future-proofing
coalesced packets from getting split by such middleboxes (as they do for
TCP), and it occurs to me that a special value of 0 could be used as this
signal. If length is 0, then the packet is coalesced, and otherwise not.
This forces a middlebox to forward coalesced or non-coalesced packets as
they are, without any re-packetization shenanigans.

If folks agree that there's value in this signal, length of 0 may be a neat
way to get it.

On Fri, May 18, 2018 at 7:05 AM, Deval, Manasi <[email-masked]>
wrote:

> Cc: Marten Seemann <[email-masked]>; IETF QUIC WG <[email-masked]>;
> Martin Thomson <[email-masked]>
> I agree with Martin and Ian.  We should keep the payload length field and
> its value should be the actual length of the payload.
>
> generattion is far away (in time or code) from actually sending a packet.
> That is to say, it is easier not to have to make the decision which version
> of the payload length value to use when the packet is created.
>
>   - Dmitri.
>

---

From: Christian Huitema <[email-masked]>
Date: Sat, 19 May 2018 18:06:40 -0700

On 5/19/2018 5:50 PM, Jana Iyengar wrote:

> There may be a slightly more compelling reason though. I've been
> thinking about optimizing loss recovery for coalesced packets, and I
> keep running up against the possibility that a future middlebox might
> split coalesced QUIC packets, if it is allowed. I have been thinking
> about future-proofing coalesced packets from getting split by such
> middleboxes (as they do for TCP), and it occurs to me that a special
> value of 0 could be used as this signal. If length is 0, then the
> packet is coalesced, and otherwise not. This forces a middlebox to
> forward coalesced or non-coalesced packets as they are, without any
> re-packetization shenanigans.

The only way to prevent middlebox from hacking some part of the protocol
is to use encryption. Any clear text hack will only be a slight road
bump for the middle-box hackers.

For example, if we coalesce a CI and a 0-RTT packet, we could have the
zero RTT encryption depend on the presence of the previous packet.

-- Christian Huitema

---

From: Jana Iyengar <[email-masked]>
Date: Sat, 19 May 2018 18:16:06 -0700

> bump for the middle-box hackers.

Agreed, though I'll note that authenticating may be enough in some cases,
encrypting may not be necessary.

> zero RTT encryption depend on the presence of the previous packet.

What I'm suggesting is that the length field, which is part of the
authenticated header, include this signal as zero, or non-zero. I think
this may be one interpretation of what you're saying: the header field,
which is part of the AEAD hash, encodes the presence of another packet.

---

From: Christian Huitema <[email-masked]>
Date: Sat, 19 May 2018 18:37:49 -0700

On 5/19/2018 6:16 PM, Jana Iyengar wrote:

> Agreed, though I'll note that authenticating may be enough in some
> cases, encrypting may not be necessary.
>
> authenticated header, include this signal as zero, or non-zero. I
> think this may be one interpretation of what you're saying: the header
> field, which is part of the AEAD hash, encodes the presence of another
> packet.

Yes, something like that would work. Maybe a flag in the first octet,
"is coalesced".

Note that, in the plausible CI + 0RTT coalescing, splitting the CI won't
work. It will be too short, and thus rejected by the server.

-- Christian Huitema

---

From: Martin Thomson <[email-masked]>
Date: Sun, 20 May 2018 17:14:59 +1000

It only works to ensure that the last packet remains the last packet.  That
doesn't seem like an actual defense against splitting.
On Sun, May 20, 2018 at 11:37 AM Christian Huitema <[email-masked]>

> Yes, something like that would work. Maybe a flag in the first octet, "is
coalesced".

---

From: Jana Iyengar <[email-masked]>
Date: Sun, 20 May 2018 10:44:33 -0700

Just to be clear about what I'm suggesting:

Packets that are coalesced in a UDP datagram have their length fields set
to the packet length. Packets that are not coalesced set the packet length
to zero.
A receiver that sees a non-zero packet length field in a long header checks
if this packet is coalesced. Similarly, a packet that is received with a
zero in the packet length field must be not coalesced.

I believe this protects from splitting.

CFIN+1RTT packets can also be coalesced in addition to CI+0RTT.

---

From: Christian Huitema <[email-masked]>
Date: Sun, 20 May 2018 11:00:11 -0700

> doesn't seem like an actual defense against splitting.

I have been thinking of the middle-box hacks that could interfere with
packet coalescing, trying to build a threat model. I am not sure I can't
come with convincing attacks, or rather with convincing attacks that we
can defend against. For me the main coalescing scenarios are:

1) Client Initial (Client Hello) + 0Rtt.

2) Server Handshake (first flight) + 1Rtt.

3) Client Handshake (second flight) + 1Rtt

What would be the motivation for splitting? In the CI+0-RTT case, the
middlebox designer might have heard that 0Rtt is insecure, and might
sell blocking 0RTT as a feature. It might want to pass the CI and block
the 0Rtt. This can be done in many ways. Flipping a couple bits in the
0Rtt payload would achieve that -- decryption would fail, and the 0Rtt
will be ignored. Or, unwrap the coalesced packet, decrypt the CI using
the well known key, add padding to reach the min size, and reencrypt
using the well known key. Tweaking the long header is not going to fix
either of these hacks.

In the Server Handshake + 1Rtt case, the motivation might be similar:
prevent 0.5Rtt transmission because it is arguably insecure. Again, this
can be achieved by flipping bits in the 1Rtt payload to cause a
decryption error, or unwrapping and reformatting the handshake packet.
Since the handshake is only "protected" by a well known key, this is
still possible, even if we added some kind of coalescing indication in
the short header of the 1Rtt data.

In the Client Handshake + 1Rtt case, I fail to find a motivation. But
evil middlebox designers could invent something. Again, if the goal is
to remove the 1Rtt packet, tweaking the headers of that packet won't help.

If we did want to remove the attack, we would have to protect the
coalescing indication with a key that is unknown to the middlebox. That
probably requires an encrypted extension to the client hello, server
hello or finished messages. we could do that, but I wonder whether
that's worth the effort.

-- Christian Huitema

---

From: Martin Thomson <[email-masked]>
Date: Fri, 25 May 2018 14:06:10 +1000

It seems like the discussion has settled down.

For those advocating for 0 being special, are you happy to keep things as
they are?
On Fri, May 18, 2018 at 3:08 PM Marten Seemann <[email-masked]>

---

From: Jana Iyengar <[email-masked]>
Date: Fri, 25 May 2018 15:50:56 -0700

I'm fine with having 0 not be special. Marten and Lars had stronger
opinions, so they should speak up.

---

From: Marten Seemann <[email-masked]>
Date: Sat, 26 May 2018 08:20:21 +0800

Works for me.

---

From: "Eggert, Lars" <[email-masked]>
Date: Sat, 26 May 2018 07:38:19 +0000

If we make the plen field fixed (which I think we just did to fix the issue with coalesced packets) I'm fine.

Lars

> On 2018-5-26, at 2:20, Marten Seemann <[email-masked]> wrote:
> 
> Works for me.
> 
> I'm fine with having 0 not be special. Marten and Lars had stronger opinions, so they should speak up.
> 
> On Thu, May 24, 2018 at 9:06 PM, Martin Thomson <[email-masked]> wrote: