Subject: [TLS] Adding an additional step to exporters

From: Martin Thomson <[email-masked]>
Date: Fri, 24 Feb 2017 15:30:33 +1100

https://github.com/tlswg/tls13-spec/pull/882 contains the longer description.

In short, the existence of an exporter secret threatens the forward
secrecy of any exported secret.  This is a problem for QUIC and is
likely to be a more general problem.

The proposed fix is small: separate exporters into two steps
(extract+expand) where the first step allows for separation based on
exporter type and the second on context.  That allows an endpoint to
keep separate secrets for each exporter type and discard those that it
no longer needs, thus gaining forward secrecy if it likes.

---

From: Sean Turner <[email-masked]>
Date: Fri, 24 Feb 2017 00:01:37 -0500

So this isn’t entirely novel right I mean we did something similar wrt other key schedules?

spt

> On Feb 23, 2017, at 23:30, Martin Thomson <[email-masked]> wrote:
> 
> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls

---

From: Felix Günther <[email-masked]>
Date: Thu, 23 Feb 2017 21:09:34 -0800

Hi Martin,

just to clarify: you add an additional HKDF.Expand step, not
HKDF.Extract, right?

You mentioned extract in the email and PR text, but in code it's a
second expand---which makes sense, as only expand allows to add context
(here: label).

Cheers,
Felix

---

From: Martin Thomson <[email-masked]>
Date: Fri, 24 Feb 2017 16:40:19 +1100

> So this isn’t entirely novel right I mean we did something similar wrt other key schedules?

I certainly hope it isn't novel.  I'm just applying the same
technique: keep independent keys independent.

> just to clarify: you add an additional HKDF.Expand step, not

Yes, you are right, I should have said expand.  You need to use expand
to get the label-based separation on type.

I don't know how I got confused about that.  If we need to maintain
extract and expand in pairs (as we have already been burned by), then
I will defer to cryptographers on that.

---

From: Ilari Liusvaara <[email-masked]>
Date: Fri, 24 Feb 2017 12:02:02 +0200

> technique: keep independent keys independent.

This technique seems to assume there is some fixed known set of exporter
labels that are used. Since if you don't know the full set, you need to
keep the master exporter secret around anyway.

> I will defer to cryptographers on that.

The creator of HKDF stated that HKDF should always be used with paired
extracts and expands and any derpartion from that should be done with
utmost care.

Both the existing design and this design fail this: Because exporter
secrets are of expanded type, you would need to extract them, and
derive-secret is expansion type operation.

Note that passing label as salt is definitely very bad idea, since you
will get trivial collisions due to how HKDF works internally. And
doing so even with hash might be a bad idea.

-Ilari

---

From: Hugo Krawczyk <[email-masked]>
Date: Fri, 24 Feb 2017 11:47:32 -0500

Martin,

Which of these two derivation schemes are you proposing?
Are you assuming that all uses of the exporter_secret are known at the end
of
the handshake? If not, you still need to keep an exporter_secret beyond the
handshake.

Master Secret
      |
      |
      +-----> Derive-Secret(., "exporter master secret 1",
      |                     ClientHello...Server Finished)
      |                     = exporter_secret_1
      |
      +-----> Derive-Secret(., "exporter master secret 2",
                            ClientHello...Server Finished)
                            = exporter_secret_2

Or:

Master Secret
      |
      |
      +-----> Derive-Secret(., "exporter master secret",
                            ClientHello...Server Finished)
                            = exporter_secret
                                 |
                                 +-----> Derive-Secret(., "exporter secret
1",
                                 |                     what_exactly)
                                 |                     = exporter_secret_1
                                 |
                                 |
                                 +-----> Derive-Secret(., "exporter secret
2",
                                                       what_exactly)
                                                       = exporter_secret_2

(I wrote "what exactly" since I am not sure what do you plan to include
there.)

Regarding Ilari's comment on HKDF pairings, I have said that an Extract
operation needs to always be followed by an Expand operation, but an expand
operation may be followed by an expand operation. The point is that the
output
of Expand is (typically) intended as a key to another cryptographic
function.
Such function can be HKDF-Expand itself (which is just a specific
implementation
of a variable-length input/output PRF).

Thus, both of the above possible derivations are OK from the point of view
of HKDF.

Hugo

---

From: Ilari Liusvaara <[email-masked]>
Date: Fri, 24 Feb 2017 19:42:15 +0200

> (I wrote "what exactly" since I am not sure what do you plan to include

I interpretted it to be something like follows:

Master secret
 + Derive-Secret(label="exporter master secret", context=ClientHello...ServerFinished)
    + Derive-Secret(label=EXPORTER-FOO, context=<blank>)
      + Derive-Secret(label="exporter", context=<context#1>)
      + Derive-Secret(label="exporter", context=<context#2>)
    + Derive-Secret(label=EXPORTER-BAR, context=<blank>)
      + Derive-Secret(label="exporter", context=<context#1>)
      + Derive-Secret(label="exporter", context=<context#3>)

But I don't know how useful that would be, as it requires knowing all
labels one is going to use (or one needs to keep EMS around anyway).

-Ilari

---

From: Martin Thomson <[email-masked]>
Date: Mon, 27 Feb 2017 11:21:30 +1100

> keep the master exporter secret around anyway.

This is correct.  I assume here that many applications know the set of
exporters that they support, since each generally requires code.  This
would not be a TLS-stack responsibility, but an application-layer one.

---

From: Martin Thomson <[email-masked]>
Date: Mon, 27 Feb 2017 11:28:07 +1100

Hi Hugo,

> Which of these two derivation schemes are you proposing?

I mean the latter of your two, where you have effectively three layers
of HKDF-Expand from the master secret.

master secret -> exporter secret
exporter secret + exporter type (label) -> specific exporter secret[label]
exporter secret[label] + context -> exporter value

(Just like what Ilari said.)

I think that is easier for implementation reasons to manage.
Splitting off from the master secret allows implementations to defer
some of the exporter-related processing and decisions until later.

> Are you assuming that all uses of the exporter_secret are known at the end of

Yes, this is correct.  This assumes that you know the *type* of all
exporters you might support.  I think that this is a reasonable
assumption since each exporter relies on implementing a specification
for that exporter and having code for it.  For example, you might have
a list of supported exporters, for which you could derive the
intermediate value.

> Thus, both of the above possible derivations are OK from the point of view

Thanks.  I thought that it was OK, but having you confirm that makes
me much happier.