What causes first block of AES decryption to be garbled, even with correct IV?

Loading...

What causes first block of AES decryption to be garbled, even with correct IV?

I am attempting to duplicate wireshark's packet capture decryption for a TLS HTTP session, where I control the private key of the server.
The cipher suite number is 0x00002f, TLS_RSA_AES_128_CBC_SHA
I wrote a utility that takes apart the packet captures using libpcap, and so far can match what the logs from wireshark say they have in terms of MAC keys, Write keys, and IV's; printing out the binary data as hex characters.
Visually, I can confirm that the keyblock and ciphertext are identical to what wireshark's log display.
However, after I perform the following decryption steps:
... decrypt pre_master_secret, generate keyblock
... initialize cipher context

EVP_CIPHER_CTX_init(&myevp);
if (!EVP_CipherInit_ex(&myevp, cipher, NULL, wKey, IV, 0))
    LogError("evp_cipherinit_ex:", ERR_error_string(ERR_get_error(), NUL));

dec = EVP_DecryptUpdate(&myevp, outb, outlen, data, datalen);
totalcount += outlen;

if (!dec) 
    LogError("evp_decryptupdate:", ERR_error_string(ERR_get_error(), NUL));

if (dec && blocklen != 1) {
    dec = EVP_DecryptFinal_ex(&myevp, outb + totalcount, outlen);
    totalcount += outlen;    
}

...get padding from last bit of outb, and remove padding from outb (plaintext)
...remove the MAC from the plaintext

The resultant plaintext I get is identical to what wireshark spits out in their logs, with the execption of the first block of decrypted data.
I know that in general, this is usually caused by not having a correct initialization vector when you begin the decryption.  However, all my computed keyblock values seem correct (that is to say, they jive with what wireshark is spitting out).
here's the first few blocks of what wireshark shows...
Plaintext[432]:
47 45 54 20 2f 68 65 6c 6c 6f 2e 68 74 6d 6c 20
48 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20
31 37 32 2e 31 36 2e 32 34 34 2e 31 39 36 0d 0a
...

and mine
plaintext_update[432]
e1 a2 f4 b3 2a 93 d1 c4 1b f4 60 d8 c9 92 03 25
48 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20
31 37 32 2e 31 36 2e 32 34 34 2e 31 39 36 0d 0a
...

It's just that first block.  I can verify before the Decryption step that the evp context has the correct original IV value and the current are there.
LogData("evp oiv", &myevp->evp.oiv, &myevp->evp.cipher->iv_len);
LogData("evp iv", &myevp->evp.iv, &myevp->evp.cipher->iv_len);

here's the one from wireshark
Client Write IV[16]:
8b 55 c0 c5 3c 77 dc 91 09 22 18 8b 0c 53 16 66

here's mine
evp iv[16]
8b 55 c0 c5 3c 77 dc 91 09 22 18 8b 0c 53 16 66

Likewise, the keys are the same. I don't think I need to illustrate those values, as the remaining blocks do decrypt correctly.
I've also checked to make sure that first block isn't gzipped, or whatever.  I checked the wireshark code, and they are doing the same equivalent stuff I'm doing, albeit in libgpgcrypt.  
Anybody ever seen anything like this?

Solutions/Answers:

Answer 1:

For TLS the IV for the first packet is generated from the shared secrets; quoting the RFC 2246:

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]

I suppose that you have generated these, and checked them?
(You need 6 ·16 bytes in your cipher suite, and the last 32 are the IV’s, one for each direction.)

Also, the IV for the next TLS-record is the last cipher text block of the previous record in the same direction. So you need to keep track of these as well. So the first IV is never sent, and you need to keep updating the IV as we get new packets in, or send new ones.

References

Loading...