Re: [TLS] Application layer interactions and API guidance

Ilari Liusvaara <> Wed, 12 October 2016 08:11 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id BF5CC12949E for <>; Wed, 12 Oct 2016 01:11:57 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -4.896
X-Spam-Status: No, score=-4.896 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, RCVD_IN_DNSWL_NONE=-0.0001, RP_MATCHES_RCVD=-2.996] autolearn=ham autolearn_force=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id huWG4kLHj7_Q for <>; Wed, 12 Oct 2016 01:11:55 -0700 (PDT)
Received: from ( []) by (Postfix) with ESMTP id F3D2E1294A2 for <>; Wed, 12 Oct 2016 01:11:54 -0700 (PDT)
Received: from localhost (localhost []) by (Postfix) with ESMTP id 01BC1136F6; Wed, 12 Oct 2016 11:11:53 +0300 (EEST)
X-Virus-Scanned: Debian amavisd-new at
Received: from ([IPv6:::ffff:]) by localhost ( [::ffff:]) (amavisd-new, port 10024) with ESMTP id BE6AIg_RrI1e; Wed, 12 Oct 2016 11:11:52 +0300 (EEST)
Received: from LK-Perkele-V2 ( []) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPSA id 868BC28B; Wed, 12 Oct 2016 11:11:52 +0300 (EEST)
Date: Wed, 12 Oct 2016 11:11:45 +0300
From: Ilari Liusvaara <>
To: Kyle Rose <>
Message-ID: <>
References: <> <> <> <> <> <> <> <> <> <>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
In-Reply-To: <>
User-Agent: Mutt/1.5.23 (2014-03-12)
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 08:11:58 -0000

On Tue, Oct 11, 2016 at 09:41:55PM -0400, Kyle Rose wrote:
> >
> > 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.)

I have actually seen one service where partially received PUT requests
had "side effects". Fortunately, not a replay problem in that case,
since application would reject replays anyway.

> 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.

For when 0-RTT has become boring enough for me to implement, I would
think the server-side interface I put in would be something like the

- ServerSession::getReplayable0RttReader(alp_list) -> ZRttReader
- ZRttReader::getAlpn() -> String
- ZRttReader::dataAvailable() -> size
- ZRttReader implements Read

If there is no replayable 0RTT reader given when ClientHello is
received, or if the ALP of the 0-RTT does not match any in alp_list,
the 0-RTT is rejected. Otherwise it is accepted and the data stream is
received via the ZRttReader. Then regular 1-RTT data will be returned by
the usual Read interface of ServerSession.

> 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}.

In the interface above, not caring about 0-RTT gets 0-RTT rejected. And
waiting just causes the connection to freeze up.
> 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.

The interface I envision has client write all the 0-RTT data and
explicitly signal the end of data, with a callback if server rejects,
so the application can abort the flight early (the stack just black-
holes the data after error).

And of course some critical thingy in which normally blocks 0-RTT
sending has name suggestive of replayability.

The reason for waiting for application to ACK the 0-RTT error is that
the thing is MT-safe, so one has to prepare for races..
> 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
> authentic.

Well, one always knows that for any received data, one who sent it
possesses the PSK secret and it can't be tampered with without the
PSK secret.

However, receiving any 1-RTT data after 0-RTT data does not imply that
the 0-RTT data was not replayed!
> 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.

There's the case where ALP mismatches (and unfortunately, due to how
ALPN and 0-RTT interact, mismatches can happen in cases other than
just that 0-RTT is fundamentially impossible).

In that case, the data is obviously different. Then there are also
things like the planned 0-RTT tokbind, where the data sent on 0-RTT
failure is different from the original data.

> 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
> data.

I regard post-hoc authentication as quite dangerous. At least in
some applications it is a deadly security mistake.