1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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"
21 #include "cmdparser.h" // command_t
24 #include "commonutil.h"
26 #include "fileutils.h" // savefile
27 #include "protocols.h" // defines
28 #include "cliparser.h"
30 #include "graph.h" // MAX_GRAPH_TRACE_LEN
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
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
50 // msb | PID 1 | PID 0 | lsb
51 // Condition for HITAG S: PID 1 = 0x7 – 0xF and PID 0 ≠ 0x5 – 0x6
54 uint8_t pid0
= NIBBLE_LOW(uid
);
55 uint8_t pid1
= NIBBLE_HIGH(uid
);
56 if (pid1
>= 0x7 && pid1
<= 0xF && pid0
!= 0x5 && pid0
!= 0x6) {
78 return "Probably not NXP Hitag S";
81 static bool hts_get_uid(uint32_t *uid
) {
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.");
90 if (resp
.status
!= PM3_SUCCESS
) {
91 PrintAndLogEx(DEBUG
, "DEBUG: Error - failed getting UID");
96 *uid
= bytes_to_num(resp
.data
.asBytes
, HITAG_UID_SIZE
);
101 int read_hts_uid(void) {
103 if (hts_get_uid(&uid
) == false) {
107 PrintAndLogEx(SUCCESS
, "UID.... " _GREEN_("%08X"), uid
);
108 PrintAndLogEx(SUCCESS
, "TYPE... " _GREEN_("%s"), hts_get_type_str(uid
));
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
];
121 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 2), nrar
, HITAG_NRAR_SIZE
, &nrar_len
);
127 use_nrar
= nrar_len
> 0;
129 bool use_crypto
= arg_get_lit(ctx
, 3);
131 uint8_t key
[HITAG_CRYPTOKEY_SIZE
];
134 res
= CLIParamHexToBuf(arg_get_str(ctx
, 4), key
, HITAG_CRYPTOKEY_SIZE
, &key_len
);
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
);
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
);
152 case HITAG_PASSWORD_SIZE
:
155 case HITAG_CRYPTOKEY_SIZE
:
158 default: // key_len == 0
160 memcpy(key
, "\xBB\xDD\x33\x99", 4);
162 } else if (use_crypto
) {
163 memcpy(key
, "ONMIKR", 6);
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");
175 if (auth_methods
== 0) {
179 memset(packet
, 0, sizeof(*packet
));
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");
200 static void print_error(int8_t reason
) {
203 PrintAndLogEx(FAILED
, "UID Request failed!");
206 PrintAndLogEx(FAILED
, "Select UID failed!");
209 PrintAndLogEx(FAILED
, "No write access on page " _YELLOW_("64") ". not 82xx?");
212 PrintAndLogEx(FAILED
, "Write to page " _YELLOW_("64") " failed! wrong password?");
215 PrintAndLogEx(FAILED
, "Error, " _YELLOW_("AUT=1") " This tag is configured in Authentication Mode");
218 PrintAndLogEx(FAILED
, "Error, unknown function");
221 PrintAndLogEx(FAILED
, "Authenticate failed!");
224 PrintAndLogEx(FAILED
, "No write access on page");
227 PrintAndLogEx(FAILED
, "Write to page failed!");
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"
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"
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)"),
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);
270 PrintAndLogEx(WARNING
, "Page address Invalid.");
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.");
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);
296 if (resp
.status
!= PM3_SUCCESS
) {
297 print_error(resp
.reason
);
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};
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) {
329 if (card
->pages_reason
[i
] >= 0) {
330 PrintAndLogEx(SUCCESS
, "% 3u | %s | " NOLF
, page_addr
, sprint_hex_ascii(card
->pages
[i
], HITAGS_PAGE_SIZE
));
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
);
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
);
345 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
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
);
353 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
390 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
392 PrintAndLogEx(NORMAL
, _YELLOW_("UNK ") NOLF
);
394 PrintAndLogEx(NORMAL
, " | " NOLF
);
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");
406 PrintAndLogEx(NORMAL
, "Data");
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
, "----------------------------------------");
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"
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"
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"),
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
];
456 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 6), data
, HITAGS_PAGE_SIZE
, &data_len
);
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.");
476 if (resp
.status
== PM3_ETEAROFF
) {
477 PrintAndLogEx(INFO
, "Writing tear off triggered");
481 if (resp
.status
!= PM3_SUCCESS
) {
482 print_error(resp
.reason
);
486 PrintAndLogEx(SUCCESS
, "Write ( " _GREEN_("ok") " )");
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"
500 arg_lit0("@", NULL
, "continuous reader mode"),
503 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
504 bool cm
= arg_get_lit(ctx
, 1);
508 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
514 if (hts_get_uid(&uid
)) {
515 PrintAndLogEx(SUCCESS
, "UID.... " _GREEN_("%08X"), uid
);
517 } while (cm
&& kbd_enter_pressed() == false);
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",
528 "lf hitag hts sim --82xx");
532 arg_lit0("8", "82xx", "simulate 8268/8310"),
535 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
537 // bool use_82xx = arg_get_lit(ctx, 1); // not implemented yet
540 clearCommandBuffer();
541 SendCommandNG(CMD_LF_HITAGS_SIMULATE
, NULL
, 0);
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"),
552 "Hitag S 32", "Hitag S 256", "Hitag S 2048",
553 "Unknown Hitag S/8211"
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",
563 "4 kBit", "8 kBit", "2 kBit",
564 "2 kBit and Pigeon Race Standard"
567 PrintAndLogEx(INFO
, " TTF mode......... %s",
569 "TTF Mode disabled (= RTF Mode)",
571 "Page 4, Page 5, Page 6, Page 7",
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
);
601 int CmdLFHitagS(const char *Cmd
) {
602 clearCommandBuffer();
603 return CmdsParse(CommandTable
, Cmd
);