Subject: [TLS] ALPS and TLS 1.3 half-RTT data

From: David Benjamin <[email-masked]>
Date: Thu, 3 Dec 2020 16:55:23 -0500

Hi TLS and HTTP friends,

At the last HTTPWG interim, there was a question of why one would want
something like ALPS (draft-vvv-tls-alps) for HTTP SETTINGS
(draft-vvv-httpbis-alps) over TLS 1.3 half-RTT data. I know we've also had
some discussion on this topic in the TLSWG as well. At the HTTP meeting,
folks suggested writing up what a half-RTT-based mechanism might look like,
so I put together an I-D below. I hope it helps clarify some of our
thinking.

(The I-D is not meant for adoption or publication or anything. I figured an
I-D was probably the most familiar format for folks.)

David

---------- Forwarded message ---------
From: <[email-masked]>
Date: Thu, Dec 3, 2020 at 4:22 PM
Subject: New Version Notification for
draft-davidben-tls-alps-half-rtt-00.txt
To: David Benjamin <[email-masked]>

A new version of I-D, draft-davidben-tls-alps-half-rtt-00.txt
has been successfully submitted by David Benjamin and posted to the
IETF repository.

Name:           draft-davidben-tls-alps-half-rtt
Revision:       00
Title:          Comparing ALPS and Half-RTT Data
Document date:  2020-12-03
Group:          Individual Submission
Pages:          11
URL:
https://www.ietf.org/archive/id/draft-davidben-tls-alps-half-rtt-00.txt
Status:
https://datatracker.ietf.org/doc/draft-davidben-tls-alps-half-rtt/
Html:
https://www.ietf.org/archive/id/draft-davidben-tls-alps-half-rtt-00.html
Htmlized:
https://tools.ietf.org/html/draft-davidben-tls-alps-half-rtt-00

Abstract:
   This document compares the Application Layer Protocols Settings
   extension with the half-RTT feature in TLS 1.3.

Please note that it may take a couple of minutes from the time of submission
until the htmlized version and diff are available at tools.ietf.org.

The IETF Secretariat

---

From: Cory Benfield <[email-masked]>
Date: Tue, 8 Dec 2020 08:47:28 +0000

On Thu, 3 Dec 2020 at 21:56, David Benjamin <[email-masked]> wrote:
>
> Hi TLS and HTTP friends,
>
> At the last HTTPWG interim, there was a question of why one would want something like ALPS (draft-vvv-tls-alps) for HTTP SETTINGS (draft-vvv-httpbis-alps) over TLS 1.3 half-RTT data. I know we've also had some discussion on this topic in the TLSWG as well. At the HTTP meeting, folks suggested writing up what a half-RTT-based mechanism might look like, so I put together an I-D below. I hope it helps clarify some of our thinking.
>
> (The I-D is not meant for adoption or publication or anything. I figured an I-D was probably the most familiar format for folks.)
>
> David

Thanks for producing this document David: I think I was one of the
folks who pushed for clarification in this area.

I think the document does a good job laying out the difficulties with
half-RTT data, but it didn't convince me that ALPS is easier for H2.

My biggest concerns are around the need to tightly couple the TLS and
application layer stacks. ALPN has been reasonably straightforward to
handle, being essentially a static byte sequence vended by the
application layer protocol. QUIC transport parameters are already
harder, but for things like H2 the state machines have to be
complicated by the addition of an essentially parallel I/O path. This
is because, unlike QUIC, H2 does not (and cannot) spec the requirement
for supporting the ALPS extension so the state machines need to
tolerate the possibility that they will supply the SETTINGS as
ALPS-data but then need to redeliver it in-band, which is fairly
unpleasant (doubly so for servers that may want to use multiple TLS
stacks, which now have to mitigate timing issues).

I think if ALPS were restricted to protocols that could mandate its
support then ALPS seems great. For H2 this seems unlikely to be
deployed in the long-tail which limits its usefulness, and tbh I think
brings more complexity than it's worth.

---

From: "Martin Thomson" <[email-masked]>
Date: Thu, 10 Dec 2020 17:00:21 +1100

Hi David,

Thanks for writing this up.  I think that it helped clarify things a little in my mind.

I had been separately thinking about the problem and did reach a conclusion.  I just needed time to write a response.

I think that there are two things you might want to separate here: what might we do to engender good protocol design hygiene, and what do we do about HTTP/2 and HTTP/3.

Like Cory, I didn't find this persuasive regarding HTTP/2.  It is even less persuasive for HTTP/3, where I have evidence that half-RTT data is being used successfully (this comes first hand: ngtcp2 hit a performance bug in my code).  The idea of creating a 0.5-RTT -> 1-RTT marker somehow is an odd idea, and one we've talked about maybe using in a new version of TLS, but I hardly see justification for that here.

A lot of your reluctance to use half-RTT seems to be based on the buggy IO pattern you identified.  Coupling send and receive flow control in the way you describe is - at least in my view - a defect in stacks rather than something to engineer a protocol around.  An endpoint that refuses to read until a write is complete invites deadlock in a great many situations in HTTP/2, and we even have specific text in RFC 7540, Section 5.2.2 (https://tools.ietf.org/html/rfc7540#section-5.2.2) that recommends against deferral of reads.

I realize that some applications don't work that way, but that doesn't mean that their TLS and HTTP/2 stacks need to be allowed to have the same bug.

Full disclosure, I think that NSS could have this bug under some usage patterns.  We don't buffer incoming data when we don't need it for the handshake.  But I'm not sure that we need perfect here.  This might come down to "well don't do that then", rather than the IETF embarking on a protocol engineering drill to fix these implementation issues.

What is somewhat odd about TLS 1.3 is the way that applications can write to the socket before the handshake is complete.  But reads are only possible afterwards.  That does create some problems for incoming data, but it is always a modest amount to buffer.  A new version of TLS might even allow clients to limit 0.5-RTT data, if this turns into a real problem.

In any case, I can see some advantages to something like ALPS for WebTransport.  The operational problems aren't any better, and I might not agree with you about the severity of the other things, but the protocol design hygiene aspects are pretty nice.  Thinking about QuicTransport, the ability to signal the requesting URL and origin to the server outside of the use of streams and other application data makes the whole protocol much easier to structure.  You no longer have to reserve streams or set aside control codepoints.

That said, if you need control codepoints or stream reservation for other reasons, the value is diminished somewhat.  After all, this is not magically reliable.  When you add stuff to the handshake you make the handshake bigger and more fragile.  If you really need this stuff, waiting on stream data to be retransmitted is no better or worse than waiting on the handshake.  

Indeed, binding to the handshake could be less performant in those cases where you are able to do some work ahead of receiving configuration.  You can't even buffer incoming data when the handshake is incomplete, but you could if you were waiting on receiving configuration that was sent on a stream.

On Fri, Dec 4, 2020, at 08:55, David Benjamin wrote:
> (draft-vvv-httpbis-alps) over TLS 1.3 half-RTT data. I know we've also 
> had some discussion on this topic in the TLSWG as well. At the HTTP 
> meeting, folks suggested writing up what a half-RTT-based mechanism 
> might look like, so I put together an I-D below. I hope it helps 
> clarify some of our thinking.
> 
> (The I-D is not meant for adoption or publication or anything. I 
> figured an I-D was probably the most familiar format for folks.)
> 
> David
> 
> Subject: New Version Notification for draft-davidben-tls-alps-half-rtt-00.txt

---

From: Victor Vasiliev <[email-masked]>
Date: Thu, 10 Dec 2020 22:44:14 -0500

Hi Cory,

I am not sure there is a big difference between ALPN and ALPS in that
regard.  ALPS is (or at least can be implemented as) "essentially a static
byte sequence vended by the application layer protocol".  Furthermore,
applications already have to vary their payloads dramatically depending on
signals from the TLS stack whenever they implement ALPN (by choosing, e.g.,
HTTP/1.1 vs HTTP/2).  From that standpoint, it seems natural for ALPS
handling to happen at the same or similar I/O points as ALPN handling.

I am confused by the "fairly unpleasant" part; given that the existing
implementations already can change settings in-band, this sounds like it's
just a matter of making the existing logic conditional.

On Tue, Dec 8, 2020 at 3:48 AM Cory Benfield <[email-masked]> wrote:

> > (The I-D is not meant for adoption or publication or anything. I figured
> an I-D was probably the most familiar format for folks.)
> >
> > David
>
> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

---

From: Cory Benfield <[email-masked]>
Date: Wed, 16 Dec 2020 10:16:35 +0000

On Fri, 11 Dec 2020 at 03:44, Victor Vasiliev <[email-masked]> wrote:
>
> Hi Cory,
>
> I am not sure there is a big difference between ALPN and ALPS in that regard.  ALPS is (or at least can be implemented as) "essentially a static byte sequence vended by the application layer protocol".  Furthermore, applications already have to vary their payloads dramatically depending on signals from the TLS stack whenever they implement ALPN (by choosing, e.g., HTTP/1.1 vs HTTP/2).  From that standpoint, it seems natural for ALPS handling to happen at the same or similar I/O points as ALPN handling.

The distinction here is that a HTTP/2 stack needs to know what the
peer sent for ALPS, which it never did for ALPN. That is, it was
possible to compose TLS and HTTP/2 entirely independently: the TLS
implementation accepted the static byte string from HTTP/2, and if the
ALPN it negotiated matched that string it had successfully negotiated
HTTP/2. I agree that applications needed to know what the ALPN
negotiation was, but HTTP/2 did not. You can observe this in OSS
stacks in the wild, where the HTTP/2 stack never sees the result of
the ALPN negotiation.

ALPS affects the HTTP/2 wire protocol: it is mandatory that the HTTP/2
stack behind the TLS implementation be actively told what the peer
presented in ALPS. This was not required with ALPN (H2 could assume it
was being driven based on successful ALPN negotiation of its H2 ALPN
token). While this is not novel for QUIC (see also Transport
Parameters), it is absolutely novel for H2.

> I am confused by the "fairly unpleasant" part; given that the existing implementations already can change settings in-band, this sounds like it's just a matter of making the existing logic conditional.

The two aren't the same, and the ALPS draft has so far skated around
this problem by not specifying how ALPS would actually work with
HTTP/2. In particular, ALPS must interact with the § 3.5 connection
preface in some way. The draft doesn't say how this would work, but
the logical design is that if ALPS is successfully used the connection
preface will be different (it won't bother to include SETTINGS
frames). This cannot help but require tighter coupling between H2 and
TLS, as the H2 stack must now be fed the ALPS data sent by the peer
before it can parse any bytes from that peer. This is simply not a
limitation we have today.

It is also different from making the existing logic conditional, as
presumably we wouldn't bother with SETTINGS ACKs for ALPS settings.
This is because a) the whole point of ALPS is that those settings are
well-ordered w.r.t. the rest of the protocol, obviating the need for
the ACK at all, and b) it would violate existing stack's assumptions
that SETTINGS ACKs can only be received in response to SETTINGS
frames. This requires a different path for the ALPS settings.

I want to stress: I don't think ALPS is a bad idea, I think it's a
good one! It clearly brings benefits for protocols that can require
its presence. If we want to mint a new ALPN token for HTTP/2 that also
mandates ALPS support I'm open to that, but frankly without it I don't
see that ALPS helps us much for HTTP/2.

---

From: Cory Benfield <[email-masked]>
Date: Fri, 18 Dec 2020 09:34:11 +0000

> limitation we have today.

David Benjamin kindly followed-up with me off-list to note that I
missed an ALPS draft that does express how ALPS maps into HTTP/2.
Happily, my guess about how ALPS would map into HTTP/2 matches the
document exactly, so the remainder of my criticism still applies.

While I'm here though, I'd like to add an additional point regarding
draft-vvv-httpbis-alps-00, which is that section 4 should be revised.
Specifically, section 4 mandates that any HTTP/2 endpoint that
supports ALPS MUST support SETTINGS_HPACK_ENABLE_STATIC_TABLES. The
word "support" is unclear here: do I merely have to know what the
setting is, or do I have to actually support the functionality? I can
only presume the latter, given that ALPS does not support any concept
of negotiation.

I ask because I think coupling these two features together is
unreasonable, and places an unnecessary burden on implementers. There
is also no reason to couple them together. This setting should be a
separate draft, and should require an appropriate "I support you
setting this to 0, but will not be setting it to 0 myself." setting
value. This allows peers that actually support this functionality to
indicate support for it, without requiring that it be implemented by
anyone adopting ALPS.