fix one too small
[RRG-proxmark3.git] / client / src / cmdlfhitag.c
blob24b2c3fa4c61e7d0fb4a800724efbf542069dc22
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
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.
8 //
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 //-----------------------------------------------------------------------------
16 // Low frequency Hitag support
17 //-----------------------------------------------------------------------------
18 #include "cmdlfhitag.h"
19 #include <ctype.h>
20 #include "cmdparser.h" // command_t
21 #include "comms.h"
22 #include "cmdtrace.h"
23 #include "commonutil.h"
24 #include "fileutils.h" // savefile
25 #include "protocols.h" // defines
26 #include "cliparser.h"
27 #include "crc.h"
28 #include "graph.h" // MAX_GRAPH_TRACE_LEN
29 #include "lfdemod.h"
30 #include "cmddata.h" // setDemodBuff
31 #include "pm3_cmd.h" // return codes
32 #include "hitag2/hitag2_crypto.h"
33 #include "util_posix.h" // msclock
34 #include "cmdlfhitaghts.h"
36 static int CmdHelp(const char *Cmd);
38 static const char *getHitagTypeStr(uint32_t uid) {
39 //uid s/n ********
40 uint8_t type = (uid >> 4) & 0xF;
41 switch (type) {
42 case 1:
43 return "PCF 7936";
44 case 2:
45 return "PCF 7946";
46 case 3:
47 return "PCF 7947";
48 case 4:
49 return "PCF 7942/44";
50 case 5:
51 return "PCF 7943";
52 case 6:
53 return "PCF 7941";
54 case 7:
55 return "PCF 7952";
56 case 9:
57 return "PCF 7945";
58 default:
59 return "";
63 uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit) {
64 if (nbit < 9) {
65 return 2;
67 return (CRC8Hitag1Bits(d, nbit) == 0);
72 static size_t nbytes(size_t nbits) {
73 return (nbits / 8) + ((nbits % 8) > 0);
77 static int CmdLFHitagList(const char *Cmd) {
78 return CmdTraceListAlias(Cmd, "lf hitag", "hitag2");
80 uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
81 if (!got) {
82 PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
83 return PM3_EMALLOC;
86 // Query for the actual size of the trace
87 PacketResponseNG resp;
88 if (!GetFromDevice(BIG_BUF, got, PM3_CMD_DATA_SIZE, 0, NULL, 0, &resp, 2500, false)) {
89 PrintAndLogEx(WARNING, "command execution time out");
90 free(got);
91 return PM3_ETIMEOUT;
94 uint16_t traceLen = resp.arg[2];
95 if (traceLen > PM3_CMD_DATA_SIZE) {
96 uint8_t *p = realloc(got, traceLen);
97 if (p == NULL) {
98 PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
99 free(got);
100 return PM3_EMALLOC;
102 got = p;
103 if (!GetFromDevice(BIG_BUF, got, traceLen, 0, NULL, 0, NULL, 2500, false)) {
104 PrintAndLogEx(WARNING, "command execution time out");
105 free(got);
106 return PM3_ETIMEOUT;
110 PrintAndLogEx(NORMAL, "recorded activity (TraceLen = %d bytes):");
111 PrintAndLogEx(NORMAL, " ETU :nbits: who bytes");
112 PrintAndLogEx(NORMAL, "---------+-----+----+-----------");
114 int i = 0;
115 int prev = -1;
116 int len = strlen(Cmd);
118 char filename[FILE_PATH_SIZE] = { 0x00 };
119 FILE *f = NULL;
121 if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
123 memcpy(filename, Cmd, len);
125 if (strlen(filename) > 0) {
126 f = fopen(filename, "wb");
127 if (!f) {
128 PrintAndLogEx(ERR, "Error: Could not open file [%s]", filename);
129 return PM3_EFILE;
133 for (;;) {
135 if (i >= traceLen) { break; }
137 bool isResponse;
138 int timestamp = *((uint32_t *)(got + i));
139 if (timestamp & 0x80000000) {
140 timestamp &= 0x7fffffff;
141 isResponse = 1;
142 } else {
143 isResponse = 0;
146 int parityBits = *((uint32_t *)(got + i + 4));
147 // 4 bytes of additional information...
148 // maximum of 32 additional parity bit information
150 // TODO:
151 // at each quarter bit period we can send power level (16 levels)
152 // or each half bit period in 256 levels.
154 int bits = got[i + 8];
155 int len = nbytes(got[i + 8]);
157 if (len > 100) {
158 break;
160 if (i + len > traceLen) { break;}
162 uint8_t *frame = (got + i + 9);
164 // Break and stick with current result if buffer was not completely full
165 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
167 char line[1000] = "";
168 int j;
169 for (j = 0; j < len; j++) {
171 int offset = j * 4;
172 //if((parityBits >> (len - j - 1)) & 0x01) {
173 if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
174 snprintf(line + offset, sizeof(line) - offset, "%02x! ", frame[j]);
175 } else {
176 snprintf(line + offset, sizeof(line) - offset, "%02x ", frame[j]);
180 PrintAndLogEx(NORMAL, " +%7d: %3d: %s %s",
181 (prev < 0 ? 0 : (timestamp - prev)),
182 bits,
183 (isResponse ? "TAG" : " "),
184 line);
186 if (f) {
187 fprintf(f, " +%7d: %3d: %s %s\n",
188 (prev < 0 ? 0 : (timestamp - prev)),
189 bits,
190 (isResponse ? "TAG" : " "),
191 line);
194 prev = timestamp;
195 i += (len + 9);
198 if (f) {
199 fclose(f);
200 PrintAndLogEx(NORMAL, "Recorded activity successfully written to file: %s", filename);
203 free(got);
204 return PM3_SUCCES;
208 static void print_hitag2_paxton(const uint8_t *data) {
210 // if the pwd isn't..
211 if (memcmp(data + 4, "\xBD\xF5\xE8\x46", 4)) {
212 return;
215 uint64_t num = 0;
216 uint64_t paxton_id = 0;
217 uint16_t skip = 48;
218 uint64_t mask = 0xF80000000000;
220 uint64_t bytes = bytes_to_num(data + 16, 6);
222 for (int j = 0; j < 8; j++) {
224 num = bytes & mask;
225 skip -= 5;
226 mask >>= 5;
228 uint8_t digit = (num >> skip & 0xF);
229 paxton_id = (paxton_id * 10) + digit;
231 if (j == 5) {
232 skip -= 2;
233 mask >>= 2;
238 const uint8_t isocard = 0x06;
239 const uint8_t fob = 0x03;
240 const uint8_t iso_magstripe = 0x02;
243 // [=] 4/0x04 | 39 04 21 1C | 9.!. | RW | User
244 // [=] 5/0x05 | AC 3F 00 06 | .?.. | RW | User
246 char formfactor[16];
247 switch (data[23]) {
248 case 0x06: {
249 strcat(formfactor, "isocard");
250 break;
252 case 0x03: {
253 strcat(formfactor, "fob");
254 break;
256 case 0x02: {
257 strcat(formfactor, "iso magstripe");
258 break;
260 default: {
261 snprintf(formfactor, sizeof(formfactor), "unk: %02x", data[23]);
262 break;
266 PrintAndLogEx(INFO, "");
267 PrintAndLogEx(INFO, "--- " _CYAN_("Possible de-scramble patterns") " -------------");
268 PrintAndLogEx(SUCCESS, "Paxton id... %" PRIu64 " | 0x%" PRIx64 " ( %s )", paxton_id, paxton_id, formfactor);
269 PrintAndLogEx(INFO, "");
272 static void print_hitag2_configuration(uint32_t uid, uint8_t config) {
274 PrintAndLogEx(NORMAL, "");
275 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
276 PrintAndLogEx(SUCCESS, "UID...... " _GREEN_("%08X"), uid);
277 PrintAndLogEx(SUCCESS, "TYPE..... " _GREEN_("%s"), getHitagTypeStr(uid));
279 char msg[100];
280 memset(msg, 0, sizeof(msg));
282 uint8_t bits[8 + 1] = {0};
283 num_to_bytebits(config, 8, bits);
284 const char *bs = sprint_bytebits_bin(bits, 8);
286 //configuration byte
287 // PrintAndLogEx(SUCCESS, "");
288 PrintAndLogEx(SUCCESS, "Config... " _YELLOW_("0x%02X"), config);
289 PrintAndLogEx(SUCCESS, " %s", bs);
290 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 0, 4, "RFU"));
292 if (config & 0x8) {
293 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_YELLOW, bs, 8, 4, 1, "Crypto mode"));
294 } else {
295 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 4, 1, "Password mode"));
298 // version
299 uint8_t foo = ((config & 0x6) >> 1);
300 switch (foo) {
301 case 0:
302 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Public mode B, Coding: biphase"));
303 break;
304 case 1:
305 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Public mode A, Coding: manchester"));
306 break;
307 case 2:
308 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Public mode C, Coding: biphase"));
309 break;
310 case 3:
311 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "Hitag 2"));
312 break;
315 // encoding
316 if (config & 0x01) {
317 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "Biphase"));
318 } else {
319 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "Manchester"));
321 PrintAndLogEx(NORMAL, "");
324 const char *annotation[] = {
325 "UID", "Pwd", "Key/Pwd", "Config",
326 "User", "User", "User", "User",
327 "User", "User", "User", "User"
330 static void print_hitag2_blocks(uint8_t *d, uint16_t n) {
332 PrintAndLogEx(INFO, "");
333 PrintAndLogEx(INFO, "----------------------------------------------");
334 PrintAndLogEx(INFO, " # | data | ascii | lck | Info");
335 PrintAndLogEx(INFO, "--------+-------------+-------+-----+---------");
337 uint8_t config = d[HITAG2_CONFIG_OFFSET];
338 uint8_t blocks = (n / HITAG_BLOCK_SIZE);
340 for (uint8_t i = 0; i < blocks; ++i) {
342 char lckstr[20] = {0};
343 sprintf(lckstr, " ");
345 switch (i) {
346 case 0:
347 sprintf(lckstr, "%s", _RED_("L "));
348 break;
349 case 1:
350 if (config & 0x80) {
351 sprintf(lckstr, "%s", _RED_("L "));
352 } else {
353 sprintf(lckstr, "%s", _GREEN_("RW"));
355 break;
356 case 2:
357 if (config & 0x80) {
358 if (config & 0x8) {
359 sprintf(lckstr, "%s", _RED_("L "));
360 } else {
361 sprintf(lckstr, "%s", _RED_("R "));
363 } else {
364 sprintf(lckstr, "%s", _GREEN_("RW"));
366 break;
367 case 3:
368 // OTP Page 3.
369 if (config & 0x40) {
370 sprintf(lckstr, "%s", _RED_("R "));
371 //. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE"));
372 } else {
373 sprintf(lckstr, "%s", _GREEN_("RW"));
375 break;
376 case 4:
377 case 5:
378 if (config & 0x20) {
379 sprintf(lckstr, "%s", _RED_("R "));
380 } else {
381 sprintf(lckstr, "%s", _GREEN_("RW"));
383 break;
384 case 6:
385 case 7:
386 if (config & 0x10) {
387 sprintf(lckstr, "%s", _RED_("R "));
388 } else {
389 sprintf(lckstr, "%s", _GREEN_("RW"));
391 break;
392 default:
393 break;
396 PrintAndLogEx(INFO, "%2d/0x%02X | %s| %s | %s | %s"
399 , sprint_hex(d + (i * HITAG_BLOCK_SIZE), HITAG_BLOCK_SIZE)
400 , sprint_ascii(d + (i * HITAG_BLOCK_SIZE), HITAG_BLOCK_SIZE)
401 , lckstr
402 , annotation[i]
405 PrintAndLogEx(INFO, "--------+-------------+-------+-----+---------");
406 PrintAndLogEx(INFO, " "_RED_("L") " = Locked, "_GREEN_("RW") " = Read Write, R = Read Only");
407 PrintAndLogEx(INFO, " FI = Fixed / Irreversible");
408 PrintAndLogEx(INFO, "----------------------------------------------");
411 // Annotate HITAG protocol
412 void annotateHitag1(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response) {
415 static struct {
416 enum {
417 STATE_HALT,
418 STATE_START_AUTH,
419 STATE_AUTH,
420 STATE_START_ENCRYPTED,
421 STATE_ENCRYPTED,
422 } state;
423 uint32_t uid;
424 uint64_t cipher_state;
425 uint8_t plainlen;
426 uint8_t plain[30];
427 bool found_key;
428 uint64_t key;
429 } _ht2state;
431 void annotateHitag2_init(void) {
432 _ht2state.state = STATE_HALT;
433 _ht2state.uid = 0;
434 _ht2state.cipher_state = 0;
435 _ht2state.plainlen = 0;
436 memset(_ht2state.plain, 0, sizeof(_ht2state.plain));
439 static void rev_msb_array(uint8_t *d, uint8_t n) {
440 for (uint8_t i = 0 ; i < n ; i++) {
441 d[i] = reflect8(d[i]);
445 // param nrar must be 8 bytes
446 static bool ht2_check_cryptokeys(const uint64_t *keys, const uint32_t keycount, const uint8_t *nrar) {
448 if (keys == NULL || keycount == 0 || nrar == NULL) {
449 return false;
452 uint32_t iv = REV32((nrar[3] << 24) + (nrar[2] << 16) + (nrar[1] << 8) + nrar[0]);
453 uint32_t ar = (nrar[4] << 24) + (nrar[5] << 16) + (nrar[6] << 8) + nrar[7];
455 bool found = false;
456 for (uint32_t i = 0; i < keycount; i++) {
458 uint64_t key = keys[i];
459 key = BSWAP_48(key);
460 key = REV64(key);
462 hitag_state_t hs2;
463 ht2_hitag2_init_ex(&hs2, key, _ht2state.uid, iv);
465 uint32_t tbits = ht2_hitag2_nstep(&hs2, 32);
466 if ((ar ^ tbits) == 0xFFFFFFFF) {
467 _ht2state.found_key = true;
468 _ht2state.key = key;
469 found = true;
470 break;
473 return found;
476 static int ht2_check_dictionary(uint32_t key_count, uint8_t *keys, uint8_t keylen, uint32_t *found_idx) {
478 lf_hitag_data_t packet;
479 memset(&packet, 0, sizeof(packet));
481 uint8_t *pkeys = keys;
483 while (key_count--) {
485 if (keylen == 4) {
486 packet.cmd = RHT2F_PASSWORD;
487 memcpy(packet.pwd, pkeys, keylen);
488 } else {
489 packet.cmd = RHT2F_CRYPTO;
490 memcpy(packet.key, pkeys, keylen);
493 pkeys += keylen;
495 clearCommandBuffer();
496 SendCommandNG(CMD_LF_HITAG_READER, (uint8_t *)&packet, sizeof(packet));
497 PacketResponseNG resp;
498 if (WaitForResponseTimeout(CMD_LF_HITAG_READER, &resp, 2000) == false) {
499 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
500 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
501 return PM3_ETIMEOUT;
504 if (resp.status != PM3_SUCCESS) {
505 *found_idx = *found_idx + 1;
506 continue;
508 return PM3_SUCCESS;
510 return PM3_ESOFT;
514 bool hitag2_get_plain(uint8_t *plain, uint8_t *plen) {
515 if (_ht2state.state == STATE_ENCRYPTED || _ht2state.state == STATE_START_ENCRYPTED) {
516 if (_ht2state.found_key) {
517 *plen = _ht2state.plainlen;
518 memcpy(plain, _ht2state.plain, _ht2state.plainlen);
519 return true;
522 return false;
525 // HITAG 2 commands
526 #define HITAG2_BINSTR_START_AUTH "11000" // get UID and/or start the authentication process
527 #define HITAG2_BINSTR_READ_PAGE "11" // read page after auth
528 #define HITAG2_BINSTR_READ_PAGE_INVERTED "01" // as read page but all bits inverted
529 #define HITAG2_BINSTR_WRITE_PAGE "10" // write page after auth
530 #define HITAG2_BINSTR_HALT "00" // silence currently authenticated tag
532 static uint8_t hitag2_get_page(const char *bs) {
533 if ((memcmp(bs + 2, "000", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "111", 3) == 0)) {
534 return 0;
536 if ((memcmp(bs + 2, "001", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "110", 3) == 0)) {
537 return 1;
539 if ((memcmp(bs + 2, "010", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "101", 3) == 0)) {
540 return 2;
542 if ((memcmp(bs + 2, "011", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "100", 3) == 0)) {
543 return 3;
545 if ((memcmp(bs + 2, "100", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "011", 3) == 0)) {
546 return 4;
548 if ((memcmp(bs + 2, "101", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "010", 3) == 0)) {
549 return 5;
551 if ((memcmp(bs + 2, "110", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "001", 3) == 0)) {
552 return 6;
554 if ((memcmp(bs + 2, "111", 3) == 0) && (memcmp(bs + 2 + 3 + 2, "000", 3) == 0)) {
555 return 7;
557 return 255;
560 void hitag2_annotate_plain(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, uint8_t bits) {
562 if (cmdsize == 0) {
563 return;
566 char *binstr = (char *)calloc((cmdsize * 8) + 1, sizeof(uint8_t));
567 if (binstr == NULL) {
568 return;
571 bytes_2_binstr(binstr, cmd, cmdsize);
573 size_t bn = strlen(binstr);
574 if (bits) {
575 if (cmdsize == 1) {
576 bn = bits;
577 } else if (cmdsize > 1) {
578 bn = ((cmdsize - 1) * 8) + bits;
582 switch (bn) {
583 case 5: {
584 snprintf(exp, size, " ");
585 break;
587 case 10: {
588 if (memcmp(binstr, HITAG2_BINSTR_HALT, 2) == 0) {
589 snprintf(exp, size, " ");
590 break;
593 uint8_t page = hitag2_get_page(binstr);
595 if (memcmp(binstr, HITAG2_BINSTR_READ_PAGE, 2) == 0) {
596 snprintf(exp, size, "READ PAGE (" _MAGENTA_("%u") ")", page);
597 break;
600 if (memcmp(binstr, HITAG2_BINSTR_READ_PAGE_INVERTED, 2) == 0) {
601 snprintf(exp, size, "READ PAGE INV (" _MAGENTA_("%u") ")", page);
602 break;
605 if (memcmp(binstr, HITAG2_BINSTR_WRITE_PAGE, 2) == 0) {
606 snprintf(exp, size, "WRITE PAGE (" _MAGENTA_("%u") ")", page);
607 break;
609 break;
611 case 32: { // password or data
612 snprintf(exp, size, " ");
613 break;
615 case 64: { // crypto handshake
616 snprintf(exp, size, " ");
617 break;
619 default: {
620 snprintf(exp, size, " ");
621 break;
624 free(binstr);
627 void annotateHitag2(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, uint8_t bits, bool is_response, const uint64_t *keys, uint32_t keycount, bool isdecrypted) {
629 if (cmdsize == 0) {
630 return;
633 char *binstr = (char *)calloc((cmdsize * 8) + 1, sizeof(uint8_t));
634 if (binstr == NULL) {
635 return;
638 bytes_2_binstr(binstr, cmd, cmdsize);
640 size_t bn = strlen(binstr);
641 if (bits) {
642 if (cmdsize == 1) {
643 bn = bits;
644 } else if (cmdsize > 1) {
645 bn = ((cmdsize - 1) * 8) + bits;
649 memcpy(_ht2state.plain, cmd, cmdsize);
650 _ht2state.plainlen = cmdsize;
652 if (_ht2state.state == STATE_ENCRYPTED || _ht2state.state == STATE_START_ENCRYPTED) {
654 if (_ht2state.found_key && isdecrypted == false) {
655 ht2_hitag2_cipher_transcrypt(&_ht2state.cipher_state, _ht2state.plain, bn / 8, bn % 8);
659 // 11000 AUTH only one with 5 bits. cmdsize 1
660 switch (bn) {
661 case 5: {
662 annotateHitag2_init();
664 if (memcmp(binstr, HITAG2_BINSTR_START_AUTH, 5) == 0) {
665 snprintf(exp, size, "START AUTH");
666 _ht2state.state = STATE_START_AUTH;
667 } else {
668 snprintf(exp, size, "?");
670 break;
672 case 10: {
674 if (isdecrypted == false && _ht2state.state == STATE_ENCRYPTED) {
675 snprintf(exp, size, "ENC CMD");
676 break;
679 if (memcmp(binstr, HITAG2_BINSTR_HALT, 2) == 0) {
680 snprintf(exp, size, "HALT");
681 _ht2state.state = STATE_HALT;
682 break;
685 uint8_t page = hitag2_get_page(binstr);
687 if (memcmp(binstr, HITAG2_BINSTR_READ_PAGE, 2) == 0) {
688 snprintf(exp, size, "READ PAGE (" _MAGENTA_("%u") ")", page);
689 break;
692 if (memcmp(binstr, HITAG2_BINSTR_READ_PAGE_INVERTED, 2) == 0) {
693 snprintf(exp, size, "READ PAGE INV (" _MAGENTA_("%u") ")", page);
694 break;
697 if (memcmp(binstr, HITAG2_BINSTR_WRITE_PAGE, 2) == 0) {
698 snprintf(exp, size, "WRITE PAGE (" _MAGENTA_("%u") ")", page);
699 break;
701 break;
704 case 32: { // password or data
705 if (_ht2state.state == STATE_START_AUTH) {
706 if (is_response) {
707 snprintf(exp, size, "UID");
708 uint8_t uid[4];
709 memcpy(uid, cmd, 4);
710 rev_msb_array(uid, 4);
711 _ht2state.uid = MemLeToUint4byte(uid);
712 } else {
713 snprintf(exp, size, "PWD: " _GREEN_("0x%02X%02X%02X%02X"), cmd[0], cmd[1], cmd[2], cmd[3]);
714 _ht2state.state = STATE_AUTH;
716 break;
719 if (_ht2state.state == STATE_AUTH) {
720 snprintf(exp, size, "DATA");
721 break;
724 if (_ht2state.state == STATE_START_ENCRYPTED) {
725 snprintf(exp, size, "At");
726 _ht2state.state = STATE_ENCRYPTED;
727 break;
730 if (isdecrypted == false && _ht2state.state == STATE_ENCRYPTED) {
731 snprintf(exp, size, "ENC DATA");
733 break;
736 case 64: { // crypto handshake
738 if (_ht2state.state == STATE_START_AUTH) {
739 _ht2state.state = STATE_START_ENCRYPTED;
741 // need to be called with filename...
742 if (ht2_check_cryptokeys(keys, keycount, cmd)) {
744 _ht2state.cipher_state = ht2_hitag2_init(
745 _ht2state.key,
746 _ht2state.uid,
747 REV32((cmd[3] << 24) + (cmd[2] << 16) + (cmd[1] << 8) + cmd[0])
749 ht2_hitag2_cipher_transcrypt(&_ht2state.cipher_state, _ht2state.plain + 4, 4, 0);
751 uint64_t key = REV64(_ht2state.key);
752 key = BSWAP_48(key);
753 snprintf(exp, size, "Nr Ar " _WHITE_("( ") _GREEN_("%012" PRIx64) " )", key);
755 } else {
756 snprintf(exp, size, "AUTH: Nr Ar");
758 } else {
759 snprintf(exp, size, "AUTH: Nr Ar");
761 break;
763 default: {
764 snprintf(exp, size, "?");
765 _ht2state.state = STATE_HALT;
766 break;
770 free(binstr);
773 void annotateHitagS(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response) {
776 static const char *identify_transponder_hitag2(uint32_t uid) {
778 switch (uid) {
779 case 0x53505910:
780 return "IMMO Key emulator";
781 break;
782 case 0x5accc811:
783 case 0x5accc821:
784 case 0x5accc831:
785 case 0x5accc841:
786 case 0x5accc851:
787 case 0x5accc861:
788 case 0x5accc871:
789 case 0x5accc881:
790 case 0x5accc891:
791 case 0x5accc8B1:
792 return "CN3 Tango Key emulator";
794 return "";
797 static bool getHitag2Uid(uint32_t *uid) {
799 lf_hitag_data_t packet;
800 memset(&packet, 0, sizeof(packet));
801 packet.cmd = RHT2F_UID_ONLY;
803 clearCommandBuffer();
804 SendCommandNG(CMD_LF_HITAG_READER, (uint8_t *) &packet, sizeof(packet));
805 PacketResponseNG resp;
806 if (WaitForResponseTimeout(CMD_LF_HITAG_READER, &resp, 1500) == false) {
807 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
808 return false;
811 if (resp.status != PM3_SUCCESS) {
812 PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID");
813 return false;
816 if (uid) {
817 *uid = bytes_to_num(resp.data.asBytes, HITAG_UID_SIZE);
819 return true;
822 static int CmdLFHitagInfo(const char *Cmd) {
823 CLIParserContext *ctx;
824 CLIParserInit(&ctx, "lf hitag info",
825 "Hitag 2 tag information",
826 "lf hitag info"
829 void *argtable[] = {
830 arg_param_begin,
831 arg_param_end
833 CLIExecWithReturn(ctx, Cmd, argtable, true);
834 CLIParserFree(ctx);
836 // read UID
837 uint32_t uid = 0;
838 if (getHitag2Uid(&uid) == false) {
839 return PM3_ESOFT;
841 // how to determine Hitag types?
842 // need auth / pwd to get it.
843 // we could try the default key/pwd and print if successful
844 // read block3, get configuration byte.
846 // common configurations.
847 print_hitag2_configuration(uid, 0x06); // pwd mode enabled / AM
848 // print_hitag2_configuration(uid, 0x0E); // crypto mode enabled / AM
849 // print_hitag2_configuration(uid, 0x02);
850 // print_hitag2_configuration(uid, 0x00);
851 // print_hitag2_configuration(uid, 0x04);
853 PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint"));
854 const char *s = identify_transponder_hitag2(uid);
855 if (strlen(s)) {
856 PrintAndLogEx(SUCCESS, "Found... " _GREEN_("%s"), s);
857 } else {
858 PrintAndLogEx(INFO, _RED_("n/a"));
861 PrintAndLogEx(NORMAL, "");
862 return PM3_SUCCESS;
865 static int CmdLFHitagReader(const char *Cmd) {
866 CLIParserContext *ctx;
867 CLIParserInit(&ctx, "lf hitag reader",
868 "Act as a Hitag 2 reader. Look for Hitag 2 tags until Enter or the pm3 button is pressed\n",
869 "lf hitag reader\n"
870 "lf hitag reader -@ -> Continuous mode"
873 void *argtable[] = {
874 arg_param_begin,
875 arg_lit0("@", NULL, "continuous reader mode"),
876 arg_param_end
878 CLIExecWithReturn(ctx, Cmd, argtable, true);
879 bool cm = arg_get_lit(ctx, 1);
880 CLIParserFree(ctx);
882 if (cm) {
883 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
886 do {
887 // read UID
888 uint32_t uid = 0;
889 if (getHitag2Uid(&uid)) {
890 PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid);
892 } while (cm && kbd_enter_pressed() == false);
894 return PM3_SUCCESS;
897 static int CmdLFHitagRd(const char *Cmd) {
899 CLIParserContext *ctx;
900 CLIParserInit(&ctx, "lf hitag read",
901 "Read Hitag memory. It support Hitag S and Hitag 2\n\n"
902 " Password mode:\n"
903 " - default key 4D494B52 (MIKR)\n\n"
904 " Crypto mode: \n"
905 " - key format ISK high + ISK low\n"
906 " - default key 4F4E4D494B52 (ONMIKR)\n"
908 " lf hitag read --hts -> Hitag S, plain mode\n"
909 " lf hitag read --hts --nrar 0102030411223344 -> Hitag S, challenge mode\n"
910 " lf hitag read --hts --crypto -> Hitag S, crypto mode, def key\n"
911 " lf hitag read --hts -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
912 " lf hitag read --ht2 --pwd -> Hitag 2, pwd mode, def key\n"
913 " lf hitag read --ht2 -k 4D494B52 -> Hitag 2, pwd mode\n"
914 " lf hitag read --ht2 --nrar 0102030411223344 -> Hitag 2, challenge mode\n"
915 " lf hitag read --ht2 --crypto -> Hitag 2, crypto mode, def key\n"
916 " lf hitag read --ht2 -k 4F4E4D494B52 -> Hitag 2, crypto mode\n"
919 void *argtable[] = {
920 arg_param_begin,
921 arg_lit0("s", "hts", "Hitag S"),
922 arg_lit0("2", "ht2", "Hitag 2"),
923 arg_lit0(NULL, "pwd", "password mode"),
924 arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
925 arg_lit0(NULL, "crypto", "crypto mode"),
926 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
927 // currently pm3 fw reads all the memory anyway
928 // arg_int1("p", "page", "<dec>", "page address to write to"),
929 arg_param_end
931 CLIExecWithReturn(ctx, Cmd, argtable, false);
933 bool use_ht1 = false; // not yet implemented
934 bool use_hts = arg_get_lit(ctx, 1);
935 bool use_ht2 = arg_get_lit(ctx, 2);
936 bool use_htm = false; // not yet implemented
938 bool use_plain = false;
939 bool use_pwd = arg_get_lit(ctx, 3);
940 uint8_t nrar[8];
941 int nalen = 0;
942 int res = CLIParamHexToBuf(arg_get_str(ctx, 4), nrar, sizeof(nrar), &nalen);
943 if (res != 0) {
944 CLIParserFree(ctx);
945 return PM3_EINVARG;
947 bool use_nrar = nalen > 0;
948 bool use_crypto = arg_get_lit(ctx, 5);
950 uint8_t key[6];
951 int keylen = 0;
952 res = CLIParamHexToBuf(arg_get_str(ctx, 6), key, sizeof(key), &keylen);
953 if (res != 0) {
954 CLIParserFree(ctx);
955 return PM3_EINVARG;
957 // uint32_t page = arg_get_u32_def(ctx, 6, 0);
959 CLIParserFree(ctx);
961 // sanity checks
962 if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) {
963 PrintAndLogEx(ERR, "error, specify only one Hitag type");
964 return PM3_EINVARG;
966 if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) {
967 PrintAndLogEx(ERR, "error, specify one Hitag type");
968 return PM3_EINVARG;
971 if (keylen != 0 && keylen != 4 && keylen != 6) {
972 PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen);
973 return PM3_EINVARG;
976 if (nalen != 0 && nalen != 8) {
977 PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 8, got %d", nalen);
978 return PM3_EINVARG;
981 // complete options
982 if (keylen == 4) {
983 use_pwd = true;
985 if (keylen == 6) {
986 use_crypto = true;
988 if ((keylen == 0) && use_pwd) {
989 memcpy(key, "MIKR", 4);
990 keylen = 4;
992 if ((keylen == 0) && use_crypto) {
993 memcpy(key, "ONMIKR", 6);
994 keylen = 6;
997 // check coherence
998 uint8_t foo = (use_plain + use_pwd + use_nrar + use_crypto);
999 if (foo > 1) {
1000 PrintAndLogEx(WARNING, "Specify only one authentication mode");
1001 return PM3_EINVARG;
1002 } else if (foo == 0) {
1003 if (use_hts) {
1004 use_plain = true;
1005 } else {
1006 PrintAndLogEx(WARNING, "Specify one authentication mode");
1007 return PM3_EINVARG;
1011 if (use_hts && use_pwd) { // not sure for the other types...
1012 PrintAndLogEx(WARNING, "Chosen Hitag type does not have Password mode");
1013 return PM3_EINVARG;
1016 if (use_ht2 && use_plain) { // not sure for the other types...
1017 PrintAndLogEx(WARNING, "Chosen Hitag type does not have Plain mode");
1018 return PM3_EINVARG;
1021 lf_hitag_data_t packet;
1022 memset(&packet, 0, sizeof(packet));
1024 int pm3cmd;
1025 if (use_hts) {
1026 // plain mode?
1027 pm3cmd = CMD_LF_HITAGS_READ;
1028 } else if (use_hts && use_nrar) {
1029 pm3cmd = CMD_LF_HITAGS_READ;
1030 packet.cmd = RHTSF_CHALLENGE;
1031 memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
1033 } else if (use_hts && use_crypto) {
1034 pm3cmd = CMD_LF_HITAGS_READ;
1035 packet.cmd = RHTSF_KEY;
1036 memcpy(packet.key, key, sizeof(packet.key));
1038 } else if (use_ht2 && use_pwd) {
1039 pm3cmd = CMD_LF_HITAG_READER;
1040 packet.cmd = RHT2F_PASSWORD;
1041 memcpy(packet.pwd, key, sizeof(packet.pwd));
1043 } else if (use_ht2 && use_nrar) {
1044 pm3cmd = CMD_LF_HITAG_READER;
1045 packet.cmd = RHT2F_AUTHENTICATE;
1046 memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
1047 } else if (use_ht2 && use_crypto) {
1049 pm3cmd = CMD_LF_HITAG_READER;
1050 packet.cmd = RHT2F_CRYPTO;
1051 memcpy(packet.key, key, sizeof(packet.key));
1052 } else {
1053 PrintAndLogEx(WARNING, "Sorry, not yet implemented");
1054 return PM3_ENOTIMPL;
1057 clearCommandBuffer();
1058 SendCommandNG(pm3cmd, (uint8_t *)&packet, sizeof(packet));
1060 PacketResponseNG resp;
1061 if (WaitForResponseTimeout(pm3cmd, &resp, 2000) == false) {
1062 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1063 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
1064 return PM3_ETIMEOUT;
1067 if (resp.status != PM3_SUCCESS) {
1068 PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
1069 return PM3_ESOFT;
1072 if (use_nrar) {
1073 return PM3_SUCCESS;
1076 uint8_t *data = resp.data.asBytes;
1077 uint32_t uid = bytes_to_num(data, HITAG_UID_SIZE);
1078 print_hitag2_configuration(uid, data[HITAG_BLOCK_SIZE * 3]);
1080 if (use_ht2) {
1081 print_hitag2_blocks(data, HITAG2_MAX_BYTE_SIZE);
1082 print_hitag2_paxton(data);
1083 } else {
1084 print_hex_break(data, HITAG_MAX_BYTE_SIZE, HITAG_BLOCK_SIZE);
1086 return PM3_SUCCESS;
1089 static int CmdLFHitagSCheckChallenges(const char *Cmd) {
1091 CLIParserContext *ctx;
1092 CLIParserInit(&ctx, "lf hitag cc",
1093 "Check challenges, load a file with saved hitag crypto challenges and test them all.\n"
1094 "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`") " ",
1095 "lf hitag cc -f my_hitag_challenges"
1098 void *argtable[] = {
1099 arg_param_begin,
1100 arg_str1("f", "file", "<fn>", "filename to load ( w/o ext )"),
1101 arg_param_end
1103 CLIExecWithReturn(ctx, Cmd, argtable, true);
1105 int fnlen = 0;
1106 char filename[FILE_PATH_SIZE] = {0};
1107 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
1108 CLIParserFree(ctx);
1110 uint8_t *data = NULL;
1111 size_t datalen = 0;
1112 int res = loadFile_safe(filename, ".cc", (void **)&data, &datalen);
1113 if (res == PM3_SUCCESS) {
1115 if (datalen % 8) {
1116 PrintAndLogEx(ERR, "Error, file length mismatch. Expected multiple of 8, got " _RED_("%zu"), datalen);
1117 free(data);
1118 return PM3_EINVARG;
1120 if (datalen != (8 * 60)) {
1121 PrintAndLogEx(ERR, "Error, file length mismatch. Expected 480, got " _RED_("%zu"), datalen);
1122 free(data);
1123 return PM3_EINVARG;
1126 clearCommandBuffer();
1127 SendCommandNG(CMD_LF_HITAGS_TEST_TRACES, data, datalen);
1129 if (data) {
1130 free(data);
1132 return PM3_SUCCESS;
1135 static int CmdLFHitag2CheckChallenges(const char *Cmd) {
1136 CLIParserContext *ctx;
1137 CLIParserInit(&ctx, "lf hitag ta",
1138 "Test recorded authentications (replay?)",
1139 "lf hitag ta"
1141 CLIParserFree(ctx);
1143 lf_hitag_data_t packet;
1144 memset(&packet, 0, sizeof(lf_hitag_data_t));
1145 packet.cmd = RHT2F_TEST_AUTH_ATTEMPTS;
1147 clearCommandBuffer();
1148 SendCommandNG(CMD_LF_HITAG_READER, (uint8_t *)&packet, sizeof(packet));
1149 PacketResponseNG resp;
1150 if (WaitForResponseTimeout(CMD_LF_HITAG_READER, &resp, 2000) == false) {
1151 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1152 return PM3_ETIMEOUT;
1154 if (resp.status != PM3_SUCCESS) {
1155 PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
1156 return PM3_ESOFT;
1159 // FIXME: doegox: not sure what this fct does and what it returns...
1160 return PM3_SUCCESS;
1163 static int CmdLFHitagWriter(const char *Cmd) {
1164 CLIParserContext *ctx;
1165 CLIParserInit(&ctx, "lf hitag wrbl",
1166 "Write a page in Hitag memory. It support HitagS and Hitag 2\n"
1167 " Password mode:\n"
1168 " - default key 4D494B52 (MIKR)\n\n"
1169 " Crypto mode: \n"
1170 " - key format ISK high + ISK low\n"
1171 " - default key 4F4E4D494B52 (ONMIKR)\n"
1173 " lf hitag wrbl --hts -p 6 -d 01020304 -> HitagS, plain mode\n"
1174 " lf hitag wrbl --hts -p 6 -d 01020304 --nrar 0102030411223344 -> HitagS, challenge mode\n"
1175 " lf hitag wrbl --hts -p 6 -d 01020304 --crypto -> HitagS, crypto mode, def key\n"
1176 " lf hitag wrbl --hts -p 6 -d 01020304 -k 4F4E4D494B52 -> HitagS, crypto mode\n\n"
1177 " lf hitag wrbl --ht2 -p 6 -d 01020304 --pwd -> Hitag 2, pwd mode, def key\n"
1178 " lf hitag wrbl --ht2 -p 6 -d 01020304 -k 4D494B52 -> Hitag 2, pwd mode\n"
1179 " lf hitag wrbl --ht2 -p 6 -d 01020304 --nrar 0102030411223344 -> Hitag 2, challenge mode\n"
1180 " lf hitag wrbl --ht2 -p 6 -d 01020304 --crypto -> Hitag 2, crypto mode, def key\n"
1181 " lf hitag wrbl --ht2 -p 6 -d 01020304 -k 4F4E4D494B52 -> Hitag 2, crypto mode\n"
1184 void *argtable[] = {
1185 arg_param_begin,
1186 arg_lit0("s", "hts", "Hitag S"),
1187 arg_lit0("2", "ht2", "Hitag 2"),
1188 arg_lit0(NULL, "pwd", "password mode"),
1189 arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
1190 arg_lit0(NULL, "crypto", "crypto mode"),
1191 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
1192 arg_int1("p", "page", "<dec>", "page address to write to"),
1193 arg_str1("d", "data", "<hex>", "data, 4 hex bytes"),
1194 arg_param_end
1196 CLIExecWithReturn(ctx, Cmd, argtable, false);
1198 bool use_ht1 = false; // not yet implemented
1199 bool use_hts = arg_get_lit(ctx, 1);
1200 bool use_ht2 = arg_get_lit(ctx, 2);
1201 bool use_htm = false; // not yet implemented
1203 bool use_plain = false;
1204 bool use_pwd = arg_get_lit(ctx, 3);
1205 uint8_t nrar[8];
1206 int nalen = 0;
1207 int res = CLIParamHexToBuf(arg_get_str(ctx, 4), nrar, sizeof(nrar), &nalen);
1208 if (res != 0) {
1209 CLIParserFree(ctx);
1210 return PM3_EINVARG;
1212 bool use_nrar = nalen > 0;
1213 bool use_crypto = arg_get_lit(ctx, 5);
1215 uint8_t key[6];
1216 int keylen = 0;
1217 res = CLIParamHexToBuf(arg_get_str(ctx, 6), key, sizeof(key), &keylen);
1218 if (res != 0) {
1219 CLIParserFree(ctx);
1220 return PM3_EINVARG;
1223 int page = arg_get_int_def(ctx, 7, 0);
1225 uint8_t data[4];
1226 int dlen = 0;
1227 res = CLIParamHexToBuf(arg_get_str(ctx, 8), data, sizeof(data), &dlen);
1228 if (res != 0) {
1229 CLIParserFree(ctx);
1230 return PM3_EINVARG;
1233 CLIParserFree(ctx);
1235 // sanity checks
1236 if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) {
1237 PrintAndLogEx(ERR, "error, specify only one Hitag type");
1238 return PM3_EINVARG;
1240 if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) {
1241 PrintAndLogEx(ERR, "error, specify one Hitag type");
1242 return PM3_EINVARG;
1245 if (keylen != 0 && keylen != 4 && keylen != 6) {
1246 PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen);
1247 return PM3_EINVARG;
1250 if (dlen != sizeof(data)) {
1251 PrintAndLogEx(WARNING, "Wrong DATA len expected 4, got %d", dlen);
1252 return PM3_EINVARG;
1255 if (nalen != 0 && nalen != 8) {
1256 PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 8, got %d", nalen);
1257 return PM3_EINVARG;
1260 // complete options
1261 if (keylen == 4) {
1262 use_pwd = true;
1264 if (keylen == 6) {
1265 use_crypto = true;
1267 if ((keylen == 0) && use_pwd) {
1268 memcpy(key, "MIKR", 4);
1269 keylen = 4;
1271 if ((keylen == 0) && use_crypto) {
1272 memcpy(key, "ONMIKR", 6);
1273 keylen = 6;
1276 // check coherence
1277 uint8_t foo = (use_plain + use_pwd + use_nrar + use_crypto);
1278 if (foo > 1) {
1279 PrintAndLogEx(WARNING, "Specify only one authentication mode");
1280 return PM3_EINVARG;
1281 } else if (foo == 0) {
1282 if (use_hts) {
1283 use_plain = true;
1284 } else {
1285 PrintAndLogEx(WARNING, "Specify one authentication mode");
1286 return PM3_EINVARG;
1290 if (use_hts && use_pwd) { // not sure for the other types...
1291 PrintAndLogEx(WARNING, "Chosen Hitag type does not have Password mode");
1292 return PM3_EINVARG;
1295 if (use_ht2 && use_plain) { // not sure for the other types...
1296 PrintAndLogEx(WARNING, "Chosen Hitag type does not have Plain mode");
1297 return PM3_EINVARG;
1300 lf_hitag_data_t packet;
1301 memset(&packet, 0, sizeof(packet));
1303 if (use_hts && use_plain) {
1304 packet.cmd = WHTSF_PLAIN;
1305 packet.page = page;
1306 memcpy(packet.data, data, sizeof(data));
1308 PrintAndLogEx(INFO, "Write to " _YELLOW_("Hitag S") " in Plain mode");
1310 } else if (use_hts && use_nrar) {
1311 packet.cmd = WHTSF_CHALLENGE;
1312 memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
1313 memcpy(packet.data, data, sizeof(data));
1314 // iceman: No page in Hitag S ?
1315 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Challenge mode");
1317 } else if (use_hts && use_crypto) {
1318 packet.cmd = WHTSF_KEY;
1319 memcpy(packet.key, key, sizeof(packet.key));
1320 memcpy(packet.data, data, sizeof(data));
1321 // iceman: No page in Hitag S ?
1322 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Crypto mode");
1324 } else if (use_ht2 && use_pwd) {
1325 packet.cmd = WHT2F_PASSWORD;
1326 packet.page = page;
1327 memcpy(packet.pwd, key, sizeof(packet.pwd));
1328 memcpy(packet.data, data, sizeof(data));
1329 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag 2") " in Password mode");
1331 } else if (use_ht2 && use_crypto) {
1332 packet.cmd = WHT2F_CRYPTO;
1333 packet.page = page;
1334 memcpy(packet.key, key, sizeof(packet.key));
1335 memcpy(packet.data, data, sizeof(data));
1336 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag 2") " in Crypto mode");
1338 } else {
1339 PrintAndLogEx(WARNING, "Sorry, not yet implemented");
1340 return PM3_ENOTIMPL;
1343 clearCommandBuffer();
1345 if (use_ht2) {
1346 SendCommandNG(CMD_LF_HITAG2_WRITE, (uint8_t *)&packet, sizeof(packet));
1347 PacketResponseNG resp;
1348 if (WaitForResponseTimeout(CMD_LF_HITAG2_WRITE, &resp, 4000) == false) {
1349 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1350 return PM3_ETIMEOUT;
1353 if (resp.status == PM3_ETEAROFF) {
1354 PrintAndLogEx(INFO, "Writing tear off triggered");
1355 return PM3_SUCCESS;
1358 if (resp.status != PM3_SUCCESS) {
1359 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
1360 return resp.status;
1363 } else {
1365 SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *)&packet, sizeof(packet));
1366 PacketResponseNG resp;
1367 if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 4000) == false) {
1368 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1369 return PM3_ETIMEOUT;
1372 if (resp.status == PM3_ETEAROFF) {
1373 PrintAndLogEx(INFO, "Writing tear off triggered");
1374 return PM3_SUCCESS;
1377 if (resp.status != PM3_SUCCESS) {
1378 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
1379 return resp.status;
1383 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
1384 return PM3_SUCCESS;
1387 static int CmdLFHitag2Dump(const char *Cmd) {
1389 CLIParserContext *ctx;
1390 CLIParserInit(&ctx, "lf hitag dump",
1391 "Read all Hitag 2 card memory and save to file\n"
1392 "Crypto mode key format: ISK high + ISK low, 4F4E4D494B52 (ONMIKR)\n"
1393 "Password mode, default key 4D494B52 (MIKR)\n",
1394 "lf hitag dump --pwd -> use def pwd\n"
1395 "lf hitag dump -k 4D494B52 -> pwd mode\n"
1396 "lf hitag dump --crypto -> use def crypto\n"
1397 "lf hitag dump -k 4F4E4D494B52 -> crypto mode\n"
1398 "lf hitag dump --nrar 0102030411223344\n"
1401 void *argtable[] = {
1402 arg_param_begin,
1403 arg_lit0(NULL, "pwd", "password mode"),
1404 arg_str0(NULL, "nrar", "<hex>", "nonce / answer reader, 8 hex bytes"),
1405 arg_lit0(NULL, "crypto", "crypto mode"),
1406 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
1407 arg_str0("f", "file", "<fn>", "specify file name"),
1408 arg_lit0(NULL, "ns", "no save to file"),
1409 arg_param_end
1411 CLIExecWithReturn(ctx, Cmd, argtable, false);
1413 bool use_ht1 = false; // not yet implemented
1414 bool use_hts = false; // not yet implemented
1415 bool use_ht2 = true;
1416 bool use_htm = false; // not yet implemented
1418 bool use_plain = false;
1419 bool use_pwd = arg_get_lit(ctx, 1);
1420 uint8_t nrar[8];
1421 int nalen = 0;
1422 int res = CLIParamHexToBuf(arg_get_str(ctx, 2), nrar, sizeof(nrar), &nalen);
1423 if (res != 0) {
1424 CLIParserFree(ctx);
1425 return PM3_EINVARG;
1427 bool use_nrar = nalen > 0;
1428 bool use_crypto = arg_get_lit(ctx, 3);
1430 uint8_t key[HITAG_NRAR_SIZE];
1431 int keylen = 0;
1432 res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, sizeof(key), &keylen);
1433 if (res != 0) {
1434 CLIParserFree(ctx);
1435 return PM3_EINVARG;
1438 int fnlen = 0;
1439 char filename[FILE_PATH_SIZE] = {0};
1440 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
1442 bool nosave = arg_get_lit(ctx, 6);
1443 CLIParserFree(ctx);
1445 // sanity checks
1446 if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) {
1447 PrintAndLogEx(ERR, "error, specify only one Hitag type");
1448 return PM3_EINVARG;
1450 if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) {
1451 PrintAndLogEx(ERR, "error, specify one Hitag type");
1452 return PM3_EINVARG;
1455 if (keylen != 0 &&
1456 keylen != HITAG_PASSWORD_SIZE &&
1457 keylen != HITAG_CRYPTOKEY_SIZE &&
1458 keylen != HITAG_NRAR_SIZE) {
1459 PrintAndLogEx(WARNING, "Wrong KEY len expected (0,4,6,8) got %d", keylen);
1460 return PM3_EINVARG;
1463 // complete options
1464 if (keylen == HITAG_PASSWORD_SIZE) {
1465 use_pwd = true;
1467 if (keylen == HITAG_CRYPTOKEY_SIZE) {
1468 use_crypto = true;
1470 if (keylen == HITAG_NRAR_SIZE) {
1471 use_nrar = true;
1472 memcpy(nrar, key, sizeof(nrar));
1475 // Set default key / pwd
1476 if ((keylen == 0) && use_pwd) {
1477 memcpy(key, "MIKR", HITAG_PASSWORD_SIZE);
1478 keylen = HITAG_PASSWORD_SIZE;
1480 if ((keylen == 0) && use_crypto) {
1481 memcpy(key, "ONMIKR", HITAG_CRYPTOKEY_SIZE);
1482 keylen = HITAG_CRYPTOKEY_SIZE;
1485 // check coherence
1486 uint8_t foo = (use_plain + use_pwd + use_nrar + use_crypto);
1487 if (foo > 1) {
1488 PrintAndLogEx(WARNING, "Specify only one authentication mode");
1489 return PM3_EINVARG;
1490 } else if (foo == 0) {
1491 if (use_hts) {
1492 use_plain = true;
1493 } else {
1494 PrintAndLogEx(WARNING, "Specify one authentication mode");
1495 return PM3_EINVARG;
1499 if (use_hts && use_pwd) { // not sure for the other types...
1500 PrintAndLogEx(WARNING, "Chosen Hitag type does not have Password mode");
1501 return PM3_EINVARG;
1504 if (use_ht2 && use_plain) { // not sure for the other types...
1505 PrintAndLogEx(WARNING, "Chosen Hitag type does not have Plain mode");
1506 return PM3_EINVARG;
1509 uint32_t uid = 0;
1511 PacketResponseNG resp;
1512 uint8_t *data = NULL;
1514 lf_hitag_data_t packet;
1515 memset(&packet, 0, sizeof(packet));
1517 if (use_ht2 && use_pwd) {
1518 packet.cmd = RHT2F_PASSWORD;
1519 memcpy(packet.pwd, key, sizeof(packet.pwd));
1520 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag 2") " in Password mode");
1522 } else if (use_ht2 && use_crypto) {
1523 packet.cmd = RHT2F_CRYPTO;
1524 memcpy(packet.key, key, sizeof(packet.key));
1525 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag 2") " in Crypto mode");
1527 } else if (use_ht2 && use_nrar) {
1530 memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
1532 PrintAndLogEx(INFO, _YELLOW_("Hitag 2") " - Challenge mode (NrAr)");
1534 uint64_t t1 = msclock();
1536 clearCommandBuffer();
1537 SendCommandNG(CMD_LF_HITAG2_CRACK, (uint8_t *) &packet, sizeof(packet));
1539 // loop
1540 uint8_t attempt = 30;
1541 do {
1543 PrintAndLogEx(INPLACE, "Attack 1 running...");
1544 fflush(stdout);
1546 if (WaitForResponseTimeout(CMD_LF_HITAG2_CRACK, &resp, 1000) == false) {
1547 attempt--;
1548 continue;
1551 lf_hitag_crack_response_t *payload = (lf_hitag_crack_response_t *)resp.data.asBytes;
1553 if (resp.status == PM3_SUCCESS) {
1554 PrintAndLogEx(NORMAL, " ( %s )", _GREEN_("ok"));
1555 data = payload->data;
1557 t1 = msclock() - t1;
1558 PrintAndLogEx(SUCCESS, "\ntime " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
1559 goto out;
1562 // error codes
1563 switch (payload->status) {
1564 case -1: {
1565 PrintAndLogEx(NORMAL, "");
1566 PrintAndLogEx(FAILED, "Couldn't select tag!");
1567 return PM3_ESOFT;
1569 case -2: {
1570 PrintAndLogEx(NORMAL, "");
1571 PrintAndLogEx(FAILED, "Cannot find a valid encrypted command!");
1572 return PM3_ESOFT;
1574 case -3: {
1575 PrintAndLogEx(NORMAL, "");
1576 PrintAndLogEx(FAILED, "Cannot find encrypted 'read page0' command!");
1577 return PM3_ESOFT;
1579 case -4: {
1580 PrintAndLogEx(NORMAL, "");
1581 PrintAndLogEx(FAILED, "Partial data extraction!");
1582 continue;
1586 } while (attempt);
1588 if (attempt == 0) {
1589 PrintAndLogEx(NORMAL, "");
1590 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1591 return PM3_ESOFT;
1594 t1 = msclock() - t1;
1595 PrintAndLogEx(SUCCESS, "\ntime " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
1597 goto out;
1599 } else {
1600 PrintAndLogEx(WARNING, "Sorry, not yet implemented");
1601 return PM3_ENOTIMPL;
1604 clearCommandBuffer();
1605 SendCommandNG(CMD_LF_HITAG_READER, (uint8_t *) &packet, sizeof(packet));
1607 if (WaitForResponseTimeout(CMD_LF_HITAG_READER, &resp, 5000) == false) {
1608 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1609 return PM3_ETIMEOUT;
1611 if (resp.status != PM3_SUCCESS) {
1612 PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
1613 return resp.status;
1616 data = resp.data.asBytes;
1618 out:
1621 // block3, 1 byte
1622 uid = bytes_to_num(data, HITAG_UID_SIZE);
1624 if (use_ht2) {
1625 print_hitag2_configuration(uid, data[HITAG_BLOCK_SIZE * 3]);
1626 print_hitag2_blocks(data, HITAG2_MAX_BYTE_SIZE);
1627 print_hitag2_paxton(data);
1628 } else {
1629 PrintAndLogEx(INFO, "No memory printing available");
1632 if (nosave) {
1633 PrintAndLogEx(NORMAL, "");
1634 PrintAndLogEx(INFO, "Called with no save option");
1635 PrintAndLogEx(NORMAL, "");
1636 return PM3_SUCCESS;
1639 if (fnlen < 1) {
1640 char *fptr = filename;
1641 fptr += snprintf(filename, sizeof(filename), "lf-hitag-");
1642 FillFileNameByUID(fptr, data, "-dump", HITAG_UID_SIZE);
1645 pm3_save_dump(filename, data, HITAG2_MAX_BYTE_SIZE, jsfHitag);
1646 return PM3_SUCCESS;
1649 static int CmdLFHitagView(const char *Cmd) {
1651 CLIParserContext *ctx;
1652 CLIParserInit(&ctx, "lf hitag view",
1653 "Print a HITAG dump file (bin/eml/json)",
1654 "lf hitag view -f lf-hitag-01020304-dump.bin"
1656 void *argtable[] = {
1657 arg_param_begin,
1658 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
1659 arg_lit0("v", "verbose", "Verbose output"),
1660 arg_param_end
1662 CLIExecWithReturn(ctx, Cmd, argtable, false);
1663 int fnlen = 0;
1664 char filename[FILE_PATH_SIZE];
1665 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
1666 bool verbose = arg_get_lit(ctx, 2);
1667 CLIParserFree(ctx);
1669 // read dump file
1670 uint8_t *dump = NULL;
1671 size_t bytes_read = 0;
1672 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, HITAG2_MAX_BYTE_SIZE);
1673 if (res != PM3_SUCCESS) {
1674 return res;
1677 if (bytes_read < HITAG2_MAX_BYTE_SIZE) {
1678 PrintAndLogEx(ERR, "Error, dump file is too small");
1679 free(dump);
1680 return PM3_ESOFT;
1683 if (verbose) {
1684 // block3, 1 byte
1685 uint8_t config = dump[HITAG2_CONFIG_OFFSET];
1686 uint32_t uid = bytes_to_num(dump, HITAG_UID_SIZE);
1687 print_hitag2_configuration(uid, config);
1688 print_hitag2_paxton(dump);
1690 print_hitag2_blocks(dump, HITAG2_MAX_BYTE_SIZE);
1691 free(dump);
1692 return PM3_SUCCESS;
1695 static int CmdLFHitagEload(const char *Cmd) {
1696 CLIParserContext *ctx;
1697 CLIParserInit(&ctx, "lf hitag eload",
1698 "Loads hitag tag dump into emulator memory on device",
1699 "lf hitag eload -2 -f lf-hitag-11223344-dump.bin\n"
1701 void *argtable[] = {
1702 arg_param_begin,
1703 arg_str1("f", "file", "<fn>", "Specify dump filename"),
1704 arg_lit0("1", "ht1", "Card type Hitag 1"),
1705 arg_lit0("2", "ht2", "Card type Hitag 2"),
1706 arg_lit0("s", "hts", "Card type Hitag S"),
1707 arg_lit0("m", "htm", "Card type Hitag \xce\xbc"), // μ
1708 arg_param_end
1710 CLIExecWithReturn(ctx, Cmd, argtable, false);
1712 int fnlen = 0;
1713 char filename[FILE_PATH_SIZE] = {0};
1714 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
1716 bool use_ht1 = arg_get_lit(ctx, 2);
1717 bool use_ht2 = arg_get_lit(ctx, 3);
1718 bool use_hts = arg_get_lit(ctx, 4);
1719 bool use_htm = arg_get_lit(ctx, 5);
1720 CLIParserFree(ctx);
1722 if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) {
1723 PrintAndLogEx(ERR, "error, specify only one Hitag type");
1724 return PM3_EINVARG;
1726 if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) {
1727 PrintAndLogEx(ERR, "error, specify one Hitag type");
1728 return PM3_EINVARG;
1731 // read dump file
1732 uint8_t *dump = NULL;
1733 size_t bytes_read = (4 * 64);
1734 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (4 * 64));
1735 if (res != PM3_SUCCESS) {
1736 return res;
1739 // check dump len..
1740 if (bytes_read == HITAG2_MAX_BYTE_SIZE || bytes_read == 4 * 64) {
1742 lf_hitag_t *payload = calloc(1, sizeof(lf_hitag_t) + bytes_read);
1744 if (use_ht1)
1745 payload->type = 1;
1746 if (use_ht2)
1747 payload->type = 2;
1748 if (use_hts)
1749 payload->type = 3;
1750 if (use_htm)
1751 payload->type = 4;
1753 payload->len = bytes_read;
1754 memcpy(payload->data, dump, bytes_read);
1756 clearCommandBuffer();
1757 SendCommandNG(CMD_LF_HITAG_ELOAD, (uint8_t *)payload, 3 + bytes_read);
1758 free(payload);
1759 } else {
1760 PrintAndLogEx(ERR, "error, wrong dump file size. got %zu", bytes_read);
1763 free(dump);
1764 return PM3_SUCCESS;
1767 static int CmdLFHitagEview(const char *Cmd) {
1768 CLIParserContext *ctx;
1769 CLIParserInit(&ctx, "lf hitag eview",
1770 "It displays emulator memory",
1771 "lf hitag eview\n"
1773 void *argtable[] = {
1774 arg_param_begin,
1775 arg_lit0("v", "verbose", "Verbose output"),
1776 arg_param_end
1778 CLIExecWithReturn(ctx, Cmd, argtable, true);
1779 bool verbose = arg_get_lit(ctx, 1);
1780 CLIParserFree(ctx);
1782 int bytes = HITAG2_MAX_BYTE_SIZE;
1784 // reserve memory
1785 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
1786 if (dump == NULL) {
1787 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
1788 return PM3_EMALLOC;
1791 PrintAndLogEx(INFO, "Downloading " _YELLOW_("%u") " bytes from emulator memory...", bytes);
1792 if (GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false) == false) {
1793 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
1794 free(dump);
1795 return PM3_ETIMEOUT;
1798 if (verbose) {
1799 // block3, 1 byte
1800 uint8_t config = dump[HITAG2_CONFIG_OFFSET];
1801 uint32_t uid = bytes_to_num(dump, HITAG_UID_SIZE);
1802 print_hitag2_configuration(uid, config);
1803 print_hitag2_paxton(dump);
1805 print_hitag2_blocks(dump, HITAG2_MAX_BYTE_SIZE);
1806 free(dump);
1807 return PM3_SUCCESS;
1810 static int CmdLFHitagSim(const char *Cmd) {
1811 CLIParserContext *ctx;
1812 CLIParserInit(&ctx, "lf hitag sim",
1813 "Simulate Hitag transponder\n"
1814 "You need to `lf hitag eload` first",
1815 "lf hitag sim -2"
1818 void *argtable[] = {
1819 arg_param_begin,
1820 arg_lit0("1", "ht1", "simulate Hitag 1"),
1821 arg_lit0("2", "ht2", "simulate Hitag 2"),
1822 arg_lit0("s", "hts", "simulate Hitag S"),
1823 arg_param_end
1825 CLIExecWithReturn(ctx, Cmd, argtable, true);
1827 bool use_ht1 = arg_get_lit(ctx, 1);
1828 bool use_ht2 = arg_get_lit(ctx, 2);
1829 bool use_hts = arg_get_lit(ctx, 3);
1830 bool use_htm = false; // not implemented yet
1831 CLIParserFree(ctx);
1833 if ((use_ht1 + use_ht2 + use_hts + use_htm) > 1) {
1834 PrintAndLogEx(ERR, "error, specify only one Hitag type");
1835 return PM3_EINVARG;
1837 if ((use_ht1 + use_ht2 + use_hts + use_htm) == 0) {
1838 PrintAndLogEx(ERR, "error, specify one Hitag type");
1839 return PM3_EINVARG;
1842 uint16_t cmd = CMD_LF_HITAG_SIMULATE;
1843 // if (use_ht1)
1844 // cmd = CMD_LF_HITAG1_SIMULATE;
1846 if (use_hts)
1847 cmd = CMD_LF_HITAGS_SIMULATE;
1849 clearCommandBuffer();
1850 SendCommandMIX(cmd, 0, 0, 0, NULL, 0);
1851 return PM3_SUCCESS;
1854 static int CmdLFHitagSniff(const char *Cmd) {
1855 CLIParserContext *ctx;
1856 CLIParserInit(&ctx, "lf hitag sniff",
1857 "Sniff the communication between reader and tag.\n"
1858 "Use `lf hitag list` to view collected data.",
1859 " lf hitag sniff"
1862 void *argtable[] = {
1863 arg_param_begin,
1864 arg_param_end
1866 CLIExecWithReturn(ctx, Cmd, argtable, true);
1867 CLIParserFree(ctx);
1869 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort sniffing");
1871 PacketResponseNG resp;
1872 clearCommandBuffer();
1873 SendCommandNG(CMD_LF_HITAG_SNIFF, NULL, 0);
1874 WaitForResponse(CMD_LF_HITAG_SNIFF, &resp);
1875 PrintAndLogEx(INFO, "Done!");
1876 PrintAndLogEx(HINT, "Try `" _YELLOW_("lf hitag list")"` to view captured tracelog");
1877 PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
1878 return PM3_SUCCESS;
1882 static int CmdLFHitag2PWMDemod(const char *Cmd) {
1884 CLIParserContext *ctx;
1885 CLIParserInit(&ctx, "lf hitag pwmdemod",
1886 "Demodulate the data in the GraphBuffer and output binary\n",
1887 "lf hitag pwmdemod"
1888 "lf hitag pwmdemod -t 65 --> specify first wave index\n"
1891 void *argtable[] = {
1892 arg_param_begin,
1893 arg_int0("t", "start", "<dec>", "first wave index"),
1894 arg_int0(NULL, "zero", "<dec>", "Zero pulse length"),
1895 arg_int0(NULL, "one", "<dec>", "One pulse length"),
1896 arg_param_end
1899 CLIExecWithReturn(ctx, Cmd, argtable, true);
1900 uint32_t start_idx = (uint32_t)arg_get_int_def(ctx, 1, 0);
1901 uint8_t fclow = (uint8_t)arg_get_int_def(ctx, 2, 20);
1902 uint8_t fchigh = (uint8_t)arg_get_int_def(ctx, 3, 29);
1903 CLIParserFree(ctx);
1905 uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
1906 if (bits == NULL) {
1907 PrintAndLogEx(INFO, "failed to allocate memory");
1908 return PM3_EMALLOC;
1911 size_t size = getFromGraphBuffer(bits);
1913 PrintAndLogEx(DEBUG, "DEBUG: (Hitag2PWM) #samples from graphbuff... %zu", size);
1915 if (size < 255) {
1916 PrintAndLogEx(INFO, "too few samples in buffer");
1917 free(bits);
1918 return PM3_ESOFT;
1921 // TODO autodetect
1922 size = HitagPWMDemod(bits, size, &fchigh, &fclow, &start_idx, g_DemodBitRangeBuffer);
1923 if (size == 0) {
1924 PrintAndLogEx(FAILED, "No wave detected");
1925 free(bits);
1926 return PM3_ESOFT;
1929 PrintAndLogEx(DEBUG, "DEBUG: start_idx... %u size... %zu", start_idx, size);
1931 setDemodBuffBitRange(bits, size, 0, g_DemodBitRangeBuffer);
1932 setClockGrid(32, start_idx);
1934 uint32_t total = 0;
1935 for (size_t i = 0; i < size; i++) {
1936 total += g_DemodBitRangeBuffer[i];
1937 PrintAndLogEx(DEBUG, "%d", g_DemodBitRangeBuffer[i]);
1939 PrintAndLogEx(DEBUG, "Total... %d", total);
1941 PrintAndLogEx(NORMAL, "");
1942 PrintAndLogEx(INFO, "--- " _CYAN_("HITAG/PWM") " ---------------------------");
1943 printDemodBuff(0, false, false, false);
1944 printDemodBuff(0, false, false, true);
1945 free(bits);
1946 return PM3_SUCCESS;
1950 static int CmdLFHitag2Chk(const char *Cmd) {
1952 CLIParserContext *ctx;
1953 CLIParserInit(&ctx, "lf hitag chk",
1954 "Run dictionary key or password recovery against Hitag card.",
1955 "lf hitag chk\n -> checks for both pwd / crypto keys"
1956 "lf hitag chk --crypto -> use def dictionary\n"
1957 "lf hitag chk --pwd -f my.dic -> pwd mode, custom dictionary"
1960 void *argtable[] = {
1961 arg_param_begin,
1962 arg_str0("f", "file", "<fn>", "specify dictionary filename"),
1963 arg_lit0(NULL, "pwd", "password mode"),
1964 arg_lit0(NULL, "crypto", "crypto mode"),
1965 arg_param_end
1968 CLIExecWithReturn(ctx, Cmd, argtable, true);
1969 int fnlen = 0;
1970 char filename[FILE_PATH_SIZE] = {0};
1971 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
1973 bool use_pwd = arg_get_lit(ctx, 2);
1974 bool use_crypto = arg_get_lit(ctx, 3);
1975 CLIParserFree(ctx);
1977 if (use_pwd + use_crypto > 1) {
1978 PrintAndLogEx(WARNING, "Only specify one mode");
1979 return PM3_EINVARG;
1982 // no filename -> use default = ht2_default.dic
1983 if (fnlen == 0) {
1984 snprintf(filename, sizeof(filename), HITAG_DICTIONARY);
1987 uint8_t keylen = 4;
1988 if (use_crypto) {
1989 keylen = 6;
1992 uint64_t t1 = msclock();
1994 // just loop twice at max. Starting with 4 or 6.
1995 for (; keylen < 7; keylen += 2) {
1996 // load keys
1997 uint8_t *keys = NULL;
1998 uint32_t key_count = 0;
1999 int res = loadFileDICTIONARY_safe(filename, (void **)&keys, keylen, &key_count);
2000 if (res != PM3_SUCCESS || key_count == 0 || keys == NULL) {
2001 PrintAndLogEx(WARNING, "no keys found in file");
2002 if (keys != NULL) {
2003 free(keys);
2005 return res;
2008 // Main loop
2009 uint32_t found_idx = 0;
2010 int status = ht2_check_dictionary(key_count, keys, keylen, &found_idx);
2012 if (status == PM3_SUCCESS) {
2014 PrintAndLogEx(NORMAL, "");
2015 if (keylen == 6) {
2016 PrintAndLogEx(SUCCESS, "found valid key [ " _GREEN_("%s") " ]", sprint_hex_inrow(keys + (found_idx * keylen), keylen));
2017 } else {
2018 PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%s") " ]", sprint_hex_inrow(keys + (found_idx * keylen), keylen));
2020 free(keys);
2021 break;
2023 free(keys);
2026 t1 = msclock() - t1;
2027 PrintAndLogEx(SUCCESS, "\ntime in check " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
2028 return PM3_SUCCESS;
2031 static int CmdLFHitag2Lookup(const char *Cmd) {
2033 CLIParserContext *ctx;
2034 CLIParserInit(&ctx, "lf hitag lookup",
2035 "This command take sniffed trace data and try to recovery a Hitag 2 crypto key.\n"
2036 " You can either\n"
2037 " - verify that NR/AR matches a known crypto key\n"
2038 " - verify if NR/AR matches a known 6 byte crypto key in a dictionary",
2039 "lf hitag lookup --uid 11223344 --nr 73AA5A62 --ar EAB8529C -k 010203040506 -> check key\n"
2040 "lf hitag lookup --uid 11223344 --nr 73AA5A62 --ar EAB8529C -> use def dictionary\n"
2041 "lf hitag lookup --uid 11223344 --nr 73AA5A62 --ar EAB8529C -f my.dic -> use custom dictionary\n"
2042 "lf hitag lookup --uid 11223344 --nrar 73AA5A62EAB8529C"
2045 void *argtable[] = {
2046 arg_param_begin,
2047 arg_str0("f", "file", "<fn>", "specify dictionary filename"),
2048 arg_str0("k", "key", "<hex>", "specify known cryptokey as 6 bytes"),
2049 arg_str1("u", "uid", "<hex>", "specify UID as 4 hex bytes"),
2050 arg_str0(NULL, "nr", "<hex>", "specify nonce as 4 hex bytes"),
2051 arg_str0(NULL, "ar", "<hex>", "specify answer as 4 hex bytes"),
2052 arg_str0(NULL, "nrar", "<hex>", "specify nonce / answer as 8 hex bytes"),
2053 arg_param_end
2056 CLIExecWithReturn(ctx, Cmd, argtable, false);
2057 int fnlen = 0;
2058 char filename[FILE_PATH_SIZE] = {0};
2059 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
2061 int inkeylen = 0;
2062 uint8_t inkey[6] = {0};
2063 CLIGetHexWithReturn(ctx, 2, inkey, &inkeylen);
2065 int ulen = 0;
2066 uint8_t uidarr[4] = {0};
2067 CLIGetHexWithReturn(ctx, 3, uidarr, &ulen);
2069 int nlen = 0;
2070 uint8_t narr[4] = {0};
2071 CLIGetHexWithReturn(ctx, 4, narr, &nlen);
2073 int alen = 0;
2074 uint8_t aarr[4] = {0};
2075 CLIGetHexWithReturn(ctx, 5, aarr, &alen);
2077 int nalen = 0;
2078 uint8_t nrar[8] = {0};
2079 CLIGetHexWithReturn(ctx, 6, nrar, &nalen);
2081 CLIParserFree(ctx);
2083 // sanity checks
2084 if (inkeylen && inkeylen != 6) {
2085 PrintAndLogEx(INFO, "Key wrong length. expected 6, got %i", inkeylen);
2086 return PM3_EINVARG;
2089 if (ulen && ulen != 4) {
2090 PrintAndLogEx(INFO, "UID wrong length. expected 4, got %i", ulen);
2091 return PM3_EINVARG;
2094 if (nlen && nlen != 4) {
2095 PrintAndLogEx(INFO, "Nr wrong length. expected 4, got %i", nlen);
2096 return PM3_EINVARG;
2099 if (alen && alen != 4) {
2100 PrintAndLogEx(INFO, "Ar wrong length. expected 4, got %i", alen);
2101 return PM3_EINVARG;
2104 if (nalen && nalen != 8) {
2105 PrintAndLogEx(INFO, "NrAr wrong length. expected 8, got %i", nalen);
2106 return PM3_EINVARG;
2109 // Iceman note:
2110 // - key, uid and Nr1 is alway dentoed as LSB/LE order
2111 // - Ar1 is NOT. It is in BE/MSB everywhere.
2112 // - At1 is NOT. It is in BE/MSB everywhere.
2113 // - crypto stream generated is in BE/MSB order in Pm3 code.
2114 // - crypto state is in ?
2115 // - lfsr state is in ?
2117 // Different implementations handles internally the state either in MSB or LSB.
2118 // Something to keep an eye for when looking at code.
2120 // Termology:
2121 // cs / hstate.shiftregister / crypto state = same
2122 // lsfr = some implementations mixes cs and lsfr into one and only use the state. Some differentiate between them.
2123 // usually the key recovery functions under /tools/hitag2crack
2124 // IV / Nonce Reader 1 / Nr1 = same (clear text), always 00 00 00 00 in PM3 code when acting as reader.
2125 // Answer Reader 1 / Ar1 = encrypted and BE/MSB, +32, the clear text is always FF FF FF FF.
2126 // Answer Tag 1 / At1 = encrypted and BE/MSB, +32,
2129 When initializer the crypto engine
2131 1. UID: 11223344
2132 2. KEY: FFFF143624FF
2133 3. NONCE / IV: 00 00 00 00
2134 3. NONCE / IV: 3B 6F 08 4D
2136 now you have a CS / Shiftregister / state = crypto stream?
2138 Ar1 - first encrypted crypto stream ^ 0xFFFFFFFF
2139 4. Ar1: 96 7A 6F 2A ^ FF FF FF FF == 69 85 90 D5
2142 rev_msb_array(inkey, sizeof(inkey));
2143 rev_msb_array(uidarr, sizeof(uidarr));
2144 rev_msb_array(narr, sizeof(narr));
2145 rev_msb_array(nrar, 4);
2148 // Little Endian
2149 uint64_t knownkey = MemLeToUint6byte(inkey);
2150 uint32_t uid = MemLeToUint4byte(uidarr);
2152 uint32_t nr;
2153 // Big Endian
2154 uint32_t ar;
2156 if (nlen && alen) {
2157 nr = MemLeToUint4byte(narr);
2158 ar = MemBeToUint4byte(aarr);
2159 } else if (nalen) {
2160 nr = MemLeToUint4byte(nrar);
2161 ar = MemBeToUint4byte(nrar + 4);
2162 } else {
2163 PrintAndLogEx(INFO, "No nr or ar was supplied");
2164 return PM3_EINVARG;
2167 uint32_t iv = nr;
2170 if (inkeylen) {
2172 PrintAndLogEx(DEBUG, "UID... %08" PRIx32, uid);
2173 PrintAndLogEx(DEBUG, "IV.... %08" PRIx32, iv);
2174 PrintAndLogEx(DEBUG, "Key... %012" PRIx64, knownkey);
2176 // initialize state
2177 hitag_state_t hstate;
2178 ht2_hitag2_init_ex(&hstate, knownkey, uid, iv);
2180 // get 32 bits of crypto stream.
2181 uint32_t cbits = ht2_hitag2_nstep(&hstate, 32);
2182 bool isok = (ar == (cbits ^ 0xFFFFFFFF));
2184 PrintAndLogEx(DEBUG, "state.shiftreg...... %012" PRIx64, hstate.shiftreg);
2185 PrintAndLogEx(DEBUG, "state.lfsr.......... %012" PRIx64, hstate.lfsr);
2186 PrintAndLogEx(DEBUG, "c bits.............. %08x", cbits);
2187 PrintAndLogEx(DEBUG, "c-bits ^ FFFFFFFF... %08x", cbits ^ 0xFFFFFFFF);
2188 PrintAndLogEx(DEBUG, "Ar.................. %08" PRIx32 " ( %s )", ar, (isok) ? _GREEN_("ok") : _RED_("fail"));
2190 PrintAndLogEx(INFO, "Nr/Ar match key ( %s )", (isok) ? _GREEN_("ok") : _RED_("fail"));
2191 PrintAndLogEx(NORMAL, "");
2192 return PM3_SUCCESS;
2195 if (fnlen == 0) {
2196 snprintf(filename, sizeof(filename), HITAG_DICTIONARY);
2199 // load keys
2200 uint8_t *keys = NULL;
2201 uint32_t key_count = 0;
2202 int res = loadFileDICTIONARY_safe(filename, (void **)&keys, HITAG_CRYPTOKEY_SIZE, &key_count);
2203 if (res != PM3_SUCCESS || key_count == 0 || keys == NULL) {
2204 PrintAndLogEx(WARNING, "no keys found in file");
2205 if (keys != NULL) {
2206 free(keys);
2208 return res;
2211 bool found = false;
2212 for (uint32_t i = 0; i < key_count; i++) {
2214 uint8_t *pkey = keys + (i * HITAG_CRYPTOKEY_SIZE);
2215 uint64_t mykey = MemLeToUint6byte(pkey);
2216 mykey = REV64(mykey);
2218 hitag_state_t hs2;
2219 ht2_hitag2_init_ex(&hs2, mykey, uid, iv);
2221 uint32_t tbits = ht2_hitag2_nstep(&hs2, 32);
2222 if ((ar ^ tbits) == 0xFFFFFFFF) {
2223 PrintAndLogEx(SUCCESS, "Found valid key [ " _GREEN_("%s")" ]", sprint_hex_inrow(pkey, HITAG_CRYPTOKEY_SIZE));
2224 found = true;
2225 break;
2228 if (g_debugMode) {
2229 PrintAndLogEx(DEBUG, " tbits... %08" PRIx32 " Known ar... %08" PRIx32, tbits, ar);
2230 PrintAndLogEx(DEBUG, " 0xFFFFFFFF ^ tbits... %08" PRIx32, tbits ^ 0xFFFFFFFF);
2231 PrintAndLogEx(DEBUG, " 0xFFFFFFFF ^ ar...... %08" PRIx32, ar ^ 0xFFFFFFFF);
2232 PrintAndLogEx(DEBUG, " tbits ^ ar........... %08" PRIx32 " ( 0xFFFFFFFF )", ar ^ tbits);
2236 free(keys);
2238 if (found == false) {
2239 PrintAndLogEx(WARNING, "check failed");
2242 PrintAndLogEx(NORMAL, "");
2243 return PM3_SUCCESS;
2246 static int CmdLFHitag2Crack2(const char *Cmd) {
2247 CLIParserContext *ctx;
2248 CLIParserInit(&ctx, "lf hitag crack2",
2249 "This command tries to recover 2048 bits of Hitag 2 crypto stream data.\n",
2250 "lf hitag crack2 --nrar 73AA5A62EAB8529C"
2253 void *argtable[] = {
2254 arg_param_begin,
2255 arg_str0(NULL, "nrar", "<hex>", "specify nonce / answer as 8 hex bytes"),
2256 arg_param_end
2259 CLIExecWithReturn(ctx, Cmd, argtable, false);
2260 int nalen = 0;
2261 uint8_t nrar[8] = {0};
2262 CLIGetHexWithReturn(ctx, 1, nrar, &nalen);
2263 CLIParserFree(ctx);
2265 // sanity checks
2266 if (nalen && nalen != 8) {
2267 PrintAndLogEx(INFO, "NrAr wrong length. expected 8, got %i", nalen);
2268 return PM3_EINVARG;
2271 lf_hitag_data_t packet;
2272 memset(&packet, 0, sizeof(packet));
2273 memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
2275 PrintAndLogEx(INFO, _YELLOW_("Hitag 2") " - Nonce replay and length extension attack ( Crack2 )");
2277 uint64_t t1 = msclock();
2279 PacketResponseNG resp;
2280 clearCommandBuffer();
2281 SendCommandNG(CMD_LF_HITAG2_CRACK_2, (uint8_t *) &packet, sizeof(packet));
2283 // loop
2284 uint8_t attempt = 50;
2285 do {
2287 // PrintAndLogEx(INPLACE, "Attack 2 running...");
2288 // fflush(stdout);
2290 if (WaitForResponseTimeout(CMD_LF_HITAG2_CRACK_2, &resp, 1000) == false) {
2291 attempt--;
2292 continue;
2295 if (resp.status == PM3_SUCCESS) {
2297 PrintAndLogEx(SUCCESS, "--------------------- " _CYAN_("Recovered Keystream") " ----------------------");
2298 lf_hitag_crack_response_t *payload = (lf_hitag_crack_response_t *)resp.data.asBytes;
2300 for (int i = 0; i < 256; i += 32) {
2301 PrintAndLogEx(SUCCESS, "%s", sprint_hex_inrow(payload->data + i, 32));
2303 PrintAndLogEx(NORMAL, "");
2304 PrintAndLogEx(SUCCESS, "Nonce replay and length extension attack ( %s )", _GREEN_("ok"));
2305 PrintAndLogEx(HINT, "try running `tools/hitag2crack/crack2/ht2crack2search <FILE_with_above_bytes>");
2306 break;
2307 } else {
2308 PrintAndLogEx(NORMAL, "");
2309 PrintAndLogEx(FAILED, "Nonce replay and length extension attack ( %s )", _RED_("fail"));
2310 break;
2313 } while (attempt);
2315 if (attempt == 0) {
2316 PrintAndLogEx(NORMAL, "");
2317 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
2318 return PM3_ESOFT;
2321 t1 = msclock() - t1;
2322 PrintAndLogEx(SUCCESS, "\ntime " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0);
2323 return PM3_SUCCESS;
2326 /* Test code
2328 Test data and below information about it comes from
2329 http://www.mikrocontroller.net/attachment/102194/hitag2.c
2330 Written by "I.C. Wiener 2006-2007"
2332 "MIKRON" = O N M I K R
2333 Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
2334 Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
2335 Random = 65 6E 45 72 - Random IV, transmitted in clear
2336 ~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
2338 The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
2339 The inverse of the first 4 bytes is sent to the tag to authenticate.
2340 The rest is encrypted by XORing it with the subsequent keystream.
2342 static uint64_t hitag2_benchtest_gen32(void) {
2343 const uint64_t key = 0x4ad292b272f2;
2344 const uint32_t serial = 0x96eac292;
2345 const uint32_t initvec = 0x4ea276a6;
2346 hitag_state_t state;
2348 // init crypto
2349 ht2_hitag2_init_ex(&state, key, serial, initvec);
2351 // benchmark: generation of 32 bit stream (excludes initialisation)
2352 uint64_t t1 = usclock();
2354 (void) ht2_hitag2_nstep(&state, 32);
2356 t1 = usclock() - t1;
2357 return t1;
2360 static uint64_t hitag2_benchtest(uint32_t count) {
2362 const uint64_t key = 0x4ad292b272f2;
2363 const uint32_t serial = 0x96eac292;
2364 const uint32_t initvec = 0x4ea276a6;
2366 hitag_state_t state;
2368 // start timer
2369 uint64_t t1 = usclock();
2371 // benchmark: initialise crypto & generate 32 bit authentication
2372 // adding i stops gcc optimizer moving init function call out of loop
2373 for (uint32_t i = 0; i < count; i++) {
2374 ht2_hitag2_init_ex(&state, key, serial, initvec + i);
2375 (void) ht2_hitag2_nstep(&state, 32);
2378 t1 = usclock() - t1;
2379 return t1;
2382 static uint64_t hitag2_verify_crypto_test(void) {
2384 uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 };
2385 // key = 0x4ad292b272f2 after each byte has its bit order reversed
2386 // uid = 0x96eac292 ditto
2387 // initvec = 0x4ea276a6 ditto
2388 const uint64_t key = REV64(0x524B494D4E4FUL);
2389 const uint32_t uid = REV32(0x69574349);
2390 const uint32_t iv = REV32(0x72456E65);
2392 PrintAndLogEx(DEBUG, "UID... %08" PRIx32, uid);
2393 PrintAndLogEx(DEBUG, "IV.... %08" PRIx32, iv);
2394 PrintAndLogEx(DEBUG, "Key... %012" PRIx64, key);
2396 // initialise
2397 hitag_state_t state;
2398 ht2_hitag2_init_ex(&state, key, uid, iv);
2399 PrintAndLogEx(DEBUG, "hs shiftreg... %012" PRIx64, state.shiftreg);
2401 for (uint32_t i = 0; i < 16; i++) {
2402 // get 8 bits of keystream
2403 uint8_t x = (uint8_t) ht2_hitag2_nstep(&state, 8);
2404 uint8_t y = expected[i];
2406 PrintAndLogEx(DEBUG, "%02X (%02X)", x, y);
2407 if (x != y) {
2408 return 0;
2411 return 1;
2414 static uint64_t hitag2_verify_crypto_test_round(void) {
2416 uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 };
2417 const uint64_t key = REV64(0x524B494D4E4FUL);
2418 const uint32_t uid = REV32(0x69574349);
2419 const uint32_t iv = REV32(0x72456E65);
2421 PrintAndLogEx(DEBUG, "UID... %08" PRIx32, uid);
2422 PrintAndLogEx(DEBUG, "IV.... %08" PRIx32, iv);
2423 PrintAndLogEx(DEBUG, "Key... %012" PRIx64, key);
2425 // initialise
2426 uint64_t cs = ht2_hitag2_init(key, uid, iv);
2427 PrintAndLogEx(DEBUG, "hs shiftreg... %012" PRIx64, cs);
2429 for (uint32_t i = 0; i < 16; i++) {
2430 // get 8 bits of keystream
2431 uint8_t x = (uint8_t) ht2_hitag2_byte(&cs);
2432 uint8_t y = expected[i];
2434 PrintAndLogEx(DEBUG, "%02X (%02X)", x, y);
2435 if (x != y) {
2436 return 0;
2439 return 1;
2442 static int CmdLFHitag2Selftest(const char *Cmd) {
2443 CLIParserContext *ctx;
2444 CLIParserInit(&ctx, "lf hitag test",
2445 "Perform self tests of Hitag crypto engine",
2446 "lf hitag test\n"
2449 void *argtable[] = {
2450 arg_param_begin,
2451 arg_param_end
2453 CLIExecWithReturn(ctx, Cmd, argtable, true);
2454 CLIParserFree(ctx);
2456 PrintAndLogEx(INFO, "======== " _CYAN_("Hitag 2 crypto test") " ============================");
2457 uint64_t test = hitag2_verify_crypto_test();
2458 PrintAndLogEx(INFO, "Crypto self test ( %s )", test ? _GREEN_("ok") : _RED_("fail"));
2460 test |= hitag2_verify_crypto_test_round();
2461 PrintAndLogEx(INFO, "Crypto self test ROUND ( %s )", test ? _GREEN_("ok") : _RED_("fail"));
2463 test |= hitag2_benchtest(1);
2464 PrintAndLogEx(INFO, "Hitag 2 crypto, init + gen 32 bits ( us %" PRIu64 " )", test);
2466 test |= hitag2_benchtest_gen32();
2467 PrintAndLogEx(INFO, "Hitag 2 crypto, gen new 32 bits only ( us: %" PRIu64 " )", test);
2469 test |= hitag2_benchtest(1000);
2470 PrintAndLogEx(INFO, "Hitag 2 crypto, init + gen 32 bits, x1000 ( us: %" PRIu64 " )", test);
2472 PrintAndLogEx(INFO, "--------------------------------------------------------");
2473 PrintAndLogEx(SUCCESS, "Tests ( %s )", (test) ? _GREEN_("ok") : _RED_("fail"));
2474 PrintAndLogEx(NORMAL, "");
2475 return PM3_SUCCESS;
2478 static command_t CommandTable[] = {
2479 {"help", CmdHelp, AlwaysAvailable, "This help"},
2480 {"list", CmdLFHitagList, AlwaysAvailable, "List Hitag trace history"},
2481 {"hts", CmdLFHitagS, AlwaysAvailable, "{ Hitag S/8211 operations }"},
2482 {"-----------", CmdHelp, IfPm3Hitag, "------------------------ " _CYAN_("General") " ------------------------"},
2483 {"info", CmdLFHitagInfo, IfPm3Hitag, "Hitag 2 tag information"},
2484 {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag 2 reader"},
2485 {"test", CmdLFHitag2Selftest, AlwaysAvailable, "Perform self tests"},
2486 {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("Operations") " -----------------------"},
2487 // {"demod", CmdLFHitag2PWMDemod, IfPm3Hitag, "PWM Hitag 2 reader message demodulation"},
2488 {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag 2 tag"},
2489 {"read", CmdLFHitagRd, IfPm3Hitag, "Read Hitag memory"},
2490 {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication"},
2491 {"view", CmdLFHitagView, AlwaysAvailable, "Display content from tag dump file"},
2492 {"wrbl", CmdLFHitagWriter, IfPm3Hitag, "Write a block (page) in Hitag memory"},
2493 {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("Simulation") " -----------------------"},
2494 {"eload", CmdLFHitagEload, IfPm3Hitag, "Upload file into emulator memory"},
2495 // {"esave", CmdLFHitagESave, IfPm3Hitag, "Save emulator memory to file"},
2496 {"eview", CmdLFHitagEview, IfPm3Hitag, "View emulator memory"},
2497 {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder"},
2498 {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("Recovery") " -----------------------"},
2499 {"cc", CmdLFHitagSCheckChallenges, IfPm3Hitag, "Hitag S: test all provided challenges"},
2500 {"crack2", CmdLFHitag2Crack2, IfPm3Hitag, "Recover 2048bits of crypto stream"},
2501 {"chk", CmdLFHitag2Chk, IfPm3Hitag, "Check keys"},
2502 {"lookup", CmdLFHitag2Lookup, AlwaysAvailable, "Uses authentication trace to check for key in dictionary file"},
2503 {"ta", CmdLFHitag2CheckChallenges, IfPm3Hitag, "Hitag 2: test all recorded authentications"},
2504 { NULL, NULL, 0, NULL }
2507 static int CmdHelp(const char *Cmd) {
2508 (void)Cmd; // Cmd is not used so far
2509 CmdsHelp(CommandTable);
2510 return PM3_SUCCESS;
2513 int CmdLFHitag(const char *Cmd) {
2514 clearCommandBuffer();
2515 return CmdsParse(CommandTable, Cmd);
2518 int readHitagUid(void) {
2519 uint32_t uid = 0;
2520 if (getHitag2Uid(&uid) == false) {
2521 return PM3_ESOFT;
2524 PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid);
2525 PrintAndLogEx(SUCCESS, "TYPE... " _GREEN_("%s"), getHitagTypeStr(uid));
2526 return PM3_SUCCESS;