Original text:
Change end_of_early_data to be a handshake message (*).  Remove spurious requirement to implement "pre_shared_key". Clarify location of "early_data" from server (it goes in EE, as

Reviewer comments:
benefits: (1) Restoring extract/expand parity, thus cleaning up the theoretical treatment wrt HKDF and future replacements. (2) Futureproofing against someone being able to force the ECDHE value in the second HKDF-Extract to collide with one of the labels. This seems unlikely with current groups, but might be possible with some future algorithm. (Issue due to Trevor Perrin).
This is mostly a cosmetic thing, and I'm not sure if I actually like all of my proposals below: With the current scheme, the key schedule is very simple and neatly encompassed into a box with a shape like this: NewTLS13KeySchedule(hash) => creates a new schedule with base secret = 0 AddEntropy(sched, ikm) => HKDF-Extract ikm into the current base secret DeriveSecret(sched, label) => take the current base secret and handshake transcript and derive a particular secret with the label This breaks the symmetry in a few ways: Incorporating a new IKM requires an extra label for the Derive-Secret operation in the middle. Going from 0 to Early Secret does not involve a Derive-Secret. We use Derive-Secret, Derive-Secret no longer always uses the current state of the handshake transcript (1) could be resolved by just using the same label for both, like "prepare extract" or something. I don't believe this breaks anything? We're just trying to fix the problem where HKDF-Extract and HKDF-Expand can't be used on the same key. (3) is actually kind of odd because Derive-Secret is defined as: Derive-Secret(Secret, Label, Messages) = HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.Length) So we're actually putting Hash("") into HKDF-Expand-Label, not the empty string. Then again, it feels odd making them ClientHello...ServerHello and ClientHello...Server Finished, respectively. We could use HKDF-Expand-Label directly which still gives us the separation, but it's not as obvious. Adding an extra Derive-Secret just to fix (2) feels a little pointless but would increase symmetry. (Alternatively, the answer could just be "deal with it, your key schedule box should have slightly richer methods on it". Like I said, this is just cosmetic.)
I'm ambivalent on David's gripe. This seems fine to me. One editorial suggestion though. This is now a very tall diagram. You can save a few lines by changing to something like this
About this PR, there is a con: complicating the already complicated key schedule
It does not seem especially complicated compared to, e.g., Kerberos. Or maybe that's just me.
well, you're comparing it to Kerberos :rofl:
NAME I fixed . I think we can live without . We already have this "empty hash" construct for the binder keys, so while it's a bit goofy it's no more goofy than here.
We seem to have reached consensus that the record layer will use the AEAD form only. The stream and CBC forms will be removed.
Fixed.

Revised text:
Change end_of_early_data to be a handshake message (*). <ins> Add pre-extract Derive-Secret stages to key schedule (*). </ins> Remove spurious requirement to implement "pre_shared_key". Clarify location of "early_data" from server (it goes in EE, as