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
);
40 static int CmdLFHitagSRead(const char *Cmd
) {
41 CLIParserContext
*ctx
;
42 CLIParserInit(&ctx
, "lf hitag hts read",
43 "Read Hitag S memory.\n\n"
45 " - key format ISK high + ISK low\n"
46 " - default key 4F4E4D494B52 (ONMIKR)\n",
47 " lf hitag hts read -> Hitag S, plain mode\n"
48 " lf hitag hts read --nrar 0102030411223344 -> Hitag S, challenge mode\n"
49 " lf hitag hts read --crypto -> Hitag S, crypto mode, def key\n"
50 " lf hitag hts read -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
55 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
56 arg_lit0(NULL
, "crypto", "crypto mode"),
57 arg_str0("k", "key", "<hex>", "key, 4 or 6 hex bytes"),
60 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
62 bool use_plain
= false;
67 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), nrar
, sizeof(nrar
), &nrar_len
);
73 bool use_nrar
= nrar_len
> 0;
74 bool use_crypto
= arg_get_lit(ctx
, 2);
79 res
= CLIParamHexToBuf(arg_get_str(ctx
, 3), key
, sizeof(key
), &key_len
);
87 if (key_len
&& key_len
!= HITAGS_CRYPTOKEY_SIZE
) {
88 PrintAndLogEx(WARNING
, "Wrong KEY len expected %d, got %d", HITAGS_CRYPTOKEY_SIZE
, key_len
);
92 if (nrar_len
&& nrar_len
!= HITAGS_NRAR_SIZE
) {
93 PrintAndLogEx(WARNING
, "Wrong NR/AR len expected %d, got %d", HITAGS_NRAR_SIZE
, nrar_len
);
97 if (!key_len
&& use_crypto
) {
98 memcpy(key
, "ONMIKR", 6);
103 uint8_t auth_methods
= (use_plain
+ use_nrar
+ use_crypto
);
104 if (auth_methods
> 1) {
105 PrintAndLogEx(WARNING
, "Specify only one authentication mode");
107 } else if (auth_methods
== 0) {
111 lf_hitag_data_t packet
;
112 memset(&packet
, 0, sizeof(packet
));
114 int pm3cmd
= CMD_LF_HITAGS_READ
;
117 packet
.cmd
= RHTSF_CHALLENGE
;
118 memcpy(packet
.NrAr
, nrar
, sizeof(packet
.NrAr
));
122 packet
.cmd
= RHTSF_KEY
;
123 memcpy(packet
.key
, key
, sizeof(packet
.key
));
126 clearCommandBuffer();
127 SendCommandNG(pm3cmd
, (uint8_t *) &packet
, sizeof(packet
));
129 PacketResponseNG resp
;
130 if (WaitForResponseTimeout(pm3cmd
, &resp
, 2000) == false) {
131 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
132 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
136 if (resp
.status
!= PM3_SUCCESS
) {
137 PrintAndLogEx(DEBUG
, "DEBUG: Error - hitag failed");
146 uint8_t *data
= resp
.data
.asBytes
;
148 hitags_config_t config
= hitags_config_unpack(data
+ HITAGS_PAGE_SIZE
);
150 PrintAndLogEx(NORMAL
, "");
151 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Information") " ---------------------------");
153 hitags_config_print(config
);
155 PrintAndLogEx(NORMAL
, "");
156 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Data") " ----------------------------------");
158 uint32_t size
= (const int[]) {4, 32, 256, 0}[config
.memory_type
];
160 print_hex_break(data
, size
, HITAGS_PAGE_SIZE
);
165 static int CmdLFHitagSWrite(const char *Cmd
) {
166 CLIParserContext
*ctx
;
167 CLIParserInit(&ctx
, "lf hitag hts write",
168 "Write a page in Hitag S memory.\n"
170 " - key format ISK high + ISK low\n"
171 " - default key 4F4E4D494B52 (ONMIKR)\n",
172 " lf hitag hts write -p 6 -d 01020304 -> Hitag S, plain mode\n"
173 " lf hitag hts write -p 6 -d 01020304 --nrar 0102030411223344 -> Hitag S, challenge mode\n"
174 " lf hitag hts write -p 6 -d 01020304 --crypto -> Hitag S, crypto mode, default key\n"
175 " lf hitag hts write -p 6 -d 01020304 -k 4F4E4D494B52 -> Hitag S, crypto mode\n\n"
180 arg_str0(NULL
, "nrar", "<hex>", "nonce / answer writer, 8 hex bytes"),
181 arg_lit0(NULL
, "crypto", "crypto mode"),
182 arg_str0("k", "key", "<hex>", "key, 6 hex bytes"),
183 arg_int1("p", "page", "<dec>", "page address to write to"),
184 arg_str1("d", "data", "<hex>", "data, 4 hex bytes"),
187 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
189 bool use_plain
= false;
194 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), nrar
, sizeof(nrar
), &nrar_len
);
200 bool use_nrar
= nrar_len
> 0;
201 bool use_crypto
= arg_get_lit(ctx
, 2);
206 res
= CLIParamHexToBuf(arg_get_str(ctx
, 3), key
, sizeof(key
), &key_len
);
212 int page
= arg_get_int_def(ctx
, 4, 0);
217 res
= CLIParamHexToBuf(arg_get_str(ctx
, 5), data
, sizeof(data
), &data_len
);
225 if (key_len
&& key_len
!= HITAGS_CRYPTOKEY_SIZE
) {
226 PrintAndLogEx(WARNING
, "Wrong KEY len expected %d, got %d", HITAGS_CRYPTOKEY_SIZE
, key_len
);
230 if (nrar_len
&& nrar_len
!= HITAGS_NRAR_SIZE
) {
231 PrintAndLogEx(WARNING
, "Wrong NR/AR len expected %d, got %d", HITAGS_NRAR_SIZE
, nrar_len
);
235 if (!key_len
&& use_crypto
) {
236 memcpy(key
, "ONMIKR", 6);
241 uint8_t auth_methods
= (use_plain
+ use_nrar
+ use_crypto
);
242 if (auth_methods
> 1) {
243 PrintAndLogEx(WARNING
, "Specify only one authentication mode");
245 } else if (auth_methods
== 0) {
249 lf_hitag_data_t packet
;
250 memset(&packet
, 0, sizeof(packet
));
253 memcpy(packet
.data
, data
, sizeof(data
));
256 packet
.cmd
= WHTSF_CHALLENGE
;
257 memcpy(packet
.NrAr
, nrar
, sizeof(packet
.NrAr
));
261 packet
.cmd
= WHTSF_KEY
;
262 memcpy(packet
.key
, key
, sizeof(packet
.key
));
265 clearCommandBuffer();
266 SendCommandNG(CMD_LF_HITAGS_WRITE
, (uint8_t *) &packet
, sizeof(packet
));
268 PacketResponseNG resp
;
269 if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE
, &resp
, 4000) == false) {
270 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
274 if (resp
.status
== PM3_ETEAROFF
) {
275 PrintAndLogEx(INFO
, "Writing tear off triggered");
279 if (resp
.status
!= PM3_SUCCESS
) {
280 PrintAndLogEx(FAILED
, "Write ( " _RED_("fail") " )");
284 PrintAndLogEx(SUCCESS
, "Write ( " _GREEN_("ok") " )");
288 static int CmdLFHitagSList(const char *Cmd
) {
289 return CmdTraceListAlias(Cmd
, "lf hitag hts", "hitags");
292 static command_t CommandTable
[] = {
293 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
294 {"list", CmdLFHitagSList
, AlwaysAvailable
, "List Hitag S trace history"},
296 "-----------", CmdHelp
, IfPm3Hitag
, "----------------------- " _CYAN_(
297 "General") " ------------------------"
299 {"read", CmdLFHitagSRead
, IfPm3Hitag
, "Read Hitag S memory"},
300 {"write", CmdLFHitagSWrite
, IfPm3Hitag
, "Write Hitag S page"},
301 {NULL
, NULL
, 0, NULL
}
304 static int CmdHelp(const char *Cmd
) {
305 (void) Cmd
; // Cmd is not used so far
306 CmdsHelp(CommandTable
);
310 int CmdLFHitagS(const char *Cmd
) {
311 clearCommandBuffer();
312 return CmdsParse(CommandTable
, Cmd
);
315 hitags_config_t
hitags_config_unpack(const uint8_t *config_bytes
) {
316 hitags_config_t result
= {
317 .memory_type
= (config_bytes
[0] >> 0) & 0x03,
318 .authentication
= (config_bytes
[1] >> 7) & 0x01,
319 .ttf_coding
= (config_bytes
[1] >> 6) & 0x01,
320 .ttf_data_rate
= (config_bytes
[1] >> 4) & 0x03,
321 .ttf_mode
= (config_bytes
[1] >> 2) & 0x03,
322 .lock_config
= (config_bytes
[1] >> 1) & 0x01,
323 .lock_key
= (config_bytes
[1] >> 0) & 0x01
328 void hitags_config_print(hitags_config_t config
) {
329 PrintAndLogEx(INFO
, " Memory type...... " _GREEN_("%s"),
331 "Hitag S 32", "Hitag S 256", "Hitag S 2048",
332 "Unknown Hitag S/8211"
333 }[config
.memory_type
]);
335 PrintAndLogEx(INFO
, " Authenticaion.... %s", config
.authentication
? _YELLOW_("Yes") : "No");
337 PrintAndLogEx(INFO
, " TTF coding....... %s",
338 (const char *[]) {"Manchester", "Biphase"}[config
.ttf_coding
]);
340 PrintAndLogEx(INFO
, " TTF data rate.... %s",
342 "4 kBit", "8 kBit", "2 kBit",
343 "2 kBit and Pigeon Race Standard"
344 }[config
.ttf_data_rate
]);
346 PrintAndLogEx(INFO
, " TTF mode......... %s",
348 "TTF Mode disabled (= RTF Mode)", "Page 4, Page 5",
349 "Page 4, Page 5, Page 6, Page 7", "Page 4"
352 PrintAndLogEx(INFO
, " Config locked.... %s", config
.lock_config
? _RED_("Yes") : _GREEN_("No"));
353 PrintAndLogEx(INFO
, " Key/PWD locked... %s", config
.lock_key
? _RED_("Yes") : _GREEN_("No"));