style
[RRG-proxmark3.git] / client / src / cmdlfhitaghts.c
blobe72d7194f63d1831ea67515653c1d776a1110370
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 S support
17 //-----------------------------------------------------------------------------
19 #include "cmdlfhitaghts.h"
20 #include <ctype.h>
21 #include "cmdparser.h" // command_t
22 #include "comms.h"
23 #include "cmdtrace.h"
24 #include "commonutil.h"
25 #include "hitag.h"
26 #include "fileutils.h" // savefile
27 #include "protocols.h" // defines
28 #include "cliparser.h"
29 #include "crc.h"
30 #include "graph.h" // MAX_GRAPH_TRACE_LEN
31 #include "lfdemod.h"
32 #include "cmddata.h" // setDemodBuff
33 #include "pm3_cmd.h" // return codes
34 #include "hitag2/hitag2_crypto.h"
35 #include "util_posix.h" // msclock
37 static int CmdHelp(const char *Cmd);
39 static const char *hts_get_type_str(uint32_t uid) {
40 // source 1: https://www.scorpio-lk.com/downloads/Tango/HITAG_Classification.pdf
41 // IDE Mark
42 // Each HITAG chip contains an unique Device Identifier (IDE ) so called a Serial Number.
43 // Bit 7 ot 4 of the IDE serve the function of a chip type identification. Example. IDE is 2A 48 E2 16, the IDE mark is "1".
45 // source 2: Hitag S product Specification Revision 3.1
46 // 6.1.1 Product Identifier (PID)
47 // The Product Identifier (PID) for the HITAG S Transponder IC is coded in the UID 3 Byte of the Unique Identifier (UID).
48 // This enables to distinguish between different ICs of the HITAG family
49 // | UID 3 |
50 // msb | PID 1 | PID 0 | lsb
51 // Condition for HITAG S: PID 1 = 0x7 – 0xF and PID 0 ≠ 0x5 – 0x6
53 //uid s/n ********
54 uint8_t pid0 = NIBBLE_LOW(uid);
55 uint8_t pid1 = NIBBLE_HIGH(uid);
56 if (pid1 >= 0x7 && pid1 <= 0xF && pid0 != 0x5 && pid0 != 0x6) {
57 switch (pid1) {
58 case 1:
59 return "PCF 7936";
60 case 2:
61 return "PCF 7946";
62 case 3:
63 return "PCF 7947";
64 case 4:
65 return "PCF 7942/44";
66 case 5:
67 return "PCF 7943";
68 case 6:
69 return "PCF 7941";
70 case 7:
71 return "PCF 7952";
72 case 9:
73 return "PCF 7945";
74 default:
75 return "n/a";
77 } else
78 return "Probably not NXP Hitag S";
81 static bool hts_get_uid(uint32_t *uid) {
82 clearCommandBuffer();
83 SendCommandNG(CMD_LF_HITAGS_UID, NULL, 0);
84 PacketResponseNG resp;
85 if (WaitForResponseTimeout(CMD_LF_HITAGS_UID, &resp, 1500) == false) {
86 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
87 return false;
90 if (resp.status != PM3_SUCCESS) {
91 PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID");
92 return false;
95 if (uid) {
96 *uid = bytes_to_num(resp.data.asBytes, HITAG_UID_SIZE);
98 return true;
101 int read_hts_uid(void) {
102 uint32_t uid = 0;
103 if (hts_get_uid(&uid) == false) {
104 return PM3_ESOFT;
107 PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid);
108 PrintAndLogEx(SUCCESS, "TYPE... " _GREEN_("%s"), hts_get_type_str(uid));
109 return PM3_SUCCESS;
112 static int process_hitags_common_args(CLIParserContext *ctx, lf_hitag_data_t *const packet) {
114 bool use_plain = false;
115 bool use_82xx = arg_get_lit(ctx, 1);
117 bool use_nrar = false;
118 uint8_t nrar[HITAG_NRAR_SIZE];
119 int nrar_len = 0;
121 int res = CLIParamHexToBuf(arg_get_str(ctx, 2), nrar, HITAG_NRAR_SIZE, &nrar_len);
122 if (res != 0) {
123 CLIParserFree(ctx);
124 return PM3_EINVARG;
127 use_nrar = nrar_len > 0;
129 bool use_crypto = arg_get_lit(ctx, 3);
131 uint8_t key[HITAG_CRYPTOKEY_SIZE];
132 int key_len = 0;
134 res = CLIParamHexToBuf(arg_get_str(ctx, 4), key, HITAG_CRYPTOKEY_SIZE, &key_len);
135 if (res != 0) {
136 CLIParserFree(ctx);
137 return PM3_EINVARG;
140 if (key_len != 0 && key_len != HITAG_PASSWORD_SIZE && key_len != HITAG_CRYPTOKEY_SIZE) {
141 PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", key_len);
142 return PM3_EINVARG;
145 if (nrar_len && nrar_len != HITAG_NRAR_SIZE) {
146 PrintAndLogEx(WARNING, "Wrong NR/AR len expected %d, got %d", HITAG_NRAR_SIZE, nrar_len);
147 return PM3_EINVARG;
150 // complete options
151 switch (key_len) {
152 case HITAG_PASSWORD_SIZE:
153 use_82xx = true;
154 break;
155 case HITAG_CRYPTOKEY_SIZE:
156 use_crypto = true;
157 break;
158 default: // key_len == 0
159 if (use_82xx) {
160 memcpy(key, "\xBB\xDD\x33\x99", 4);
161 key_len = 4;
162 } else if (use_crypto) {
163 memcpy(key, "ONMIKR", 6);
164 key_len = 6;
168 // check coherence
169 uint8_t auth_methods = (use_plain + use_nrar + use_82xx + use_crypto);
170 if (auth_methods > 1) {
171 PrintAndLogEx(WARNING, "Specify only one authentication mode");
172 return PM3_EINVARG;
175 if (auth_methods == 0) {
176 use_plain = true;
179 memset(packet, 0, sizeof(*packet));
181 if (use_plain) {
182 PrintAndLogEx(INFO, "Access " _YELLOW_("Hitag S") " in Plain mode");
183 } else if (use_nrar) {
184 packet->cmd = HTSF_CHALLENGE;
185 memcpy(packet->NrAr, nrar, sizeof(packet->NrAr));
186 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Challenge mode");
187 } else if (use_82xx) {
188 packet->cmd = HTSF_82xx;
189 memcpy(packet->pwd, key, sizeof(packet->pwd));
190 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in 82xx mode");
191 } else if (use_crypto) {
192 packet->cmd = HTSF_KEY;
193 memcpy(packet->key, key, sizeof(packet->key));
194 PrintAndLogEx(INFO, "Authenticating to " _YELLOW_("Hitag S") " in Crypto mode");
197 return PM3_SUCCESS;
200 static void print_error(int8_t reason) {
201 switch (reason) {
202 case -2:
203 PrintAndLogEx(FAILED, "UID Request failed!");
204 break;
205 case -3:
206 PrintAndLogEx(FAILED, "Select UID failed!");
207 break;
208 case -4:
209 PrintAndLogEx(FAILED, "No write access on page " _YELLOW_("64") ". not 82xx?");
210 break;
211 case -5:
212 PrintAndLogEx(FAILED, "Write to page " _YELLOW_("64") " failed! wrong password?");
213 break;
214 case -6:
215 PrintAndLogEx(FAILED, "Error, " _YELLOW_("AUT=1") " This tag is configured in Authentication Mode");
216 break;
217 case -7:
218 PrintAndLogEx(FAILED, "Error, unknown function");
219 break;
220 case -8:
221 PrintAndLogEx(FAILED, "Authenticate failed!");
222 break;
223 case -9:
224 PrintAndLogEx(FAILED, "No write access on page");
225 break;
226 case -10:
227 PrintAndLogEx(FAILED, "Write to page failed!");
228 break;
229 default:
230 // PM3_REASON_UNKNOWN
231 PrintAndLogEx(DEBUG, "DEBUG: Error - Hitag S failed");
235 static int CmdLFHitagSRead(const char *Cmd) {
236 CLIParserContext *ctx;
237 CLIParserInit(&ctx, "lf hitag hts rdbl",
238 "Read Hitag S memory.\n\n"
239 " Crypto mode: \n"
240 " - key format ISK high + ISK low\n"
241 " - default key 4F4E4D494B52 (ONMIKR)\n\n"
242 " 8268/8310 password mode: \n"
243 " - default password BBDD3399\n",
244 " lf hitag hts rdbl -p 1 -> Hitag S/8211, plain mode\n"
245 " lf hitag hts rdbl -p 1 --82xx -k BBDD3399 -> 8268/8310, password mode\n"
246 " lf hitag hts rdbl -p 1 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
247 " lf hitag hts rdbl -p 1 --crypto -> Hitag S, crypto mode, def key\n"
248 " lf hitag hts rdbl -p 1 -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
251 void *argtable[] = {
252 arg_param_begin,
253 arg_lit0("8", "82xx", "8268/8310 mode"),
254 arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
255 arg_lit0(NULL, "crypto", "crypto mode"),
256 arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
257 arg_int0("p", "page", "<dec>", "page address to read from"),
258 arg_int0("c", "count", "<dec>", "how many pages to read. '0' reads all pages up to the end page (default: 1)"),
259 arg_param_end
261 CLIExecWithReturn(ctx, Cmd, argtable, true);
263 lf_hitag_data_t packet;
265 if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
267 uint32_t page = arg_get_int_def(ctx, 5, 0);
269 if (page > 255) {
270 PrintAndLogEx(WARNING, "Page address Invalid.");
271 return PM3_EINVARG;
274 uint32_t count = arg_get_int_def(ctx, 6, 1);
276 if (count > HITAGS_MAX_PAGES) {
277 PrintAndLogEx(WARNING, "No more than 64 pages can be read at once.");
278 return PM3_EINVARG;
281 CLIParserFree(ctx);
283 packet.page = page;
284 packet.page_count = count;
286 clearCommandBuffer();
287 SendCommandNG(CMD_LF_HITAGS_READ, (uint8_t *) &packet, sizeof(packet));
289 PacketResponseNG resp;
290 if (WaitForResponseTimeout(CMD_LF_HITAGS_READ, &resp, 2000) == false) {
291 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
292 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
293 return PM3_ETIMEOUT;
296 if (resp.status != PM3_SUCCESS) {
297 print_error(resp.reason);
298 return PM3_ESOFT;
301 lf_hts_read_response_t *card = (lf_hts_read_response_t *)resp.data.asBytes;
303 hitags_config_t config = card->config_page.s;
305 PrintAndLogEx(NORMAL, "");
306 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
308 hitags_config_print(config);
310 PrintAndLogEx(NORMAL, "");
311 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Data") " ---------------------------");
312 PrintAndLogEx(INFO, " # | 00 01 02 03 | ascii | perm | info");
313 PrintAndLogEx(INFO, "----+-------------+-------+------+------");
315 const int hts_mem_sizes[] = {1, 8, 64, 64};
317 if (count == 0) {
318 count = hts_mem_sizes[config.MEMT] > page ? hts_mem_sizes[config.MEMT] - page : 64;
321 // int page_end = page + count;
322 // page_end = MIN(page_end, 255);
324 for (int i = 0; i < count; ++i) {
325 int page_addr = page + i;
326 if (page_addr > 255) {
327 break;
329 if (card->pages_reason[i] >= 0) {
330 PrintAndLogEx(SUCCESS, "% 3u | %s | " NOLF, page_addr, sprint_hex_ascii(card->pages[i], HITAGS_PAGE_SIZE));
332 // access right
333 if (page_addr == HITAGS_UID_PADR) {
334 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
335 } else if (page_addr == HITAGS_CONFIG_PADR) {
336 if (card->config_page.s.LCON)
337 PrintAndLogEx(NORMAL, _YELLOW_("OTP ")NOLF);
338 else
339 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
340 } else if (2 <= page_addr && page_addr <= 3) {
341 if (card->config_page.s.LKP)
342 if (card->config_page.s.auth)
343 PrintAndLogEx(NORMAL, _RED_("NO ")NOLF);
344 else
345 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
346 else
347 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
348 } else if (4 <= page_addr && page_addr <= 5) {
349 if (card->config_page.s.LCK7)
350 if (card->config_page.s.TTFDR == 2 && page_addr == 5)
351 PrintAndLogEx(NORMAL, _YELLOW_("RO/W")NOLF);
352 else
353 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
354 else
355 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
356 } else if (6 <= page_addr && page_addr <= 7) {
357 if (card->config_page.s.LCK6)
358 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
359 else
360 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
361 } else if (8 <= page_addr && page_addr <= 11) {
362 if (card->config_page.s.LCK5)
363 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
364 else
365 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
366 } else if (12 <= page_addr && page_addr <= 15) {
367 if (card->config_page.s.LCK4)
368 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
369 else
370 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
371 } else if (16 <= page_addr && page_addr <= 23) {
372 if (card->config_page.s.LCK3)
373 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
374 else
375 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
376 } else if (24 <= page_addr && page_addr <= 32) {
377 if (card->config_page.s.LCK2)
378 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
379 else
380 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
381 } else if (32 <= page_addr && page_addr <= 47) {
382 if (card->config_page.s.LCK1)
383 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
384 else
385 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
386 } else if (48 <= page_addr && page_addr <= 63) {
387 if (card->config_page.s.LCK0)
388 PrintAndLogEx(NORMAL, _RED_("RO ")NOLF);
389 else
390 PrintAndLogEx(NORMAL, _GREEN_("RW ")NOLF);
391 } else
392 PrintAndLogEx(NORMAL, _YELLOW_("UNK ") NOLF);
394 PrintAndLogEx(NORMAL, " | " NOLF);
396 // info
397 if (page_addr == HITAGS_UID_PADR) {
398 PrintAndLogEx(NORMAL, "UID");
399 } else if (page_addr == HITAGS_CONFIG_PADR) {
400 PrintAndLogEx(NORMAL, "Config");
401 } else if (page_addr == 2 && card->config_page.s.auth) {
402 PrintAndLogEx(NORMAL, "Pwd/Key");
403 } else if (page_addr == 3 && card->config_page.s.auth) {
404 PrintAndLogEx(NORMAL, "Key");
405 } else
406 PrintAndLogEx(NORMAL, "Data");
407 } else
408 PrintAndLogEx(INFO, "%02u | -- -- -- -- | read failed reason: " _YELLOW_("%d"), page_addr, card->pages_reason[i]);
411 PrintAndLogEx(INFO, "----+-------------+-------+------+------");
412 PrintAndLogEx(INFO, " " _RED_("RO") " = Read Only, " _GREEN_("RW") " = Read Write");
413 PrintAndLogEx(INFO, " " _YELLOW_("OTP") " = One Time Programmable");
414 PrintAndLogEx(INFO, " " _YELLOW_("RO/W") " = Partially Read Write");
415 PrintAndLogEx(INFO, "----------------------------------------");
416 return PM3_SUCCESS;
419 static int CmdLFHitagSWrite(const char *Cmd) {
420 CLIParserContext *ctx;
421 CLIParserInit(&ctx, "lf hitag hts wrbl",
422 "Write a page in Hitag S memory.\n"
423 " Crypto mode: \n"
424 " - key format ISK high + ISK low\n"
425 " - default key 4F4E4D494B52 (ONMIKR)\n\n"
426 " 8268/8310 password mode: \n"
427 " - default password BBDD3399\n",
428 " lf hitag hts wrbl -p 6 -d 01020304 -> Hitag S/8211, plain mode\n"
429 " lf hitag hts wrbl -p 6 -d 01020304 --82xx -k BBDD3399 -> 8268/8310, password mode\n"
430 " lf hitag hts wrbl -p 6 -d 01020304 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
431 " lf hitag hts wrbl -p 6 -d 01020304 --crypto -> Hitag S, crypto mode, default key\n"
432 " lf hitag hts wrbl -p 6 -d 01020304 -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
435 void *argtable[] = {
436 arg_param_begin,
437 arg_lit0("8", "82xx", "8268/8310 mode"),
438 arg_str0(NULL, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
439 arg_lit0(NULL, "crypto", "crypto mode"),
440 arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
441 arg_int1("p", "page", "<dec>", "page address to write to"),
442 arg_str1("d", "data", "<hex>", "data, 4 hex bytes"),
443 arg_param_end
445 CLIExecWithReturn(ctx, Cmd, argtable, false);
447 lf_hitag_data_t packet;
449 if (process_hitags_common_args(ctx, &packet) < 0) return PM3_EINVARG;
451 int page = arg_get_int_def(ctx, 5, 0);
453 uint8_t data[HITAGS_PAGE_SIZE];
454 int data_len = 0;
456 int res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, HITAGS_PAGE_SIZE, &data_len);
457 if (res != 0) {
458 CLIParserFree(ctx);
459 return PM3_EINVARG;
462 CLIParserFree(ctx);
464 packet.page = page;
465 memcpy(packet.data, data, sizeof(packet.data));
467 clearCommandBuffer();
468 SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *) &packet, sizeof(packet));
470 PacketResponseNG resp;
471 if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 4000) == false) {
472 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
473 return PM3_ETIMEOUT;
476 if (resp.status == PM3_ETEAROFF) {
477 PrintAndLogEx(INFO, "Writing tear off triggered");
478 return PM3_SUCCESS;
481 if (resp.status != PM3_SUCCESS) {
482 print_error(resp.reason);
483 return resp.status;
486 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
487 return PM3_SUCCESS;
490 static int CmdLFHitagSReader(const char *Cmd) {
491 CLIParserContext *ctx;
492 CLIParserInit(&ctx, "lf hitag hts reader",
493 "Act as a Hitag S reader. Look for Hitag S tags until Enter or the pm3 button is pressed\n",
494 "lf hitag hts reader\n"
495 "lf hitag hts reader -@ -> Continuous mode"
498 void *argtable[] = {
499 arg_param_begin,
500 arg_lit0("@", NULL, "continuous reader mode"),
501 arg_param_end
503 CLIExecWithReturn(ctx, Cmd, argtable, true);
504 bool cm = arg_get_lit(ctx, 1);
505 CLIParserFree(ctx);
507 if (cm) {
508 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
511 do {
512 // read UID
513 uint32_t uid = 0;
514 if (hts_get_uid(&uid)) {
515 PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid);
517 } while (cm && kbd_enter_pressed() == false);
519 return PM3_SUCCESS;
522 static int CmdLFHitagSSim(const char *Cmd) {
523 CLIParserContext *ctx;
524 CLIParserInit(&ctx, "lf hitag hts sim",
525 "Simulate Hitag S transponder\n"
526 "You need to `lf hitag hts eload` first",
527 "lf hitag hts sim\n"
528 "lf hitag hts sim --82xx");
530 void *argtable[] = {
531 arg_param_begin,
532 arg_lit0("8", "82xx", "simulate 8268/8310"),
533 arg_param_end
535 CLIExecWithReturn(ctx, Cmd, argtable, true);
537 // bool use_82xx = arg_get_lit(ctx, 1); // not implemented yet
538 CLIParserFree(ctx);
540 clearCommandBuffer();
541 SendCommandNG(CMD_LF_HITAGS_SIMULATE, NULL, 0);
542 return PM3_SUCCESS;
545 static int CmdLFHitagSList(const char *Cmd) {
546 return CmdTraceListAlias(Cmd, "lf hitag hts", "hitags");
549 void hitags_config_print(hitags_config_t config) {
550 PrintAndLogEx(INFO, " Memory type...... " _GREEN_("%s"),
551 (const char *[]) {
552 "Hitag S 32", "Hitag S 256", "Hitag S 2048",
553 "Unknown Hitag S/8211"
554 }[config.MEMT]);
556 PrintAndLogEx(INFO, " Authenticaion.... %s", config.auth ? _YELLOW_("Yes") : "No");
558 PrintAndLogEx(INFO, " TTF coding....... %s",
559 config.RES3 ? "FSK 0=RF/10 1=RF/8" : (const char *[]) {"Manchester", "Biphase"}[config.TTFC]);
561 PrintAndLogEx(INFO, " TTF data rate.... %s",
562 (const char *[]) {
563 "4 kBit", "8 kBit", "2 kBit",
564 "2 kBit and Pigeon Race Standard"
565 }[config.TTFDR]);
567 PrintAndLogEx(INFO, " TTF mode......... %s",
568 (const char *[]) {
569 "TTF Mode disabled (= RTF Mode)",
570 "Page 4, Page 5",
571 "Page 4, Page 5, Page 6, Page 7",
572 "Page 4",
573 "TTF Mode disabled (= RTF Mode)",
574 "Page 4, Page 5, Page 6",
575 "Page 4, Page 5, Page 6, Page 7, Page 8",
576 "Page 4, Page 5, Page 6, Page 7, Page 8, Page 9, Page 10, Page 11",
577 }[config.RES0 << 2 | config.TTFM]);
579 PrintAndLogEx(INFO, " Config locked.... %s", config.LCON ? _RED_("Yes") : _GREEN_("No"));
580 PrintAndLogEx(INFO, " Key/PWD locked... %s", config.LKP ? _RED_("Yes") : _GREEN_("No"));
583 static command_t CommandTable[] = {
584 {"help", CmdHelp, AlwaysAvailable, "This help"},
585 {"list", CmdLFHitagSList, AlwaysAvailable, "List Hitag S trace history"},
586 {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("General") " ------------------------"},
587 {"reader", CmdLFHitagSReader, IfPm3Hitag, "Act like a Hitag S reader"},
588 {"rdbl", CmdLFHitagSRead, IfPm3Hitag, "Read Hitag S page"},
589 {"wrbl", CmdLFHitagSWrite, IfPm3Hitag, "Write Hitag S page"},
590 {"-----------", CmdHelp, IfPm3Hitag, "----------------------- " _CYAN_("Simulation") " -----------------------"},
591 {"sim", CmdLFHitagSSim, IfPm3Hitag, "Simulate Hitag S transponder"},
592 {NULL, NULL, 0, NULL}
595 static int CmdHelp(const char *Cmd) {
596 (void) Cmd; // Cmd is not used so far
597 CmdsHelp(CommandTable);
598 return PM3_SUCCESS;
601 int CmdLFHitagS(const char *Cmd) {
602 clearCommandBuffer();
603 return CmdsParse(CommandTable, Cmd);