Can someone make sure I'm creating my Client finished message properly as I've been working at this for days and keep getting a Bad record MAC error and I have no idea what I'm doing wrong.

  1. First step is creating the 12 bytes of verify data. This is created using the PRF with the master secret, the label "client finished", and the sha256 digest of all the previous handshake messages. (The cipher suite is TLS_RSA_WITH_AES_256_CBC_SHA256).

  2. The 12 bytes are then placed in the finished handshake record with a handshake type field and 3byte length field.

  3. These 16 bytes are then passed through the sha256 HMAC, which has as input:

    • the sequence number (for a finished message this is number 3 as the previous 3 messages were the client hello, the client key exchange, and the change cipher spec)
    • the type - 0x14
    • the version - 0x0303
    • the length -16
    • the 16 bytes of 'plain text data'
  4. This produces 32 bytes of hash which are tagged onto the 16 bytes of data, creating 48 bytes before padding (49 if you include the padding length field). And so we add 15 bytes of padding with value 0x0F. This takes the total length to 64 bytes (a multiple of the block size 16).

  5. The 64 bytes are then encrypted with using the IV and the client write key.

  6. The 64 bytes, preceded by the 16 byte IV are sent to the server - 80 bytes in total.

What am I doing wrong?


Thanks for the pointers guys! Don't know why I hadn't thought of debugging another implementation to find where I was going wrong. Turns out the library I was using for calculating my SHA256 HMAC (I was using Nettle) was a bit buggy. I imported another library and managed to get it all working!

  • 2
    $\begingroup$ Take another implementation of TLS, configure the same cipher suite, use identical keys and randoms on both sides, print out all intermediate values and compare. Just debugging by describing the protocol to us is unlikely to help. $\endgroup$ – Maarten Bodewes Sep 5 '15 at 12:05
  • $\begingroup$ possibly step 5: "the 64 bytes are then encrypted with using the IV and the client write key". You don't mention computing the GCM tag or the HMAC tag required for this record-layer encryption. This would explain the "bad record MAC" answer. $\endgroup$ – SEJPM Sep 5 '15 at 13:03
  • $\begingroup$ @SEJPM the identified suite uses HMAC which OP described almost correctly in steps 3 and 4. $\endgroup$ – dave_thompson_085 Sep 6 '15 at 15:59

The sequence_number resets at CCS, so for Finished it's zero (for 8 bytes). Also record type for handshake is 0x16, and to be clear the record length is 2 bytes, in this case 00 10, and "the IV" should be random for each record. As a mnemonic, the RHUL group's Lucky Thirteen attack uses the fact that the HMAC pseudoheader is 13 bytes.

That said I agree with @Maarten's comment: debug against another implementation. Especially an open source one like OpenSSL/LibreSSL/BoringSSL or GnuTLS or Java.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.