Clarification needed in TLS 1.2 key derivation process 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 +
                  SecurityParameters.client_random);

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

  client_write_MAC_key[SecurityParameters.mac_key_length]
  server_write_MAC_key[SecurityParameters.mac_key_length]
  client_write_key[SecurityParameters.enc_key_length]
  server_write_key[SecurityParameters.enc_key_length]
  client_write_IV[SecurityParameters.fixed_iv_length]
  server_write_IV[SecurityParameters.fixed_iv_length]



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:

$$\operatorname{enc}_{\mathit{kc}_\mathrm{data}}(\mathit{data})$$

My questions are:


Is my interpretation for the TLS 1.2 key generation and usage correct?
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?
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                  --------&gt;
                                                  ServerHello
                                                 Certificate*
                                           ServerKeyExchange*
                                          CertificateRequest*
                               &lt;--------      ServerHelloDone
  Certificate*
  ClientKeyExchange
  CertificateVerify*
  [ChangeCipherSpec]
  Finished                     --------&gt;
                                           [ChangeCipherSpec]
                               &lt;--------             Finished
  Application Data             &lt;-------&gt;     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.