Reference to TLS 1.2 standard documentation section 6.3 regarding the key generation here:

To generate the key material, compute

  key_block = PRF(SecurityParameters.master_secret,
                  "key expansion",
                  SecurityParameters.server_random +

until enough output has been generated. Then, the key_block is
partitioned as follows:


I assigned them the the following variables:

  • $kc_{mac}$= client_write_MAC_key[SecurityParameters.mac_key_length]
  • $ks_{mac}$= server_write_MAC_key[SecurityParameters.mac_key_length]
  • $kc_{data}$= client_write_key[SecurityParameters.enc_key_length]
  • $ks_{data}$= server_write_key[SecurityParameters.enc_key_length]

In a DHE key-exchange, where the client and server exchanged the keys and both have $\mathit{premaster} = g^{xy}$.

The client and server compute the master secret:

$$ms = \operatorname{hkdf}(\mathit{premaster},\mathit{nonce}_\mathrm{client}+\mathit{nonce}_\mathrm{server})$$

Then both compute the session keys:

$$\mathit{kc}_\mathrm{mac}, \mathit{ks}_\mathrm{mac}, \mathit{kc}_\mathrm{data}, \mathit{ks}_\mathrm{data} = \operatorname{hkdf}(\mathit{ms}, \mathit{nonce}_\mathrm{client} + \mathit{nonce}_\mathrm{server})$$

The $ms$ is used in the Finished MAC computation as follows: $\operatorname{MAC}(\mathit{ms}, \operatorname{hash}(\mathit{handshake}))$

The Finished messages are encrypted with the $\mathit{kc}_\mathrm{mac}$, e.g. the client Finished MAC:

$$\operatorname{enc}_{\mathit{kc}_\mathrm{mac}}(\operatorname{Finished}(\operatorname{MAC}(\mathit{ms}, \operatorname{hash}(\mathit{handshake})))$$

The data from client to server is encrypted as in:


My questions are:

  1. Is my interpretation for the TLS 1.2 key generation and usage correct?

  2. Are the master key $\mathit{ms}$ and the four session keys: $\mathit{kc}_\mathrm{mac}$, $\mathit{ks}_\mathrm{mac}$, $\mathit{kc}_\mathrm{data}$, $\mathit{ks}_\mathrm{mac}$ computed in in two consecutive steps, that is: after the Client Key Exchange and before the client Change Cipher Spec and Finished messages? or is there any other messages sent/received between them?


1 Answer 1


There are a few things off in your description.

First, you use the term "hkdf". There is such a thing as HKDF, which is a key derivation function that internally uses HMAC; however, HKDF is not used in TLS. TLS defines its own key derivation function, which it consistently calls "PRF". It is described in section 5 of the standard. That function is also based on HMAC, but with a different structure. The PRF has three input parameters:

  • the "secret";
  • the "seed";
  • the "label".

Exactly what goes into each of these parameters depends on the context. Normally, the "label" is a constant string that qualifies the usage point (e.g. "client finished" when computing the client's Finished message). The "seed" is made of elements from the handshake, that are normally observable, i.e. non secret. The "secret" input is where goes any actually secret data. The PRF will mix all these values together with a fair dosage of HMAC invocations, into a sequence of bytes of arbitrary length.

In TLS, a key exchange mechanism is used, that results in a "pre-master secret". When RSA key exchange is used, the "pre-master" is generated randomly by the client and encrypted with the server's RSA public key. When using Diffie-Hellman key exchange, the "pre-master" is the encoding of the integer that results from DH ($g^{ab} \pmod p$). When using ECDH (Diffie-Hellman over an elliptic curve), the pre-master secret is the $X$ coordinate of the computed DH point ($abG$). Note that there is no question of hashing at this point: the pre-master secret is a sequence of bytes whose length and contents depend on the used key exchange method.

The master secret is computed from the pre-master secret using the PRF. This is described in section 8. The label is "master secret" and the seed is the concatenation of the client random and server random (these two values are 32-byte each, generated randomly for each handshake, and exchanged in the ClientHello and ServerHello messages). The master secret has length 48 bytes, exactly.

From the master secret are derived the keys and IV needed for symmetric encryption. This is the "key block" that you show. Note that the sizes for the various keys in the key block depend on the negotiated cipher suite. For instance, if the cipher suite uses AES/GCM (e.g. TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), then there is no MAC key (or, equivalently, the MAC key length is 0), since GCM mode ensures both encryption and integrity check with the same key. Key block computation uses the PRF, with this time the master secret as "secret" input; the "seed" is the concatenation of the server and client randoms. Mind the order! This time, the server random comes first.

The Finished messages have contents which are computed with, again, the PRF. The contents of the Finished message are 12 bytes obtained by invoking the PRF with, as "secret" input, the master secret; the "seed" is the hash of all previous handshake messages. The "label" differs depending on who, between the client and the server, sends that specific Finished message. Since the Finished messages are sent after the ChangeCipherSpec, they are encrypted and MACed, using the algorithms and keys which have just been negotiated. In that sense, the keys and nonces (the client and server randoms) are involved multiple times.

Thus, in your description, use of "hkdf" terminology is spurious, as well as the MAC usage, in particular with regards to the Finished messages.

A nice summary of the SSL handshake is this diagram, which is part of the TLS 1.2 standard:

  Client                                               Server

  ClientHello                  -------->
                               <--------      ServerHelloDone
  Finished                     -------->
                               <--------             Finished
  Application Data             <------->     Application Data

         Figure 1.  Message flow for a full handshake

Note that after the ClientKeyExchange message from the client, and before the ChangeCipherSpec, there may be a CertificateVerify message (this is sent by the client when the server requests a client certificate, and the client sends one, and this is not full-static DH or ECDH).

The "hash of all previous handshake messages" that is used as an input to the PRF for the computation of the Finished messages really includes all previous messages for this handshake, starting with the ClientHello. Notably, when the server responds with its own Finished message, the hash used in that second Finished message will include the contents of the first Finished message. Also note that the ChangeCipherSpec message is not formally a handshake message (though it may occur only at very specific times within the handshake) so its contents are not used for these hashes.

The complete TLS handshake is quite complicated, mostly for historical reasons. If you want to formalize its use of cryptographic algorithms, you have little choice but to invest a few hours of reading time to get through all the details. I suggest starting with this answer.

  • $\begingroup$ Thank you very much. I am assuming authentication only. So, there is not client CertificateVerify. Does this implies that the master and session keys are computed consequently? $\endgroup$ Aug 13, 2017 at 17:51
  • $\begingroup$ A server cannot compute the pre-master secret until it has received the ClientKeyExchange from the client, and it will need to compute the pre-master, then master, then key block, in order to decrypt the Finished message from the client. How exactly it does that is up to the implementation. Some will compute everything as soon as the ClientKeyExchange is received; other will delay until the ChangeCipherSpec is received. In any case, computation of pre-master and master are often done in two different functions, to accommodate the plurality of possible key exchange algorithms. $\endgroup$ Aug 13, 2017 at 17:54
  • $\begingroup$ Plus premaster-to-master and master-to-working usually need to be separable because the latter is redone on session resumption (with new nonces) but the former (along with the premaster creation) is not. $\endgroup$ Aug 14, 2017 at 5:38
  • $\begingroup$ @Thomas Pornin one last thing that I find it a bit tricky in identifying the keys used in the Finished encryption. You said: are encrypted and MACed, using the algorithms and keys which have just been negotiated. So the Finished encryption is by using the symmetric keys. What keys exactly involved, this depends on the ciphersuite (e.g. if it is Authenticated Encryption like AES/GCM, no need for MAC keys. But if it is non AE, the Encryption and MAC keys are needed). Sorry but I am really grateful to your comprehensive clarification. $\endgroup$ Aug 14, 2017 at 7:21
  • $\begingroup$ @Thomas Pornin Also, compared to TLS 1.3, in the TLS 1.3, the Finished is computed using HMAC not a PRF as in TLS 1.2?? see link. $\endgroup$ Aug 14, 2017 at 9:57

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.