RFC 5869 Defines HKDF-Extract in section 2.2 as:
HKDF-Extract(salt, IKM) -> PRK
TLS 1.3 RFC 8446 defines the first part of the Key Schedule like this:
0 | v PSK -> HKDF-Extract = Early Secret | ... <<< omitting unrelated lines >>> ... v Derive-Secret(., "derived", "") | v (EC)DHE -> HKDF-Extract = Handshake Secret
And later confirms that if there is no PSK, the first Extract operation is on (0,0):
if PSK is not in use, Early Secret will still be HKDF-Extract(0, 0)
The result of HKDF-Extract(0, 0) will get fed into the Derive-Secret Operation as such:
Derive-Secret( [HKDF-Extract(0, 0)], "derive", "")
Which doesn't include a transcript hash. Hence, this is put together from entirely prescribed values (0, 0, "derive").
Q: Does this mean this value, which is then combined with the result of the (EC)DHE, is always constant?
HKDF-Extract on (
0,0), then an
HKDF-Expand-Label on the result of the earlier Extract, plus the label "derived" plus an empty handshake transcript?