Re: [TLS] Application layer interactions and API guidance

Kyle Rose <> Wed, 12 October 2016 01:42 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 9834D1293E1 for <>; Tue, 11 Oct 2016 18:42:00 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2
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, HTML_MESSAGE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (1024-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id 627EjMTdvIgB for <>; Tue, 11 Oct 2016 18:41:58 -0700 (PDT)
Received: from ( [IPv6:2607:f8b0:400d:c09::229]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id E4743124281 for <>; Tue, 11 Oct 2016 18:41:56 -0700 (PDT)
Received: by with SMTP id o68so58717563qkf.3 for <>; Tue, 11 Oct 2016 18:41:56 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=13nSEfZX+9Fa7HJoJOYjH7VicUGWUd6plA6e06sGrXk=; b=QPYSFOYEJyA/RbMTOIbyPzmznZGjUkfVa33DDetO+UZFLIuQQ0iWgl7dBmlseFlbd4 R+orcapnCVC9GshHq1Y1tQeWr+EMAjtu5ositlpiN2V7M6c0NW/UPO0npDl6u3hPs6uq A62bV75lX/xy3jUL+ZwxBPq5qbm1XiKoPUuZQ=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=13nSEfZX+9Fa7HJoJOYjH7VicUGWUd6plA6e06sGrXk=; b=DVlsNyzDPf+WOBSogTdxih6uDyhLYZu2oePfUTY9yQ4zL34Axc3gxIrHXUCchSPvI7 sxwOhgaVKESU+kVhUPKR4PYfQppuNyMEuL+tv1BMWs6UCOKDb8Ie4dnAT+NJuVJbfGMr UpCfg/WujuRHB/7sAovgYZxydptVj73C0RmnUSBZfY9C+hvh3eclYo2ynQqYoUc3Oa+V Xy5ff3QWxfYpXspSB4Ui6Qn3MGYNqGBEKhs6ZWsVYvVo9CUt6e7QgFnOHYwWHLwh1fTd OOZam2K6DFOcxJKV6VCjg3Us6xestd78nZdrSE4c9XCR09oClFYb5EqT2N/atF8pfxd3 OMDA==
X-Gm-Message-State: AA6/9RnLV5wyWk6LQ0CLtVLIdBxrZxxhSOHfUfYIanOJ7Lw4+XmtLodaE7NHN6nqA1nVaj/2GZxzlps9bCmBmw==
X-Received: by with SMTP id l64mr7117706qkd.21.1476236516132; Tue, 11 Oct 2016 18:41:56 -0700 (PDT)
MIME-Version: 1.0
Received: by with HTTP; Tue, 11 Oct 2016 18:41:55 -0700 (PDT)
X-Originating-IP: [2001:470:1f07:121:7cdd:60af:8a49:c126]
In-Reply-To: <>
References: <> <> <> <> <> <> <> <> <> <> <>
From: Kyle Rose <>
Date: Tue, 11 Oct 2016 21:41:55 -0400
Message-ID: <>
To: Martin Thomson <>
Content-Type: multipart/alternative; boundary=94eb2c072edc262482053ea1196c
Archived-At: <>
Cc: "" <>
Subject: Re: [TLS] Application layer interactions and API guidance
X-Mailman-Version: 2.1.17
Precedence: list
List-Id: "This is the mailing list for the Transport Layer Security working group of the IETF." <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Wed, 12 Oct 2016 01:42:00 -0000

> The 0-RTT API in NSS allows a server to detect this transition.  The
> problem that I think David was referring to is that the specific
> instant of the transition is lost when the multiple layers of stack
> that sit on top of TLS get involved.

To David's second paragraph, if we eventually authenticate the early data
as strongly as 1-RTT data, then there is no problem with long requests.
I.e., if the client starts a long PUT request that doesn't finish until
after the handshake is done, then the connection could be broken by the
server stack mid-request if it is able to figure out that the early data
was replayed. It appears this will be the case because the handshake
context for 0-RTT includes the ClientHello, which includes the early data,
so the client {Finished} will cover it. (Not clear on the value of 0-RTT to
long PUT requests, but you provide a more likely example below.)

If an HTTP client sends a request that relies on HPACK state that was
> established during 0-RTT, is it a 0-RTT request?  I'm going to go with
> probably not.

For the above reason, the HPACK state should be strongly authenticated by
this point, at which point it's no longer 0-RTT data.

Since the authentication status of early data may vary over the course of
the connection from "unknown/possibly replayed" to either "replayed" or
"authentic", maybe we should classify it by its status at the time we go to
use it. Which suggests the following terrible API for the server:

read(max) will return either a string of fully-authenticated data up to max
bytes, or EAGAIN if none is available (with possibly some side-band
mechanism for indicating that data of unknown authenticity is available)

read_sketchy(max) will return possibly-sketchy data up to max bytes, or 0
if there is no more such data (at which point the caller should switch to
regular read), or EAGAIN if the entire ClientHello hasn't yet been received.

If the server doesn't care about early data, or waits long enough for the
handshake to complete, all data will have been elevated to authentic or the
connection broken, depending on what happened with client {Finished}.

On the client side, one option is for the early data to be specified prior
to or alongside handshake initiation, with some indication by the stack of
whether it was written or not. (I suggest all-or-none.) This precludes
question on the part of the client as to which data might have been sent
0-RTT and which must have been sent 1-RTT.

One of the nice things about the above API is that a simple server wanting
to process early data ASAP can do the same thing every time:

poll for read
  r = read_sketchy()
  if r: do_something_with_early_data(r)
catch EAGAIN: noop
  r = read()
  if r: do_something(r)
  else: terminate_connection
catch EAGAIN: noop

Another nice thing is that at the moment you receive a single byte from
read() you know a priori that every byte of early data you processed was

Do we want to support the case in which 0-RTT failure means the client can
send entirely different data? If so, then the above isn't general enough,
but the client API could offer an option to say "don't resend this data if
0-RTT fails" with some flag set on this condition or (for event systems) a
callback registered to do something more interesting.

The above API also doesn't support the case in which the server wants to
treat 0-RTT data entirely different from 1-RTT data, which would suggest a
side-band/two channel API. Is this interesting to anyone? I'm not sure I
can see any use for purposely ignoring post-hoc authentication of early