On Mon, 9 Jan 2023, at 03:34, Joseph Salowey wrote:
> The definition of the TLS-PRF is given in 5246 as:
> 
> PRF(secret, label, seed) = P_<hash>(secret, label | seed)
> 
> This construction only defines 3 parameters and does not define a length.  I 
> don't think current implementations include the length as an input to the key 
> derivation so I think the following is the correct resolution:

>From a literal statement, you do need a length, as PRF outputs an output 
>stream, so implementations knows how much stuff to emit and do not use 
>infinity RAM.

https://github.com/FreeRADIUS/freeradius-server/blob/v3.2.x/src/modules/rlm_eap/libeap/mppe_keys.c#L157-L165
https://w1.fi/cgit/hostap/tree/src/crypto/sha256-tlsprf.c

Do you mean "length is irrelevant as an input" as it has no impact on the 
content of the output stream?

> Original Text (Section 5.2):
> [snipped]
> 
> Corrected Text (Section 5.2):
> [snipped]
> 
> In addition there are similar corrections to section 5.3
> 
> Original Text:
> [snipped]
> 
> New Text (Section 5.3):
> [snipped]

Problem is this section has the instruction "generate 64 bytes, use the first 
32..." and after personally getting tripped up[1] on the different though used 
with TLS-Exporter which for TLSv1.3 now generates wildly different outputs 
depending on the length you request.

So do we think implementers treat the PRF function as a '(stable) stream output 
function' or a 'hashing function'? It works as the former but when you use it 
it feels like the latter.

So two options:

1. I do like the amendment to use the language "First N octets of TLS-PRF(..." 
but it would be helpful to include with it a statement along the lines that 
PRF/P_<hash> outputs a stable infinite *stream* of pseudorandom wonder.

2. We update the PRF/P_<hash> function definition updated to include 'length' 
(as actual implementations *do* take in a length to know how much stuff to 
generate) just so we push it under the noses of implementers and ready them for 
the excitement and pitfalls of TLSv1.3.

So whilst I prefer the amendment language, I think for communication and 
clarity reasons adding 'length' to the PRF/P_<hash> is the better options as it 
makes it literally closer to how those functions are in practice implemented 
and called; plus TLS-Exporter is now sensitive to length to we gain some kind 
of symmetry there too.

On a related note, whilst we are here, it does raise the question on how we got:

"...the length is 64 octets..." and "First 32 octets of TLS-PRF(...)"

The '0x00 || 0x40' (64 network order 16bit length concatenation) looks 
superfluous and I cannot see what they add here (as the label is not recycled 
elsewhere) and makes me wonder if it was unintended?

Part of my reasoning is later in the same section we see TLS-PRF(...) with what 
is obviously a length field:

IMCK[j] = TLS-PRF(S-IMCK[j-1], "Inner Methods Compound Keys" || IMSK[j], 60)
S-IMCK[j] = first 40 octets of IMCK[j]
CMK[j] = last 20 octets of IMCK[j]

This makes me believe that originally we were meant to see:

IMSK = First 32 octets of TLS-PRF(EMSK, "teapbind...@ietf.org" || 0x00, 64)

This aligns nicely with the 'label | seed' definition seen earlier for 
PRF/P_<hash> too.

Not to sure why the '0x00' is still needed, but maybe it was to stop people 
messing up the seed with a NULL/empty value rather than a single NUL byte or 
vice versa; this way it is explicitly described/read-as "seed is 0x00" and 
clear to the implementer.

Anyway, pondering on history here is mostly irrelevant as Windows, Cisco ISE, 
hostapd and now FreeRADIUS all have implemented '... || 0x00 || 0x00 || 0x40'.

Cheers

[1] I had Alan add a paragraph on this to 
https://datatracker.ietf.org/doc/html/draft-ietf-emu-tls-eap-types-09#section-2.1
 as I lost a day or so wondering why my EAP-whatever/TLSv1.3 was not working

_______________________________________________
Emu mailing list
Emu@ietf.org
https://www.ietf.org/mailman/listinfo/emu

Reply via email to