MTPZ: Handshake, Part 3 - Confirmation Message

11 Aug 2011 - zune - mtpz

Welcome back! Unlike the other sections of the handshake, I was able to reverse engineer this final part with relative ease, due to the fact that much of the process involved code that was used in the other sections.

Let’s take a look at this message.

00000002 03 00 10 CD A5 6A 66 68 25 67 9D 99 CE B2 E9 28 E3 9F B9 ......jfh%g.....(...

Very short, in comparison to the other two messages. As usual, it begins with marker bytes – in this case, 02 03. Following that is a 16-byte block of something (as always, preceded by its length, 00 10).

Message generation

Before we begin the process, we have to recall part 2 of the handshake, which was validation of the device’s response. Once we had decrypted the message and discovered the format, we could see that there was a 32-byte block at the end of the message, which was a CBC-MAC code with SHA-256 applied. For the sake of ease of implementation (or perhaps even just laziness), we didn’t calculate this code on our own, but rather opted to copy the code they sent us. The reason we copy these 32-bytes as opposed to simply ignoring them is because they are necessary to generate our confirmation message.

CBC-MAC/SHA-256 hash:

0000007F E1 15 37 D4 47 8B 1F A8 DB 3D A6 AF DF 18 14 0D 52 47 85 FC 6F E7 54 ...7.G....=......RG..o.T
00001818 36 FD 58 A6 00 06 E9 .6.X....

Firstly, the last 16 bytes of the hash are truncated, so that our hash is conveniently 16 bytes long. Going back to part 2, the message was decrypted by using a hash as the key using what is essentially a modified AES cipher. This time, however, we’re going to use this 16-byte hash as our key for encryption. What are we going to encrypt with this key, though? Seemingly, the software encrypts empty (zero) bytes with our key, providing us with a 16-byte encrypted value.

Encrypted value:

0000005B 52 7A 07 01 24 D4 40 8B F5 15 35 EE 42 7A 81 [Rz..$.@...5.Bz.

Now we create two 16-byte blocks, which will end up storing transformed versions of this encrypted value. The first transformation involves taking the encrypted value and multiplying each of its bytes by two and bitwise OR-ing it with the next byte. Then, if the first byte is negative, it XOR’s the last byte by 0x87. The result of this transformation goes into the first of our new 16-byte blocks.

The second transformation is the same as the first transformation, except instead of taking the bytes of the encrypted value, it takes the bytes of our first, freshly transformed bytes. This transformation is stored in the second byte block.

Block 1:

000000B6 A4 F4 0E 02 49 A8 81 17 EA 2A 6B DC 84 F5 02 .....I....*k....

Block 2:

0000006D 49 E8 1C 04 93 51 02 2F D4 54 D7 B9 09 EA 83 mI....Q./.T.....

Now, we’re going to need our truncated 16-byte CBC-MAC/SHA-256 hash from earlier again since we are going to have to encrypt one more thing. Our second block that we transformed just earlier actually is not even going to be used (it would be used in case our hash was longer than 16 bytes, but since it’s not, and never will be, this second block is effectively useless). What we do with the first block is XOR the last byte with 01, and then encrypt this using our 16-byte hash as a key. Once this is done, we end up with another 16-byte encrypted value.

Encrypted value:

000000CD A5 6A 66 68 25 67 9D 99 CE B2 E9 28 E3 9F B9 ..jfh%g.....(...

Bingo! This is the exact 16-byte block that is sent in the confirmation message.

What the device presumably does is perform this same process and compare its own calculated value with the value we send in the confirmation message. If the two values are the same, then the handshake is complete and the device unlocks itself for synchronization and other matters.

What’s next?

So, after all these months, I’ve managed to completely reverse engineer the handshake in its entirety. However, that doesn’t mean that everything’s fantastic and my work is done. There’s still the task of actually implementing this handshake into the libmtp project so that any media player that uses that will be able to take advantage of it.

Stay tuned for blog posts about my progress on that front! All in all, we should be able to look forward to Zune support on Linux fairly soon.

blog comments powered by Disqus