Hi Jamil et al -

I think I finally understand the disconnect here - let me try and work through an explanation from another direction.

The TLS 1.3 KDF is NOT HKDF-Expand, it is HKDF-Expand-Label.

HKDF-Expand has a calling sequence of HKDF-Expand (Secret, Label, Length).   That results in underlying calls to T(n) = PRF (Secret, T(n-1) || label || n) for each block of key stream (RFC 5869 - page 3).

Two key things to understand here are:  that the Length value in HKDF-Expand is not passed in as a mixin, only as a value to determine how much key stream to produce; that the "label" parameter is just opaque data (remember this please - its important later).

HKDF-Expand-Label (Secret, Label, HashValue, Length)  is defined as HKDF-Expand (Secret, hkdfLabel, Length) where hkdfLabel is a structured value (NON-Opaque) consisting of the Length, Label (from the top level call) and Hash Value (also from the top level call) (TLS 1.3 section 7.1 Key Schedule). The hkdfLabel ultimately is the "label" part of the call to the PRF.

A module creating a key from HKDF-Expand-Label knows that it MUST cut off the key stream after Length bytes (and if a new length value is provided, you get a whole different key stream).  It can read the hkdfLabel  from the call and know this production is for a key or an iv and set protections appropriately. HKDF-Expand-Label also knows that it will only produce a single object from each call.  In HDKF-Expand, the Label value is opaque.  It may contain the Length value, it may contain key tagging information, it may contain your dog's name, but since it's not structured in any way, an implementer of the HKDF-Expand calling convention can't do anything useful with that data in figuring out the assignment of the key stream to a key object.

I think what we have is a failure of language.  HKDF (and for that matter SP800-108) should be called key stream producers - not key derivation functions.  Mainly because they don't properly consider the assignment of the key stream bytes to the keys and how that interacts with the key stream production.

I need a way of making sure that 1) the key assignment/production specifications can be included in the mixins, and 2) a way of letting the module/provider be able to rely upon those specifications (e.g. by changing the key stream if the specifications change).  That means that the KeyDerivation calling convention needs to let me provide all of this data before the first call to derive a key.

This would have been more obvious had TLS1.3 kept the same multiple production per KDF call as was in previous versions - the HkdfLabel argument would have been an array of hkdfLabel structures.  They opted to clean it up slightly and limit it to a single production per KDF call.

Mike




Reply via email to