TLS 1.2 defines a PRF-like construction $P_{hash} : \{0,1\}^* \times \{0,1\}^* \rightarrow \{0,1\}^l$ for key derivation, etc. To quote the spec:

We define a data expansion function, P_hash(secret, data), that uses a single hash function to expand a secret and seed into an arbitrary quantity of output:

P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
                       HMAC_hash(secret, A(2) + seed) +
                       HMAC_hash(secret, A(3) + seed) + ...

where + indicates concatenation.

A() is defined as:

A(0) = seed
A(i) = HMAC_hash(secret, A(i-1))

Why does $P_{hash}$ invoke HMAC twice per block of output? Are there valid security arguments for doing so?

In particular, why not a simpler, faster, counter-based scheme such as:

$P_{hash}(\text{secret}, \text{seed}) = B(\text{secret},\text{seed},0) \| B(\text{secret},\text{seed},1) \| \dots \\ B(\text{secret},\text{seed},i) = \text{HMAC}_{hash}(\text{secret}, \text{to_byte}(i) \| \text{seed})$

If there is no technical advantage, what are the historical reasons behind this design?

  • $\begingroup$ If TLS were designed today, we'd probably use HKDF instead. $\endgroup$ Apr 9, 2016 at 8:04
  • $\begingroup$ @CodesInChaos It is being designed today, and it uses HKDF. As you well know, I suspect :) $\endgroup$
    – Maarten Bodewes
    Apr 9, 2016 at 23:45
  • 1
    $\begingroup$ @MaartenBodewes not so sure I'd call it being "designed" so much as monkey-patched. Some of the decisions for 1.3 aren't going near far enough. Still way too many options in there. IMHO there should be exactly two cipher suites, and everything else is either a MUST or is completely out of the spec. Or is there a TLS 2.0 WG coming up with something simpler that can actually be implemented securely and analyzed? $\endgroup$
    – rmalayter
    Apr 11, 2016 at 4:19
  • 1
    $\begingroup$ @rmalayter A TLS that will be implemented securely? Dream on ;) $\endgroup$
    – Tim McLean
    Apr 11, 2016 at 18:10
  • $\begingroup$ @rmalayter You may be interested in my answer to the question here. I think you'll find that we kind-of agree on this. As for this question, it might be that the reasons are lost in the mist of time. $\endgroup$
    – Maarten Bodewes
    Jun 18, 2016 at 11:42

1 Answer 1


Read Marsh Ray's analysis. PRF in TLS is designed to be the most conservative aspect of TLS (the last part of TLS to break). Mr. Marsh calls it "the slowest, most conservatively designed stream cipher in common use".

TLS PRF seems to be NIST sp800_108 in "Double Pipeline Mode". What Tim McLean contemplates above as a potential alternative is sp800_108 in "Counter" mode.

The "Double Pipeline Mode" is the most conservative sp800_108 mode, and is also subject to several papers (ex. by Koutarou Suzuki and Kan Yasuda) that prove certain "feel-good" properties about it that are not present in other modes.

TLS (IMHO) is trying to ensure that its PRF survives even when the underlying hash function gets utterly broken (ex. assume something even more broken than MD5).

  • $\begingroup$ The other thing to note is that, of the components within TLS, the PRF is probably the least performance critical - virtually all your time is spent doing something else. Hence, it makes sense to be ultra-conservative with the PRF, as it doesn't cost you (that is, slow down the protocol) that much. $\endgroup$
    – poncho
    Jun 20, 2016 at 19:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.