PR: https://github.com/tlswg/tls13-spec/pull/454

I have uploaded a PR [technically two PRs, but one builds on the
other, so easier to just read the composition] which resolves two out
of the three significant remaining crypto issues (the remaining one is
the long-running discussion of post-handshake keys). The following
message lays out the changes, which are:

- Adopt a more linear key schedule
- Add a context identifier for resumption


KEY SCHEDULE
We had a lot of comments that the existing key schedule was too hard
to understand and implement and could be simplified under the
assumption that keys were available in a specific order (PSK then DH
ZZ). I've been working together with Karthik, Hugo, Antoine, and
others to produce something cleaner. (Note: I believe they consider
this acceptable, but that doesn't mean they wouldn't have designed
every piece exactly as I have.)


The overall key schedule looks like this:

                 0
                 |
                 v
   PSK ->  HKDF-Extract
                 |
                 v
           Early Secret  --> Derive-Secret(., "early traffic secret",
                 |                         ClientHello)
                 |                         = early_traffic_secret
                 v
(EC)DHE -> HKDF-Extract
                 |
                 v
              Handshake
               Secret -----> Derive-Secret(., "handshake traffic secret",
                 |                         ClientHello + ServerHello)
                 |                         = handshake_traffic_secret
                 v
      0 -> HKDF-Extract
                 |
                 v
            Master Secret
                 |
                 +---------> Derive-Secret(., "application traffic secret",
                 |                             ClientHello...Server
Finished)
                 |                             = traffic_secret_0
                 |
                 +---------> Derive-Secret(., "exporter master secret",
                 |                         ClientHello...Client Finished)
                 |                         = exporter_secret
                 |
                 +---------> Derive-Secret(., "resumption master secret",
                                           ClientHello...Client Finished)
                                           = resumption_secret

  Derive-Secret(Secret, Label, Messages) =
       HKDF-Expand-Label(Secret, Label,
                         Hash(Messages) + resumption_context, L))


Derive-Secret is just a wrapper around HKDF-Expand-Label, for reasons
indicated below. If a key is missing you just use 0s.

The general pattern here is that the secrets shown down the left side
of the diagram are just raw entropy without context, whereas the
secrets down the right side include handshake context and therefore
can be used to derive working keys without additional context.  All
the working keys (both encryption keys and finished keys) are
generated using HKDF-Expand-Label off of the traffic secrets.

This design is motivated by the following principles:

- Separate out adding entropy from adding context.
- Incorporate the transcript once and then derive from there.
- Have a narrow, consistent interface for generating the leaf keys
  so they can just start with a base key.
- Derive from keys as soon as practical so that you can destroy them
  (thus the final call to Add-Secret, which isolates the
  Finished keys from the MS).

An additional nice point about this design is that it easily
accomodates additional keys. For instance, if we had some post-quantum
key exchange method, we could easily add its key in the final
Add-Secret or add an extra Add-Secret stage before HS. Similarly, if
we had a long-term DH key as in OPTLSv1, it could replace the 0 in the
final Add-Secret.

One thing I want to call out explicitly is that we are using
HKDF-Expand-Label with the output of HKDF-Expand-Label. This is
cryptographically fine, but means that you need an implementation of
the individual HKDF Expand/Extract primitives. As far as I can tell,
this isn't a hardship for anyone, but please speak up if it is. The
advantage of this is that you remove unnecessary crypto operations.


CONTEXT IDENTIFIER
PR: https://github.com/tlswg/tls13-spec/pull/454

Hugo and Karthik both independently suggested that it would be nice to
have some identity/context bound into the PSK handshake. The second PR
accomodates that by deriving two values from the RMS:

   resumption_psk = HKDF-Expand-Label(resumption_secret,
                                      "resumption psk", "", L)

   resumption_context = HKDF-Expand-Label(resumption_secret,
                                          "resumption context", "", L)

The resumption_psk is then used as the PSK for resumption and the
resumption_context is added to the hash of the handshake messages
whenever you use them, currently just by appending to the hash, as in:

   Hash(handshake messages) +resumption_context

This is used *both* to derive the keys and for the input to
the CertificateVerify/Finished. For convenience, I've


Note: the reason for separately deriving RMS and then computing the
context and PSK from RMS is to allow the server to just store RMS in
the ticket. If we used MS the server would need to store MS in the
ticket and then compromise of the ticket key would threaten the
original handshake.

One nit question, would it be better to hash twice, as in:

  Hash(Hash(handshake messages) + resumption_context)

I can't see a reason to, but maybe I've missed something.

Comments welcome. In the interest of not having too many outstanding
changes, I'll probably merge this tomorrow unless someone strongly
objects or we find something really egregious (which is always possible
because there's a lot of text here).

Best,
-Ekr
_______________________________________________
TLS mailing list
TLS@ietf.org
https://www.ietf.org/mailman/listinfo/tls

Reply via email to