The Key Schedule in the TLS 1.3 RFC starts like this:
0
|
v
PSK -> HKDF-Extract = Early Secret
|
+-----> Derive-Secret(., "ext binder" | "res binder", "")
| = binder_key
|
+-----> Derive-Secret(., "c e traffic", ClientHello)
| = client_early_traffic_secret
|
+-----> Derive-Secret(., "e exp master", ClientHello)
| = early_exporter_master_secret
...
Later in Section 7.1, the RFC provides guidance on what to use as a substitute value for PSK if a Pre-Shared-Key is not actually used:
If a given secret is not available, then the 0-value consisting of a
string of Hash.length bytes set to zeros is used. Note that this
does not mean skipping rounds, so if PSK is not in use, Early Secret
will still be HKDF-Extract(0, 0).
The client_early_traffic_secret
and early_exporter_master_secret
include a transcript hash of the Client Hello, which includes a Random Number generated by the client. So these two keys will be different for every SSL Session.
However, the binder_key
does not include any transcript hash. Which means (by my interpretation), the only values feeding into the binder_key
secret are both known by everyone and never change (0 as the starting value, 000...0 as the substitute for PSK, and the constant labels ext binder
or res binder
).
Am I interpreting that correctly? If so, how is this not a reduction in security that one of the output secret keys of the key schedule never changes?