Re: [TLS] Separate APIs for 0-RTT

David Benjamin <davidben@chromium.org> Wed, 14 June 2017 19:55 UTC

Return-Path: <davidben@google.com>
X-Original-To: tls@ietfa.amsl.com
Delivered-To: tls@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 9DBCB129544 for <tls@ietfa.amsl.com>; Wed, 14 Jun 2017 12:55:39 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2
X-Spam-Level:
X-Spam-Status: No, score=-2 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=chromium.org
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yyJxqFiYk216 for <tls@ietfa.amsl.com>; Wed, 14 Jun 2017 12:55:36 -0700 (PDT)
Received: from mail-pg0-x22b.google.com (mail-pg0-x22b.google.com [IPv6:2607:f8b0:400e:c05::22b]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id C5FD312EB06 for <tls@ietf.org>; Wed, 14 Jun 2017 12:55:36 -0700 (PDT)
Received: by mail-pg0-x22b.google.com with SMTP id a70so4612818pge.3 for <tls@ietf.org>; Wed, 14 Jun 2017 12:55:36 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=+MBnlnPmoXc4G8RTEBdDlC0mIfRvF5DbO5aZNWQhVYU=; b=V0azzHYjGyFhPPtMICmfidM+bP3kzn2QAyhxSuLoRgeRLT2pN7DXjNcGpaK+aPmNm2 kHobQyFaUHvXYaWm6BPzb9sWMmy5UT9OV2Q3QJyzl2/A6otgJe/vlSp59lslAio6f7n1 0k4GXS6yVQFxCwl6kuiXlRdF1WNf2EqdW52uk=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=+MBnlnPmoXc4G8RTEBdDlC0mIfRvF5DbO5aZNWQhVYU=; b=S7IoUM17fBoxFGEpaqlHFWppV0fsCUr3gn+bXJnZIdU4s6doxdFlAe6Gp3/MCWpMSW eNnl5SnpdoZc5PbefIxTuK7bJLet6WZ2aTdlSGSh+lxAT8SWaFBkOdmV20wRTyhZhV7P G+6mFBOjWxQNdU1mP6MvQMYMa7dWqm4uTkEMBJmCBdkZZAKDDy4rzvVKITSbDJwDq/P6 Egeav94PAqUVtXIBYmGhokwR1JE8/tfY3dvn5c6dLX9INT0BV+LMJ2MLVjaB+r2o5gA5 MYrklJlJqu8weJGOofEJWw329WHyVv+HcenqAvlXN7iYr5II/suMLTsPOSKBxKL9fB+D 0kEQ==
X-Gm-Message-State: AKS2vOwPJ2Oxyiu0koeDHFGnnS72f2kXKtfZrXUG5/3T+iaZgSU9+VPx v57bYITLbhmSsSUWbEsc8vJJCUyBuL6eZBs=
X-Received: by 10.84.236.71 with SMTP id h7mr1830712pln.88.1497470136236; Wed, 14 Jun 2017 12:55:36 -0700 (PDT)
MIME-Version: 1.0
References: <CABcZeBMpeBhcKoJYuMwLyER0VBh+RtVr6amWMPos3CJipXYHcA@mail.gmail.com> <DM2PR21MB00916718A71749E5D2CB19C38CC20@DM2PR21MB0091.namprd21.prod.outlook.com> <CABcZeBO+Qprg4DTwNJrFU1PXDPyKbbdakMrF9fhe02jRL50cow@mail.gmail.com> <8e206c83-645f-6389-a7bd-ddd51e747ea2@akamai.com> <CAAF6GDfyqMndibTujY83_Xha2dZn7qvaCpZJw7xZ--b=-EOaYA@mail.gmail.com> <bf4506e7-13ce-ce7f-d20e-67a0d73c642a@akamai.com> <CAAF6GDePg9FL0JgzrWrTcrK7X=J0_fKjHVCj9EScvyQobJWTKA@mail.gmail.com> <20170613183536.GA12760@LK-Perkele-V2.elisa-laajakaista.fi> <63c8ac33-489c-0ace-d4ba-b960cd965281@akamai.com> <DM2PR21MB0091B8DC8780B4FA67464F0A8CC20@DM2PR21MB0091.namprd21.prod.outlook.com> <20170613205530.GB13223@LK-Perkele-V2.elisa-laajakaista.fi> <e5ab9945-054b-67bf-beef-9fce7a4a6f36@nic.cz>
In-Reply-To: <e5ab9945-054b-67bf-beef-9fce7a4a6f36@nic.cz>
From: David Benjamin <davidben@chromium.org>
Date: Wed, 14 Jun 2017 19:55:24 +0000
Message-ID: <CAF8qwaCuDk3oemXeKyEzzRgg2oCMA22qMBXQaL4YW3yWAeXUvA@mail.gmail.com>
To: Petr Špaček <petr.spacek@nic.cz>, tls@ietf.org
Content-Type: multipart/alternative; boundary="f403045fe2e48899970551f0efb4"
Archived-At: <https://mailarchive.ietf.org/arch/msg/tls/4cxbbuCwrIGMg2A50a8emQUTXE4>
Subject: Re: [TLS] Separate APIs for 0-RTT
X-BeenThere: tls@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: "This is the mailing list for the Transport Layer Security working group of the IETF." <tls.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/tls>, <mailto:tls-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/tls/>
List-Post: <mailto:tls@ietf.org>
List-Help: <mailto:tls-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/tls>, <mailto:tls-request@ietf.org?subject=subscribe>
X-List-Received-Date: Wed, 14 Jun 2017 19:55:39 -0000

On Wed, Jun 14, 2017 at 2:17 AM Petr Špaček <petr.spacek@nic.cz> wrote:

>
>
> On 13.6.2017 22:55, Ilari Liusvaara wrote:
> > On Tue, Jun 13, 2017 at 06:57:05PM +0000, Andrei Popov wrote:
> >> Regarding RFC language, I think we could be more specific:
> >>
> >>
> >>
> >> 1. A TLS implementation SHOULD/MUST only send 0-RTT application data if
> the application has explicitly opted in;
> >>
> >> 2. A TLS implementation SHOULD/MUST only accept 0-RTT application data
> if the application has explicitly opted in;
> >>
> >> 3. When delivering 0-RTT application data to the application, a TLS
> implementation SHOULD/MUST provide a way for the application to distinguish
> it from the rest of the application data.
> >
> > First of these has to be MUST, or you get problems like I outlined
> > earlier.
> >
> > And to implement checking for client only sending "safe" data, you need
> > the second and third.
>
> I support MUST for the three points above.
>

The third one is not practical as one moves up layers. Instead, I believe
we can get the same benefit with a simpler signal.

TLS fundamentally is a transformation from a vaguely TCP-like transport to
another vaguely TCP-like transport. Consider TLS records: TLS could have
decided record boundaries were meaningful and applications can use it in
their framing layers, but instead TLS exposes a byte stream, because it
intentionally looks like TCP.

Of course, 0-RTT unavoidably must stretch the “vaguely”. Suppose there is a
semantically meaningful difference between 0-RTT and 1-RTT data. I can see
why this is attractive. It moves the problem out of TLS. But this signal is
pointless if applications don’t use it. If everyone did the following, we
haven’t solved anything:

if (InEarlyData()) {
  return EarlyDataRead(...);
} else {
  return NormalRead(...);
}

So we must consider this signal’s uses. Consider HTTP/2. The goal may be to
tag requests as “0-RTT”, because we wish to reject 0-RTT POSTs or so.

What if the server receives data with the 0-RTT boundary spanning an HTTP/2
frame? Is that a 0-RTT request? 1-RTT? Invalid? If I’m parsing that, I have
to concatenate, and we’re back to that if/else strawman above. HTTP2 is
arguably an easy case. Maybe my protocol is a compressed stream. Carrying a
low-level byte boundary through layers of application data parsing and
processing is not practical.

We could say that the application profile should modify the protocol to
reject such cases. Now, we’re taking on complexity in every protocol
specification and parser.

It also brings complexity on the sender side. Perhaps I am halfway through
writing an HTTP/2 frame and, in parallel, I receive the ServerHello. We
moved 0-RTT data out of a ClientHello extension way back in draft -07 so
0-RTT data can be streamed while waiting for ServerHello. This is
especially useful for HTTP/2 where reads and writes flow in parallel. This
means the sender must synchronize with the TLS socket to delay the 1-RTT
transition.

Now suppose the TLS stack receives that atomic data and it doesn’t fit in
the 0-RTT send limit. That won’t work, so the sender must query the early
data size and send over 1-RTT if it doesn’t fit.

Now suppose this HTTP request takes multiple frames to send. One can send
multiple HEADERS frames in HTTP/2. That won’t work, so we actually need the
synchronization to cover the entire request. Maybe my request has a
response body. We need to cover that too, and we need to know the size for
send limit purposes.

Now suppose assembling the HTTP request takes an asynchronous step after
connection binding. Maybe I’m signing something for tokbind. Maybe I have
some weird browser extension API. In this worldview, all the while, the
HTTP/2 multiplexer must lock out all other requests and the client
Finished, even if the ServerHello has already come in. That last one is
particularly nasty if the server is delaying an already-sent request until
the 1-RTT point (cf.
https://www.ietf.org/mail-archive/web/tls/current/msg21486.html).

Perhaps I keep the request assembling logic, HTTP/2 multiplexers, and TLS
sockets in different threads or processes. Now this synchronization must
span all of these. As one adds layers, the complexity grows.

The root problem here is we’ve changed TLS’s core abstraction. One might
argue all this complexity is warranted for 0-RTT. We are trying to solve a
problem here. But I think we can solve it simpler:

Our problem is a server wishes not to process some HTTP requests (or other
protocol units) at 0-RTT and needs to detect this case. So check a boolean
signal for whether the connection has currently passed the 1-RTT point
before any unsafe processing. A “1-RTT request” will always return 1-RTT. A
“0-RTT request” will usually return 0-RTT, but if it spans the boundary or
the processing pipeline was just slow, perhaps we don’t query until after
the client Finished. That’s actually fine. We get the replay protection we
need out of the client Finished.

This solves our problem without the complexity. Two APIs or an explicit
boundary is one way to expose this boolean, but this boolean, unlike the
hard boundary, is much easier to carry across higher-level protocol layers,
and does not imply impractical sender constraints.

David