fix one too small
[RRG-proxmark3.git] / client / src / cmdlfhitaghts.c
bloba55a46255dd435fa9dcc2706c2f0e7cb6035a434
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);
40 static int CmdLFHitagSRead(const char *Cmd) {
41 CLIParserContext *ctx;
42 CLIParserInit(&ctx, "lf hitag hts read",
43 "Read Hitag S memory.\n\n"
44 " Crypto mode: \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"
53 void *argtable[] = {
54 arg_param_begin,
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"),
58 arg_param_end
60 CLIExecWithReturn(ctx, Cmd, argtable, true);
62 bool use_plain = false;
64 uint8_t nrar[8];
65 int nrar_len = 0;
67 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), nrar, sizeof(nrar), &nrar_len);
68 if (res != 0) {
69 CLIParserFree(ctx);
70 return PM3_EINVARG;
73 bool use_nrar = nrar_len > 0;
74 bool use_crypto = arg_get_lit(ctx, 2);
76 uint8_t key[6];
77 int key_len = 0;
79 res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, sizeof(key), &key_len);
80 if (res != 0) {
81 CLIParserFree(ctx);
82 return PM3_EINVARG;
85 CLIParserFree(ctx);
87 if (key_len && key_len != HITAGS_CRYPTOKEY_SIZE) {
88 PrintAndLogEx(WARNING, "Wrong KEY len expected %d, got %d", HITAGS_CRYPTOKEY_SIZE, key_len);
89 return PM3_EINVARG;
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);
94 return PM3_EINVARG;
97 if (!key_len && use_crypto) {
98 memcpy(key, "ONMIKR", 6);
99 key_len = 6;
102 // check coherence
103 uint8_t auth_methods = (use_plain + use_nrar + use_crypto);
104 if (auth_methods > 1) {
105 PrintAndLogEx(WARNING, "Specify only one authentication mode");
106 return PM3_EINVARG;
107 } else if (auth_methods == 0) {
108 use_plain = true;
111 lf_hitag_data_t packet;
112 memset(&packet, 0, sizeof(packet));
114 int pm3cmd = CMD_LF_HITAGS_READ;
116 if (use_nrar) {
117 packet.cmd = RHTSF_CHALLENGE;
118 memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
121 if (use_crypto) {
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);
133 return PM3_ETIMEOUT;
136 if (resp.status != PM3_SUCCESS) {
137 PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
138 return PM3_ESOFT;
141 // ??
142 if (use_nrar) {
143 return PM3_SUCCESS;
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);
162 return PM3_SUCCESS;
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"
169 " Crypto mode: \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"
178 void *argtable[] = {
179 arg_param_begin,
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"),
185 arg_param_end
187 CLIExecWithReturn(ctx, Cmd, argtable, false);
189 bool use_plain = false;
191 uint8_t nrar[8];
192 int nrar_len = 0;
194 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), nrar, sizeof(nrar), &nrar_len);
195 if (res != 0) {
196 CLIParserFree(ctx);
197 return PM3_EINVARG;
200 bool use_nrar = nrar_len > 0;
201 bool use_crypto = arg_get_lit(ctx, 2);
203 uint8_t key[6];
204 int key_len = 0;
206 res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, sizeof(key), &key_len);
207 if (res != 0) {
208 CLIParserFree(ctx);
209 return PM3_EINVARG;
212 int page = arg_get_int_def(ctx, 4, 0);
214 uint8_t data[4];
215 int data_len = 0;
217 res = CLIParamHexToBuf(arg_get_str(ctx, 5), data, sizeof(data), &data_len);
218 if (res != 0) {
219 CLIParserFree(ctx);
220 return PM3_EINVARG;
223 CLIParserFree(ctx);
225 if (key_len && key_len != HITAGS_CRYPTOKEY_SIZE) {
226 PrintAndLogEx(WARNING, "Wrong KEY len expected %d, got %d", HITAGS_CRYPTOKEY_SIZE, key_len);
227 return PM3_EINVARG;
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);
232 return PM3_EINVARG;
235 if (!key_len && use_crypto) {
236 memcpy(key, "ONMIKR", 6);
237 key_len = 6;
240 // check coherence
241 uint8_t auth_methods = (use_plain + use_nrar + use_crypto);
242 if (auth_methods > 1) {
243 PrintAndLogEx(WARNING, "Specify only one authentication mode");
244 return PM3_EINVARG;
245 } else if (auth_methods == 0) {
246 use_plain = true;
249 lf_hitag_data_t packet;
250 memset(&packet, 0, sizeof(packet));
252 packet.page = page;
253 memcpy(packet.data, data, sizeof(data));
255 if (use_nrar) {
256 packet.cmd = WHTSF_CHALLENGE;
257 memcpy(packet.NrAr, nrar, sizeof(packet.NrAr));
260 if (use_crypto) {
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.");
271 return PM3_ETIMEOUT;
274 if (resp.status == PM3_ETEAROFF) {
275 PrintAndLogEx(INFO, "Writing tear off triggered");
276 return PM3_SUCCESS;
279 if (resp.status != PM3_SUCCESS) {
280 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
281 return resp.status;
284 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
285 return PM3_SUCCESS;
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);
307 return PM3_SUCCESS;
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
325 return result;
328 void hitags_config_print(hitags_config_t config) {
329 PrintAndLogEx(INFO, " Memory type...... " _GREEN_("%s"),
330 (const char *[]) {
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",
341 (const char *[]) {
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",
347 (const char *[]) {
348 "TTF Mode disabled (= RTF Mode)", "Page 4, Page 5",
349 "Page 4, Page 5, Page 6, Page 7", "Page 4"
350 }[config.ttf_mode]);
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"));