Subject: [saag] Securing the full TLS handshake including SNI

From: Phillip Hallam-Baker <[email-masked]>
Date: Sun, 19 Feb 2017 14:46:35 -0500

All,

I have been looking at various ways to protect the TLS handshake including
the domain name of the site being accessed. To do this, it is necessary to
put 'some form' of key into the DNS record for the host.

While many people have suggested schemes in the past, these have all been
based on the legacy RSA exchanges and in ways I find unconvincing. Not
least because TLS is a protocol with 25 years history and has been patched
and repatched many times.

I would prefer to use a scheme that has the following properties

1) Only use DH/ECDH key exchange.
2) Enables use of hardware host keys
3) Provides perfect forward secrecy by default.
4) Has integrated support for client auth.

The type of approach I like best is the one used in the noise protocol
which underpins Signal, etc. The wonderful thing about DH is that it is
composable to as many keys as you need. So the basic idea is to have each
of the parties identified by a key:

* KH - The Host is identified by a host key that is distributed through a
DNS TXT record.
* KS - The Service is identified by a WebPKI certificate (EV / OV or DV)
* KC - The Client SHOULD be identified by a client key.
* EC - An ephemeral mix-in is supplied by the client.
* ES - An ephemeral mix-in is supplied by the service.

Let A(k1, k2...) be a function that creates an agreed key from k1, k2, etc.
Let KDF (x,p) be a key derivation function for purpose p.

A brief sketch of the protocol would be:

Client obtains KH from the DNS, creates A(KH, EC)

Client encrypts initial contact message under KDF (A (KH, EC),p1) this
contains
   * Client cert (if used) (contains KC)
   * DNS name of Service to be contacted
   * sundry flags

Service reply is encrypted under KDF (A (KH, EC), p2). This contains
   * Service certificate + chain (contains KS)
   * ES
   * Opaque identifier (for fast restart)
   * sundry flags

The rest of the conversation is encrypted under KDF (A(KH, EC) + A (KS, KC,
ES),p) where p = p1 or p2 depending on the direction.

The reason for not using a quintuple exchange for the service exchange is
that this approach allows different curves to be used for the host and
service level agreement. It is very likely that 25519 is sufficient for the
host level but there are definitely cases where 448 is needed for the
service level.

I have not looked into how to squeeze this into TLS data frames but that is
just bit shuffling.

While I can't see a case for moving away from X.509 for the service cert,
it might well be that we would want to use a different cert for the client
part. In particular, I can see the use of some form of blinding or
annonymization being layered in.

Note that with EC, multi-key exchanges don't actually take more time than
two key. The private keys add and the public keys multiply. So there is
only one modular exponentiation or other costly operation.

One odd feature of this exchange is that practically every part of it is
already specified by IETF docs. I built it from code I already had to
implement KDFs etc.

One possibility that I like a lot is that we can have client authentication
at the transport level for free. Which is useful for SMTPS / IMAPS / etc.
That does not do away with the need for application level authentication of
course, but we have the option of a transport binding.

I would like to see an option that allows a client to prove that they are
the same client that contacted earlier and that this be unlinkable across
DNS domains. Easy enough in DH//ECDH. If x is a device bound key, we can
use KDF (x + H(Domain), p3).

Thoughts?

---

From: "Salz, Rich" <[email-masked]>
Date: Tue, 21 Feb 2017 16:00:02 +0000

TLS 1.3 already has the concept of encrypted extensions in the handshake.  What if you put the “real” SNI inside an encrypted extension.  This requires the true origin and the “fronting” origin to have a trust relationship, but that can probably work for most, not all, of the delpoyments today.  Then all you need to do is write up an I-D defining this “true SNI extension.”

Disclaimer: this is not my idea.

--
Senior Architect, Akamai Technologies
Member, OpenSSL Dev Team
IM: [email-masked] Twitter: RichSalz

---

From: Phillip Hallam-Baker <[email-masked]>
Date: Thu, 23 Feb 2017 11:20:09 -0500

On Tue, Feb 21, 2017 at 11:00 AM, Salz, Rich <[email-masked]> wrote:

> TLS 1.3 already has the concept of encrypted extensions in the handshake.
> What if you put the “real” SNI inside an encrypted extension.  This
> requires the true origin and the “fronting” origin to have a trust
> relationship, but that can probably work for most, not all, of the
> delpoyments today.  Then all you need to do is write up an I-D defining
> this “true SNI extension.”
>
>
>
​How to shoehorn the result into TLS was the least complicated bit AFAIK.

The tricky bit would be that you need to decide how you want DNS Discovery
to work. I think the answer is to do DNS-SD for everything and assume that
the recursive resolver knows to pull the entire discovery chains for the
relevant records.​