Subject: [TLS] Renegotation redux

From: Watson Ladd <[email-masked]>
Date: Mon, 14 Apr 2014 07:48:22 -0700

Dear all,

Are there any users of renegotiation beyond authentication with client
side certificates? In particular has anyone come up with a use for
changing the claimed identity of the server?

I think we can do client authentication upgrades via a channel
extraction+signing solution while preserving the privacy currently
given by renegotiation. I haven't yet run Proverif on this solution,
so it might not work, but my intuition is that this will work better
than trying to expose the semantics of renegotiation correctly.

Renegotation has been responsible for two major security issues, and
significantly complicates the TLS handshake state machine and
semantics.

Sincerely,
Watson Ladd

---

From: "Salz, Rich" <[email-masked]>
Date: Mon, 14 Apr 2014 10:52:28 -0400

> Are there any users of renegotiation beyond authentication with client side certificates?

Yes, although these days it's a pretty narrow window.  Under certain circumstances, a client can recognize that a server is "authorized" to do stronger crypto, and will renegotiate. Search for step-up or server-gated cryptography.  It's not really needed much any more, although we have at least one customer with embedded clients that wants it.

--  
Principal Security Engineer
Akamai Technology
Cambridge, MA

---

From: Juho Vähä-Herttua <[email-masked]>
Date: Mon, 14 Apr 2014 18:04:14 +0300

> On 14.4.2014, at 17.48, Watson Ladd <[email-masked]> wrote:
> 
> Dear all,
> 

I've been under the impression that renegotiation can be used to keep the connection open when the encryption is based on nonces and client/server runs out of usable nonces. The current counters are large enough that this is unlikely to happen, but if some crypto defines smaller nonces it might be a problem.

Disallowing renegotiation would leave both parties with no other choice than hanging up the connection.

Juho

---

From: Alyssa Rowan <[email-masked]>
Date: Mon, 14 Apr 2014 19:16:30 +0100

On 14/04/2014 15:52, Salz, Rich wrote:

> Yes, although these days it's a pretty narrow window.  Under 
> certain circumstances, a client can recognize that a server is 
> "authorized" to do stronger crypto, and will renegotiate. Search 
> for step-up or server-gated cryptography.  It's not really needed 
> much any more, although we have at least one customer with
> embedded clients that wants it.

An extraordinary case: those must be VERY embedded clients! :-)

I seem to recall those circumstances were clients with 'export-grade'
40-bit crypto who'd step up to 128-bit with an SGC certificate.

Weren't we talking about completely removing Ye Olde 40-bit 'Export'
Suites?

- -- 
/akr

---

From: Nick Mathewson <[email-masked]>
Date: Mon, 14 Apr 2014 14:40:04 -0400

> than trying to expose the semantics of renegotiation correctly.

So, I've got an example, but I hesitate to bring it up.

Long ago, Tor added a link authentication mode in which we do an
innocuous TLS handshake designed to look like a browser talking to a
webserver, and then renegotiate with the actual parameters and
certificates we wanted.  The goal here was to resist attempts to block
users from connecting to the network.

Using renegotiation here was a mistake and a very bad design.  The
versions of Tor which prefer this link protocol are all deprecated
now.  Renegotiation was not a good solution for this problem, for a
few reasons:

    * It only helped somewhat against blocking.  It turns out that
renegotiating in the way we were renegotiating was weird enough that
it didn't actually make us less conspicuous.
    * It seriously complicated our code.
    * Because we depending on renegotiation, many of the workarounds
for TLS renegotiation bugs broke our clients and servers.

I'm only mentioning it here so nobody brings up Tor as an example of
projects that need renegotiation. We would have been better off if we
had never used renegotiation.  Please do not cite Tor as a good use
case for renegotiation.

> significantly complicates the TLS handshake state machine and

To add to the parade of ugliness: the presence of negotiation keeps
programmers from implementing post-handshake TLS as a filter: you need
a notion of "[TLS] read blocked on [TCP] write" and "[TLS] write
blocked on [TCPl] read."  This adds a great deal of complexity and
bugginess to non-blocking programs that want to use TLS libraries.

cheers,
-- 
Nick Mathewson

---

From: Nico Williams <[email-masked]>
Date: Mon, 14 Apr 2014 23:36:56 -0500

> changing the claimed identity of the server?

Yes, it's been discussed in the context of protecting the server's
identity: start with anon ECDHE ciphersuites then renegotiate to [use
SNI and] authenticate the server.

This is important in general given that privacy protection is desirable.

> extraction+signing solution while preserving the privacy currently

We call that channel binding.  I agree as to that.

> significantly complicates the TLS handshake state machine and

First off, renego was responsible for one bug -- the other is a
resumption bug, and BOTH were the result of insufficient or
non-existent channel binding between the one connection and the other.

Second, we do have uses for renego (see above).

Third, I'm skeptical of proposals to throw the baby out with the bathwater.

Fourth, renego need not complicate the TLS handshake state machine if
we see the two (or three, or...) handshakes as distinct connections
with channel binding of inner to outer.

I'll admit that the fact that we did not discover the lack of
sufficient channel binding in resumption after the renego bug does
give me pause.  We should audit the protocol and implementations on
this point, but we have to anyways.  Also, note that your proposal
regarding client certs is to push the problem to the app layer and
hope that they get channel binding right, which given our collective
failure to do the same in TLS should give us pause.  I.e., TANSTAAFL,
which makes me think even more that yours is a
throw-the-baby-out-with-the-bathwater proposal.

Nico
--

---

From: Nico Williams <[email-masked]>
Date: Mon, 14 Apr 2014 23:56:37 -0500

On Mon, Apr 14, 2014 at 11:36 PM, Nico Williams <[email-masked]> wrote:
>>[...]
> [...]

To be fair I should add that such a model of renegotiation is actually
barely different from yours anyways.

That is:

a) remove renegotiation
b) require a channel binding output (RFC5929 will do, provided
resumption is fixed)
c) require a channel binding _input_ and check it when provided.

You propose (a) and (b).  I propose (b) and (c) and an API that looks like (a).

This way it is possible to model TLS handshakes as an SChannel-like
(or GSS-API-like) initSecContext/acceptSecContext token exchange but
with renegotiation being a brand new SecContext with channel binding
from the inner to the outer.

This way there's no complication of the TLS state machine at all.  The
application becomes responsible for doing the renego _if_ it wants to.

I think you and I are closer to agreement on this than I thought ten
minutes ago.

Now, if some implementations want to keep renego the old way, as long
as it does the necessary channel binding and on the wire it interops
with new-style implementations, I won't mind!

Nico
--

---

From: Watson Ladd <[email-masked]>
Date: Mon, 14 Apr 2014 23:14:15 -0700

> SNI and] authenticate the server.

That won't work if you do it like that. Hint: how does the server know
who to reveal their identity to?

> non-existent channel binding between the one connection and the other.

It's not "a lack of channel binding". It's a failure to hash
transcripts in a key exchange. That's why you can have the same
pre-master secret on two different connections, and thus break
resumption. If the two connections were completely independent these
problems wouldn't have happened as you wouldn't trust the earlier data
as coming from the person you now authenticated. (My understanding of
insecure resumption is that a renegotiation was necessary to seal the
deal: i'll double check the paper to see if that's correct).

> with channel binding of inner to outer.\

And that's not complicated? I don't see how channel binding fixes the
confusion that is changing claimed identities across connections, or
reduces the impact of renegotiation on implementation complexity.

The problem Nick had was the following: you want a software component
that sits between a bidirectional stream of bytes and a socket, and
applies TLS after the handshake has completed. Because this is C, and
not Go (or CML, or etc...), you cannot write an independent event loop
without an OS level thread. (Completing the handshake involves a bit
more work)

The usual solution would be as follows: when the host application
writes to the stream, it signals there is new data to send, which the
component dutifully encrypts, and sends (since the host application
has checked that sending is possible on the fd via poll(3) or
equivalent). On read the same thing happens in reverse.

However, with renegotiation the component suddenly goes into a state
into which sending data is dependent on receiving some data. How you
deal with this cleanly is beyond me. It's not solved by any retooling
of the API: it's fundamental to any protocol exchange in which a read
can block a write.

> throw-the-baby-out-with-the-bathwater proposal.

I'm not pushing it to the app layer any more than now, nor am I
suggesting that the average application developer be ever trusted with
cryptography. The library should say "pass me a cert" (ideally not
even that) and handle the rest.

In the course of my writing this missive, another email from you
arrived. You suggested that we hand this over to the application layer
in part, by exposing channel binding inputs and outputs. This is a
terrible idea. The application developer is not supposed to know or
understand cryptography. They are supposed to write dial("443",
"secure.example.com") and have the OS take care of determining which
certs are trusted, opening a secure connection, and the fiddly details
of managing that connection, and authenticating the user over that
connection (if needed). They get it wrong too often to be trusted with
it, and shouldn't even be trusted with cert selection (as that means
they can read certs). (TCP is spelled dial_insecure, just be sure
everyone gets the message). (and by application developer I mean me
when I don't want to think about this).

What does the application do with the return value of dial? write(2),
read(2), poll(3), close(2), just like anything else.

Sincerely,
Watson Ladd

-- 
"Those who would give up Essential Liberty to purchase a little
Temporary Safety deserve neither  Liberty nor Safety."
-- Benjamin Franklin

---

From: Nico Williams <[email-masked]>
Date: Wed, 16 Apr 2014 21:53:48 -0500

I've thought more about this and... I've changed my mind.  We should
remove renegotiation.

I'll post separately about how we should cover the uses of
renegotiation that we've seen or discussed.

Nico
--

---

From: "Salz, Rich" <[email-masked]>
Date: Thu, 17 Apr 2014 11:04:33 -0400

> I've thought more about this and... I've changed my mind.

Regardless of the topic, this doesn't seem to happen often.  This is example we all (myself included!) should take to heart.

	/r$