Hello,

I'm studying this protocol and coding some samples. Unfortunately I'm stuck at the very end of the handshake, more exactly, in the Finished message, sent by the client.

I really hope somebody can follow me on this:

Looking into the RFC,

Code:
struct {
   opaque verify_data[12];
} Finished;

verify_data
   PRF(master_secret, finished_label, MD5(handshake_messages) +
   SHA-1(handshake_messages)) [0..11];

finished_label
   For Finished messages sent by the client, the string "client
   finished". For Finished messages sent by the server, the
   string "server finished".

handshake_messages
   All of the data from all handshake messages up to but not
   including this message.
So, only the first 12 bytes of the result of PRF() are used. OK.

Code:
enum {
    hello_request(0), client_hello(1), server_hello(2),
    certificate(11), server_key_exchange (12),
    certificate_request(13), server_hello_done(14),
    certificate_verify(15), client_key_exchange(16),
    finished(20), (255)
} HandshakeType;

struct {
    HandshakeType msg_type;
    uint24 length;
    select (HandshakeType) {
        case hello_request:       HelloRequest;
        case client_hello:        ClientHello;
        case server_hello:        ServerHello;
        case certificate:         Certificate;
        case server_key_exchange: ServerKeyExchange;
        case certificate_request: CertificateRequest;
        case server_hello_done:   ServerHelloDone;
        case certificate_verify:  CertificateVerify;
        case client_key_exchange: ClientKeyExchange;
        case finished:            Finished;
    } body;
} Handshake;
Then according to that, these 12 bytes should put in a handshake record, after the handshake type and the message length.

The following paragraph doesn't come next in the document (I really hate its disposition):

At this point, a change cipher spec message is sent by the client,
and the client copies the pending Cipher Spec into the current Cipher
Spec. The client then immediately sends the finished message under
the new algorithms, keys, and secrets.
In response, the server will
send its own change cipher spec message, transfer the pending to the
current Cipher Spec, and send its finished message under the new
Cipher Spec. At this point, the handshake is complete and the client
and server may begin to exchange application layer data.
The Finished message must be encrypted with the selected Cipher Spec, right?

Now comes the tricky part. I'm using TLS_RSA_WITH_RC4_128_MD5 as my Cipher Spec, and did a trace with Wireshark for a browser using the same Spec, and connecting to the same server. Look what I got:

-from client to server-

Code:
TLSv1 Record Layer: Handshake Protocol: Client Key Exchange
  Content Type: Handshake (22)
  Version: TLS 1.0 (0x0301)
  Length: 262
  Handshake Protocol: Client Key Exchange
    Handshake Type: Client Key Exchange (16)
    Length: 258

TLSv1 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
  Content Type: Change Cipher Spec (20)
  Version: TLS 1.0 (0x0301)
  Length: 1
  Change Cipher Spec Message (0x01)

TLSv1 Record Layer: Handshake Protocol: Encrypted Handshake Message
  Content Type: Handshake (22)
  Version: TLS 1.0 (0x0301)
  Length: 32
  Handshake Protocol: Encrypted Handshake Message (here goes the Finished message)
**first two records, only for reference.

I have no idea how the encrypted message (32 bytes) is calculated. If the browser applies RC4 with a key size of 16 bytes over the Finished message (12 bytes plus a 4-bytes header), the resulting encrypted string won't be 32 bytes in size. So it's obvious I've forgot something.

On the other side, I get a bunch of keys from the "key expansion":

Code:
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_secret[SecurityParameters.hash_size]
   server_write_MAC_secret[SecurityParameters.hash_size]
   client_write_key[SecurityParameters.key_material_length]
   server_write_key[SecurityParameters.key_material_length]
   client_write_IV[SecurityParameters.IV_size]
   server_write_IV[SecurityParameters.IV_size]
Feeling stupid but, could somebody tell me which key should I use with the selected Cipher Spec? The available documentation is not clear and I'm really tired of taking assumptions on this.


Thank you very much!