Subject: [TLS] Proposal for client auth

From: Eric Rescorla <[email-masked]>
Date: Wed, 21 Oct 2015 11:01:45 -0700

Folks,

At the Seattle interim, we decided to have a small ad hoc design team
go and figure out how to harmonize the various forms of client
authentication. I've posted a WIP version of the output of that work
at:

        https://github.com/tlswg/tls13-spec/pull/316

The basic observation (due to Karthik) is that TLS already implicitly
adopts the SIGMA framework for authentication (specifically, SIGMA-I).
To see this, consider the 1-RTT key exchange:

           ClientHello
             + ClientKeyShare        -------->
                                                           ServerHello
                                                       ServerKeyShare*
                                                 {EncryptedExtensions}
                                                {ServerConfiguration*}
                                                        {Certificate*} <-\
                                                 {CertificateRequest*}    >
Signature
                                                  {CertificateVerify*} <-/
                                     <--------              {Finished} <-
MAC
Sign.  /-> {Certificate*}
       \-> {CertificateVerify*}
MAC     -> {Finished}                -------->
           [Application Data]        <------->      [Application Data]

Each signature covers the entire handshake up to that point, including
both identities, and the MAC is derived from g^xy (and in the case of
0-RTT, g^xs as well).

So, what this draft does is adopt the following three messages.

   Certificate
   CertificateVerify
   Finished

As the "TLS Authentication Block" and send them whenever we want to do
authentication. [Note that we may eventually merge messages here, but
that doesn't affect the logic.]

In every case, the input to the block would be:

   - A session context (SC) which is (generally) the handshake
     transcript up to this point.
   - A base key to compute the finished key from (the finished
     keys are directional, so the client and server keys are
     different).

And then the signature covers: SC + Certificate
And the MAC covers SC + Certificate + CertificateVerify

The inputs are:

Mode             Handshake Context                        Base Key
----             -----------------                        --------
0-RTT            ClientHello + ServerConfiguration        xSS
                             + Server Certificate
                             + CertificateRequest

1-RTT (Server)   ClientHello ... ServerConfiguration      master_secret

1-RTT (Client)   ClientHello ... ServerFinished           master_secret

Post-Handshake   ClientHello ... ClientFinished +         master_secret
                 CertificateRequest

If we just move CertificateRequest to before Certificate, than this
effectively is what we already do for the TLS 1.3 handshake.

The proposal, then, is to adopt the following unified flow diagram.

            ClientHello
              + ClientKeyShare
         ^    + EarlyDataIndication
  O-RTT  |  (Certificate*)
  mode   |  (CertificateVerify*
         v  (Finished)  // Note: new message.
            (Application Data*)       -------->
                                                            ServerHello
                                                        ServerKeyShare*
                                                  {EncryptedExtensions}
                                                  {CertificateRequest*}
                                                 {ServerConfiguration*}
                                                         {Certificate*}  ^
                                                   {CertificateVerify*}  |
Server Authentication
                                      <--------              {Finished}  v
 1-RTT   ^  {Certificate*}
 Client  |  {CertificateVerify*}
 Auth    |  {Finished}                -------->
         v  [Application Data]        <------->      [Application Data]

                                      <--------    [CertificateRequest]   ^
            [Certificate]                                                 |
Post-Handshake
            [CertificateVerify]                                           |
Authentication
            [Finished]                -------->                           v

Note 1: I think the best plan here is to allow the server to send a
CertificateRequest in 1-RTT even if the client sent a certificate in
its 0-RTT first flight. This is superficially more complicated but
actually simpler since it lets us regard there as being just a 1-RTT
handshake plus some stuff that the client sends in 0-RTT.  Obviously,
this leaves the possibility that that server can ask the client for a
certificate in its first flight even with the same CertificateRequest
that the client is (implicitly) responding to in 0-RTT, and while this
is silly there's nothing stopping the server from doing this in
post-handshake auth either.

Note 2: This PR also modifies the master_secret derivation so that it
is computed right after ServerCertificateVerify (i.e., at the same
time as we compute the server Finished message) because this allows
the use of the same traffic keys regardless of whether client auth is
involved. In addition, it doesn't include the client's 0-RTT client
auth messages in the session hash. This isolates them more completely
from the rest of the handshake, thus leading to a more unified
flow. If this has a security impact then as noted elsewhere, it
probably threatens post-handshake client auth entirely.

The PR has more detail (and again, it's a WIP). I expect we'll need
to discuss in Yokohama, but I wanted to get people's feedback now.

-Ekr

P.S. Thanks to Hugo, Bjoern, Karthikeyan, mt, Adam, AGL, DKG, and Hoeteck
for their time working through this.

---

From: Ilari Liusvaara <[email-masked]>
Date: Thu, 22 Oct 2015 20:26:16 +0300

> And the MAC covers SC + Certificate + CertificateVerify

Perhaps I'm reading things wrong, but this change seems to pass
raw Context+Certificate+Signature to HMAC to compute Finished.
Due to the way HMAC works, this requires to know the key for
the MAC before one can start the pipe (I didn't look when it
becomes available) and requires a separate pipe from ordinary
transcript hash.

Previously, Finished messages used the same transcript hash
pipe as everything else using transcript hashing.

-Ilari

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 22 Oct 2015 10:34:01 -0700

> pipe as everything else using transcript hashing.

I just messed up the editing.

It's the same plan as before. HMAC(key, handshake_hash). So, for
example, the signature from the server would cover all messages
between ClientHello and Certificate (inclusive) and the MAC would
cover all messages from ClientHello and CertificateVerify inclusive.

I'll fix this in the text.

-Ekr