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
);
150 uint8_t mode
= arg_get_int_def(ctx
, 5, 3);
153 PrintAndLogEx(WARNING
, "Wrong response protocol mode, expected 0, 1, 2 or 3, got %d", mode
);
159 case HITAG_PASSWORD_SIZE
:
162 case HITAG_CRYPTOKEY_SIZE
:
165 default: // key_len == 0
167 memcpy(key
, "\xBB\xDD\x33\x99", 4);
169 } else if (use_crypto
) {
170 memcpy(key
, "ONMIKR", 6);
176 uint8_t auth_methods
= (use_plain
+ use_nrar
+ use_82xx
+ use_crypto
);
177 if (auth_methods
> 1) {
178 PrintAndLogEx(WARNING
, "Specify only one authentication mode");
182 if (auth_methods
== 0) {
186 memset(packet
, 0, sizeof(*packet
));
189 PrintAndLogEx(INFO
, "Access " _YELLOW_("Hitag S") " in Plain mode");
190 } else if (use_nrar
) {
191 packet
->cmd
= HTSF_CHALLENGE
;
192 memcpy(packet
->NrAr
, nrar
, sizeof(packet
->NrAr
));
193 PrintAndLogEx(INFO
, "Authenticating to " _YELLOW_("Hitag S") " in Challenge mode");
194 } else if (use_82xx
) {
195 packet
->cmd
= HTSF_82xx
;
196 memcpy(packet
->pwd
, key
, sizeof(packet
->pwd
));
197 PrintAndLogEx(INFO
, "Authenticating to " _YELLOW_("Hitag S") " in 82xx mode");
198 } else if (use_crypto
) {
199 packet
->cmd
= HTSF_KEY
;
200 memcpy(packet
->key
, key
, sizeof(packet
->key
));
201 PrintAndLogEx(INFO
, "Authenticating to " _YELLOW_("Hitag S") " in Crypto mode");
206 packet
->mode
= HITAGS_UID_REQ_STD
;
209 packet
->mode
= HITAGS_UID_REQ_ADV1
;
212 packet
->mode
= HITAGS_UID_REQ_ADV2
;
215 packet
->mode
= HITAGS_UID_REQ_FADV
;
222 static void print_error(int8_t reason
) {
225 PrintAndLogEx(FAILED
, "UID Request failed!");
228 PrintAndLogEx(FAILED
, "Select UID failed!");
231 PrintAndLogEx(FAILED
, "No write access on page " _YELLOW_("64") ". not 82xx?");
234 PrintAndLogEx(FAILED
, "Write to page " _YELLOW_("64") " failed! wrong password?");
237 PrintAndLogEx(FAILED
, "Error, " _YELLOW_("AUT=1") " This tag is configured in Authentication Mode");
240 PrintAndLogEx(FAILED
, "Error, unknown function");
243 PrintAndLogEx(FAILED
, "Authenticate failed!");
246 PrintAndLogEx(FAILED
, "No write access on page");
249 PrintAndLogEx(FAILED
, "Write to page failed!");
252 PrintAndLogEx(FAILED
, "Read page failed!");
255 // PM3_REASON_UNKNOWN
256 PrintAndLogEx(DEBUG
, "DEBUG: Error - Hitag S failed");
260 static int CmdLFHitagSRead(const char *Cmd
) {
261 CLIParserContext
*ctx
;
262 CLIParserInit(&ctx
, "lf hitag hts rdbl",
263 "Read Hitag S memory.\n\n"
265 " - key format ISK high + ISK low\n"
266 " - default key 4F4E4D494B52 (ONMIKR)\n\n"
267 " 8268/8310 password mode: \n"
268 " - default password BBDD3399\n",
269 " lf hitag hts rdbl -p 1 -> Hitag S/8211, plain mode\n"
270 " lf hitag hts rdbl -p 1 --82xx -k BBDD3399 -> 8268/8310, password mode\n"
271 " lf hitag hts rdbl -p 1 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
272 " lf hitag hts rdbl -p 1 --crypto -> Hitag S, crypto mode, def key\n"
273 " lf hitag hts rdbl -p 1 -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
278 arg_lit0("8", "82xx", "8268/8310 mode"),
279 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
280 arg_lit0(NULL
, "crypto", "crypto mode"),
281 arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
282 arg_int0("m", "mode", "<dec>", "response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)"),
283 arg_int0("p", "page", "<dec>", "page address to read from"),
284 arg_int0("c", "count", "<dec>", "how many pages to read. '0' reads all pages up to the end page (def: 1)"),
287 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
289 lf_hitag_data_t packet
;
291 if (process_hitags_common_args(ctx
, &packet
) < 0) return PM3_EINVARG
;
293 uint32_t page
= arg_get_int_def(ctx
, 6, 0);
296 PrintAndLogEx(WARNING
, "Page address Invalid.");
300 uint32_t count
= arg_get_int_def(ctx
, 7, 1);
302 if (count
> HITAGS_MAX_PAGES
) {
303 PrintAndLogEx(WARNING
, "No more than 64 pages can be read at once.");
310 packet
.page_count
= count
;
312 clearCommandBuffer();
313 SendCommandNG(CMD_LF_HITAGS_READ
, (uint8_t *) &packet
, sizeof(packet
));
315 PacketResponseNG resp
;
316 if (WaitForResponseTimeout(CMD_LF_HITAGS_READ
, &resp
, 2000) == false) {
317 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
318 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
322 if (resp
.status
!= PM3_SUCCESS
) {
323 print_error(resp
.reason
);
327 lf_hts_read_response_t
*card
= (lf_hts_read_response_t
*)resp
.data
.asBytes
;
329 hitags_config_t config
= card
->config_page
.s
;
331 PrintAndLogEx(NORMAL
, "");
332 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Information") " ---------------------------");
334 hitags_config_print(config
);
336 PrintAndLogEx(NORMAL
, "");
337 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Data") " ---------------------------");
338 PrintAndLogEx(INFO
, " # | 00 01 02 03 | ascii | perm | info");
339 PrintAndLogEx(INFO
, "----+-------------+-------+------+------");
341 const int hts_mem_sizes
[] = {1, 8, 64, 64};
344 count
= hts_mem_sizes
[config
.MEMT
] > page
? hts_mem_sizes
[config
.MEMT
] - page
: 64;
347 // int page_end = page + count;
348 // page_end = MIN(page_end, 255);
350 for (int i
= 0; i
< count
; ++i
) {
351 int page_addr
= page
+ i
;
352 if (page_addr
> 255) {
355 if (card
->pages_reason
[i
] >= 0) {
356 PrintAndLogEx(SUCCESS
, "% 3u | %s | " NOLF
, page_addr
, sprint_hex_ascii(card
->pages
[i
], HITAGS_PAGE_SIZE
));
359 if (page_addr
== HITAGS_UID_PADR
) {
360 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
361 } else if (page_addr
== HITAGS_CONFIG_PADR
) {
362 if (card
->config_page
.s
.LCON
)
363 PrintAndLogEx(NORMAL
, _YELLOW_("OTP ")NOLF
);
365 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
366 } else if (2 <= page_addr
&& page_addr
<= 3) {
367 if (card
->config_page
.s
.LKP
)
368 if (card
->config_page
.s
.auth
)
369 PrintAndLogEx(NORMAL
, _RED_("NO ")NOLF
);
371 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
373 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
374 } else if (4 <= page_addr
&& page_addr
<= 5) {
375 if (card
->config_page
.s
.LCK7
)
376 if (card
->config_page
.s
.TTFDR
== 2 && page_addr
== 5)
377 PrintAndLogEx(NORMAL
, _YELLOW_("RO/W")NOLF
);
379 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
381 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
382 } else if (6 <= page_addr
&& page_addr
<= 7) {
383 if (card
->config_page
.s
.LCK6
)
384 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
386 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
387 } else if (8 <= page_addr
&& page_addr
<= 11) {
388 if (card
->config_page
.s
.LCK5
)
389 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
391 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
392 } else if (12 <= page_addr
&& page_addr
<= 15) {
393 if (card
->config_page
.s
.LCK4
)
394 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
396 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
397 } else if (16 <= page_addr
&& page_addr
<= 23) {
398 if (card
->config_page
.s
.LCK3
)
399 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
401 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
402 } else if (24 <= page_addr
&& page_addr
<= 32) {
403 if (card
->config_page
.s
.LCK2
)
404 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
406 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
407 } else if (32 <= page_addr
&& page_addr
<= 47) {
408 if (card
->config_page
.s
.LCK1
)
409 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
411 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
412 } else if (48 <= page_addr
&& page_addr
<= 63) {
413 if (card
->config_page
.s
.LCK0
)
414 PrintAndLogEx(NORMAL
, _RED_("RO ")NOLF
);
416 PrintAndLogEx(NORMAL
, _GREEN_("RW ")NOLF
);
418 PrintAndLogEx(NORMAL
, _YELLOW_("UNK ") NOLF
);
420 PrintAndLogEx(NORMAL
, " | " NOLF
);
423 if (page_addr
== HITAGS_UID_PADR
) {
424 PrintAndLogEx(NORMAL
, "UID");
425 } else if (page_addr
== HITAGS_CONFIG_PADR
) {
426 PrintAndLogEx(NORMAL
, "Config");
427 } else if (page_addr
== 2 && card
->config_page
.s
.auth
) {
428 PrintAndLogEx(NORMAL
, "Pwd/Key");
429 } else if (page_addr
== 3 && card
->config_page
.s
.auth
) {
430 PrintAndLogEx(NORMAL
, "Key");
432 PrintAndLogEx(NORMAL
, "Data");
434 PrintAndLogEx(INFO
, "% 3u | -- -- -- -- | .... | N/A | " NOLF
, page_addr
);
435 print_error(card
->pages_reason
[i
]);
439 PrintAndLogEx(INFO
, "----+-------------+-------+------+------");
440 PrintAndLogEx(INFO
, " " _RED_("RO") " = Read Only, " _GREEN_("RW") " = Read Write");
441 PrintAndLogEx(INFO
, " " _YELLOW_("OTP") " = One Time Programmable");
442 PrintAndLogEx(INFO
, " " _YELLOW_("RO/W") " = Partially Read Write");
443 PrintAndLogEx(INFO
, "----------------------------------------");
447 static int CmdLFHitagSWrite(const char *Cmd
) {
448 CLIParserContext
*ctx
;
449 CLIParserInit(&ctx
, "lf hitag hts wrbl",
450 "Write a page in Hitag S memory.\n"
452 " - key format ISK high + ISK low\n"
453 " - default key 4F4E4D494B52 (ONMIKR)\n\n"
454 " 8268/8310 password mode: \n"
455 " - default password BBDD3399\n",
456 " lf hitag hts wrbl -p 6 -d 01020304 -> Hitag S/8211, plain mode\n"
457 " lf hitag hts wrbl -p 6 -d 01020304 --82xx -k BBDD3399 -> 8268/8310, password mode\n"
458 " lf hitag hts wrbl -p 6 -d 01020304 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
459 " lf hitag hts wrbl -p 6 -d 01020304 --crypto -> Hitag S, crypto mode, default key\n"
460 " lf hitag hts wrbl -p 6 -d 01020304 -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
465 arg_lit0("8", "82xx", "8268/8310 mode"),
466 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
467 arg_lit0(NULL
, "crypto", "crypto mode"),
468 arg_str0("k", "key", "<hex>", "pwd or key, 4 or 6 hex bytes"),
469 arg_int0("m", "mode", "<dec>", "response protocol mode. 0 (Standard 00110), 1 (Advanced 11000), 2 (Advanced 11001), 3 (Fast Advanced 11010) (def: 3)"),
470 arg_int1("p", "page", "<dec>", "page address to write to"),
471 arg_str1("d", "data", "<hex>", "data, 4 hex bytes"),
474 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
476 lf_hitag_data_t packet
;
478 if (process_hitags_common_args(ctx
, &packet
) < 0) return PM3_EINVARG
;
480 int page
= arg_get_int_def(ctx
, 6, 0);
482 uint8_t data
[HITAGS_PAGE_SIZE
];
485 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 7), data
, HITAGS_PAGE_SIZE
, &data_len
);
494 memcpy(packet
.data
, data
, sizeof(packet
.data
));
496 clearCommandBuffer();
497 SendCommandNG(CMD_LF_HITAGS_WRITE
, (uint8_t *) &packet
, sizeof(packet
));
499 PacketResponseNG resp
;
500 if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE
, &resp
, 4000) == false) {
501 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
505 if (resp
.status
== PM3_ETEAROFF
) {
506 PrintAndLogEx(INFO
, "Writing tear off triggered");
510 if (resp
.status
!= PM3_SUCCESS
) {
511 print_error(resp
.reason
);
515 PrintAndLogEx(SUCCESS
, "Write ( " _GREEN_("ok") " )");
519 static int CmdLFHitagSReader(const char *Cmd
) {
520 CLIParserContext
*ctx
;
521 CLIParserInit(&ctx
, "lf hitag hts reader",
522 "Act as a Hitag S reader. Look for Hitag S tags until Enter or the pm3 button is pressed\n",
523 "lf hitag hts reader\n"
524 "lf hitag hts reader -@ -> Continuous mode"
529 arg_lit0("@", NULL
, "continuous reader mode"),
532 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
533 bool cm
= arg_get_lit(ctx
, 1);
537 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
543 if (hts_get_uid(&uid
)) {
544 PrintAndLogEx(SUCCESS
, "UID.... " _GREEN_("%08X"), uid
);
546 } while (cm
&& kbd_enter_pressed() == false);
551 static int CmdLFHitagSSim(const char *Cmd
) {
552 CLIParserContext
*ctx
;
553 CLIParserInit(&ctx
, "lf hitag hts sim",
554 "Simulate Hitag S transponder\n"
555 "You need to `lf hitag hts eload` first",
557 "lf hitag hts sim --82xx");
561 arg_lit0("8", "82xx", "simulate 8268/8310"),
564 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
566 // bool use_82xx = arg_get_lit(ctx, 1); // not implemented yet
569 clearCommandBuffer();
570 SendCommandMIX(CMD_LF_HITAGS_SIMULATE
, false, 0, 0, NULL
, 0);
574 static int CmdLFHitagSList(const char *Cmd
) {
575 return CmdTraceListAlias(Cmd
, "lf hitag hts", "hitags");
578 void hitags_config_print(hitags_config_t config
) {
579 PrintAndLogEx(INFO
, " Memory type...... " _GREEN_("%s"),
581 "Hitag S 32", "Hitag S 256", "Hitag S 2048",
582 "Unknown Hitag S/8211"
585 PrintAndLogEx(INFO
, " Authenticaion.... %s", config
.auth
? _YELLOW_("Yes") : "No");
587 PrintAndLogEx(INFO
, " TTF coding....... %s",
588 config
.RES3
? "FSK 0=RF/10 1=RF/8" : (const char *[]) {"Manchester", "Biphase"}[config
.TTFC
]);
590 PrintAndLogEx(INFO
, " TTF data rate.... %s",
592 "4 kBit", "8 kBit", "2 kBit",
593 "2 kBit and Pigeon Race Standard"
596 PrintAndLogEx(INFO
, " TTF mode......... %s",
598 "TTF Mode disabled (= RTF Mode)",
600 "Page 4, Page 5, Page 6, Page 7",
602 "TTF Mode disabled (= RTF Mode)",
603 "Page 4, Page 5, Page 6",
604 "Page 4, Page 5, Page 6, Page 7, Page 8",
605 "Page 4, Page 5, Page 6, Page 7, Page 8, Page 9, Page 10, Page 11",
606 }[config
.RES0
<< 2 | config
.TTFM
]);
608 PrintAndLogEx(INFO
, " Config locked.... %s", config
.LCON
? _RED_("Yes") : _GREEN_("No"));
609 PrintAndLogEx(INFO
, " Key/PWD locked... %s", config
.LKP
? _RED_("Yes") : _GREEN_("No"));
612 static command_t CommandTable
[] = {
613 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
614 {"list", CmdLFHitagSList
, AlwaysAvailable
, "List Hitag S trace history"},
615 {"-----------", CmdHelp
, IfPm3Hitag
, "----------------------- " _CYAN_("General") " ------------------------"},
616 {"reader", CmdLFHitagSReader
, IfPm3Hitag
, "Act like a Hitag S reader"},
617 {"rdbl", CmdLFHitagSRead
, IfPm3Hitag
, "Read Hitag S page"},
618 {"wrbl", CmdLFHitagSWrite
, IfPm3Hitag
, "Write Hitag S page"},
619 {"-----------", CmdHelp
, IfPm3Hitag
, "----------------------- " _CYAN_("Simulation") " -----------------------"},
620 {"sim", CmdLFHitagSSim
, IfPm3Hitag
, "Simulate Hitag S transponder"},
621 {NULL
, NULL
, 0, NULL
}
624 static int CmdHelp(const char *Cmd
) {
625 (void) Cmd
; // Cmd is not used so far
626 CmdsHelp(CommandTable
);
630 int CmdLFHitagS(const char *Cmd
) {
631 clearCommandBuffer();
632 return CmdsParse(CommandTable
, Cmd
);