!!! Overview
[{$pagename}] describes a Step within the [TLS Handshake] process.

%%information
[{$pagename}] has been removed in [TLS 1.3]
%%

The [{$pagename}] is sent by the [User-agent] immediately after the [CertificateRequest] if it was sent or otherwise immediately after the [ServerHelloDone] message. [{$pagename}] has two variants, one for when RSA is used as the [Key-Exchange] algorithm, and one for when Diffie-Hellman is used.

%%information
This information is based on [TLS 1.0]
%%

The [Key-Exchange] choice is part of the [Cipher Suites] defined for [TLS].

The goal of the [{$pagename}] is to perform a [Key-Exchange] of the [premaster Secret] so each side can independently [Derive the Master Secret].

The [{$pagename}] handshake header is not encrypted.


Structure of the [{$pagename}] message:
%%prettify 
{{{
struct {
    select (KeyExchangeAlgorithm) {
        case rsa: EncryptedPreMasterSecret;
        case diffie_hellman: ClientDiffieHellmanPublic;
    } exchange_keys;
} ClientKeyExchange;
}}} /%


! [RSA]
If RSA is being used for [key-Exchange] and [authentication], the [user-agent] generates a 48-byte [premaster Secret], encrypts it using the [public Key] from the certificate sent in the [serverCertificate] message or the temporary RSA key provided in a [ServerKeyExchange] message, and sends the result in an encrypted premaster secret message. This structure is a variant of the [ClientKeyExchange] message, not a message in itself.

Structure of the RSA message:
%%prettify 
{{{
struct {
    ProtocolVersion client_version;
    opaque random[46];
} PreMasterSecret;
struct {
    public-key-encrypted PreMasterSecret pre_master_secret;
} EncryptedPreMasterSecret;
}}} /%
Where the client_version is the latest (newest) version supported by the [user-agent] and is intended to prevent version roll-back by a [Man-In-The-Middle] attack. Upon receiving the premaster secret from the [user-agent], the server should check that this value matches the value transmitted by the [user-agent] in the [clientHello] message. While this may indeed work for [TLS] but in [SSLv3] implementations use of the __negotiated version__ is common and thus checking this value creates incompatibility problems.

The random is 46 random bytes generated by a cryptographic [Pseudorandom number generator] which is specified within [RFC 2246].

Combined these 48 bytes provide the [User-agent]’s input into the [Master Secret] from which the session keys will be derived.

The [PKCS] encoding is needed to pad the [{$pagename}] to the length of the [RSA] key. The [{$pagename}] consists of 0x00, 0x02, randomly generated pad bytes, 0x00 and finally the message, in our example, the [{$pagename}]. The number of pad bytes is chosen to make the resulting message the same length as the key. The number of pad bytes must be at least 8, so the minimum pad length is 11 bytes. 

In theory fragmentation of the message may be necessary, but in practice [RSA] keys are longer than 59 bytes – the length of the [{$pagename}] secret combined with the minimum pad – so this is not done.

As the [{$pagename}] message is encrypted with the server’s [Public Key], only the holder of the [Private Key] can decrypt the message. This means that although the [certificate] may be sent by any party, only servers that hold the [Private Key] can successfully complete this part of the handshake. This also protects the version number from a [Man-In-The-Middle] attack, as the random bytes cannot be recovered from the message for inclusion in a modified message, and if they do not match the key material will not match on both sides and the handshake will fail when when the finished messages are processed. However as discussed above, this protection is largely useless for [SSLv3].

! [Diffie-Hellman]
When Diffie-Hellman is used the client [Key-Exchange] message consists of the handshake header followed by the [Diffie-Hellman] public value. This allows both the client and server to calculate the same [Premaster Secret].

In the case where client authentication is used, and the client certificate that was sent, in the [CertificateRequest] message, contains a [Diffie-Hellman] public value that uses the parameters specified by the server, then the public value is omitted from this message as it is already known. In this case the handshake header comprises the message entirely.

Structure of the [Diffie-Hellman] part of message:
%%prettify 
{{{
enum { implicit, explicit } PublicValueEncoding;
struct {
    select (PublicValueEncoding) {
        case implicit: struct { };
        case explicit: opaque dh_Yc<1..2^16-1>;
     } dh_public;
} ClientDiffieHellmanPublic;
}}} /%
Where:
* dh_Yc - The client's [Diffie-Hellman] public value (Yc).
* implicit - If the client certificate already contains a suitable Diffie-Hellman key, then Yc is implicit and does not need to be sent again. In this case, the [{$pagename}] message will be sent, but will be empty.
* explicit - Yc needs to be sent.

!! More Information
There might be more information for this subject on one of the following:
[{ReferringPagesPlugin before='*' after='\n' }]
----
* [#1] - [Client Key Exchange|http://www.umsl.edu/~sbxvd/Client%20Key%20Exchange.html|target='_blank'] - based on information obtained 2013-04-10