fix one too small
[RRG-proxmark3.git] / client / src / cmdlfem410x.c
blob67c53972e5bbcc7416da78d10b9fc5ed01b11277
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 EM410x commands
17 //-----------------------------------------------------------------------------
19 #include "cmdlfem410x.h"
20 #include "cmdlfem4x50.h"
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include "fileutils.h"
27 #include "cmdparser.h" // command_t
28 #include "comms.h"
29 #include "commonutil.h"
30 #include "common.h"
31 #include "util_posix.h"
32 #include "protocols.h"
33 #include "ui.h"
34 #include "proxgui.h"
35 #include "graph.h"
36 #include "cmddata.h"
37 #include "cmdlf.h"
38 #include "lfdemod.h"
39 #include "generator.h"
40 #include "cliparser.h"
41 #include "cmdhw.h"
42 #include "hitag.h"
44 static uint64_t gs_em410xid = 0;
46 static int CmdHelp(const char *Cmd);
47 /* Read the ID of an EM410x tag.
48 * Format:
49 * 1111 1111 1 <-- standard non-repeatable header
50 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
51 * ....
52 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
53 * 0 <-- stop bit, end of tag
56 // Construct the graph for emulating an EM410X tag
57 static void em410x_construct_emul_graph(uint8_t *uid, uint8_t clock, uint8_t gap) {
59 // clear our graph
60 ClearGraph(true);
62 // write 16 zero bit sledge
63 for (uint8_t i = 0; i < gap; i++)
64 AppendGraph(false, clock, 0);
66 // write 9 start bits
67 for (uint8_t i = 0; i < 9; i++)
68 AppendGraph(false, clock, 1);
70 uint8_t bs[8], parity[8];
71 memset(parity, 0, sizeof(parity));
73 for (uint8_t i = 0; i < 5; i++) {
75 for (uint8_t j = 0; j < 8; j++) {
76 bs[j] = (uid[i] >> (7 - j) & 1);
78 PrintAndLogEx(DEBUG, "EM ID[%d] 0x%02x (%s)", i, uid[i], sprint_bytebits_bin(bs, 4));
80 for (uint8_t j = 0; j < 2; j++) {
81 // append each bit
82 AppendGraph(false, clock, bs[0 + (4 * j)]);
83 AppendGraph(false, clock, bs[1 + (4 * j)]);
84 AppendGraph(false, clock, bs[2 + (4 * j)]);
85 AppendGraph(false, clock, bs[3 + (4 * j)]);
87 // append parity bit
88 AppendGraph(false, clock, bs[0 + (4 * j)] ^ bs[1 + (4 * j)] ^ bs[2 + (4 * j)] ^ bs[3 + (4 * j)]);
90 // keep track of column parity
91 parity[0] ^= bs[0 + (4 * j)];
92 parity[1] ^= bs[1 + (4 * j)];
93 parity[2] ^= bs[2 + (4 * j)];
94 parity[3] ^= bs[3 + (4 * j)];
98 // parity columns
99 AppendGraph(false, clock, parity[0]);
100 AppendGraph(false, clock, parity[1]);
101 AppendGraph(false, clock, parity[2]);
102 AppendGraph(false, clock, parity[3]);
104 // stop bit
105 AppendGraph(true, clock, 0);
108 // print 64 bit EM410x ID in multiple formats
109 void printEM410x(uint32_t hi, uint64_t id, bool verbose, int type) {
111 if (!id && !hi) return;
113 if (verbose == false) {
114 if (type & 0x1) { // Short ID
115 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
117 if (type & 0x2) { // Long ID
118 PrintAndLogEx(SUCCESS, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64), hi, id);
120 if (type & 0x4) { // Short Extended ID
121 uint64_t data = (id << 20) >> 20;
122 // Convert back to Short ID
123 id = ((uint64_t)hi << 16) | (id >> 48);
124 if ((data & 0xFFFFFFFF) == 0) {
125 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64)" Electra "_GREEN_("%03" PRIu64), id, data >> 32);
126 } else {
127 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64)" on 128b frame with data "_GREEN_("%011" PRIX64), id, data);
130 return;
133 if (type & 0x2) { // Long ID
134 //output 88 bit em id
135 PrintAndLogEx(SUCCESS, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64)" ( RF/%d )", hi, id, g_DemodClock);
137 if (type & 0x4) { // Short Extended ID
138 PrintAndLogEx(SUCCESS, "EM 410x Short ID found on a 128b frame");
139 uint64_t data = (id << 20) >> 20;
140 PrintAndLogEx(SUCCESS, " Data after ID: "_GREEN_("%011" PRIX64), data);
141 if ((data & 0xFFFFFFFF) == 0) {
142 PrintAndLogEx(SUCCESS, " Possibly an Electra (RO), 0x"_GREEN_("%03" PRIX64)" = "_GREEN_("%03" PRIu64), data >> 32, data >> 32);
144 PrintAndLogEx(SUCCESS, " Short ID details:");
145 // Convert back to Short ID
146 id = ((uint64_t)hi << 16) | (id >> 48);
148 if (type & (0x4 | 0x1)) { // Short Extended or Short ID
149 //output 40 bit em id
150 uint64_t n = 1;
151 uint64_t id2lo = 0;
152 uint8_t m, i;
153 for (m = 5; m > 0; m--) {
154 for (i = 0; i < 8; i++) {
155 id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8)));
158 PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
159 PrintAndLogEx(SUCCESS, "EM410x ( RF/%d )", g_DemodClock);
160 PrintAndLogEx(INFO, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
161 PrintAndLogEx(SUCCESS, "Unique TAG ID : %010" PRIX64, id2lo);
162 PrintAndLogEx(INFO, "HoneyWell IdentKey");
163 PrintAndLogEx(SUCCESS, " DEZ 8 : %08" PRIu64, id & 0xFFFFFF);
164 PrintAndLogEx(SUCCESS, " DEZ 10 : %010" PRIu64, id & 0xFFFFFFFF);
165 PrintAndLogEx(SUCCESS, " DEZ 5.5 : %05" PRIu64 ".%05" PRIu64, (id >> 16LL) & 0xFFFF, (id & 0xFFFF));
166 PrintAndLogEx(SUCCESS, " DEZ 3.5A : %03" PRIu64 ".%05" PRIu64, (id >> 32ll), (id & 0xFFFF));
167 PrintAndLogEx(SUCCESS, " DEZ 3.5B : %03" PRIu64 ".%05" PRIu64, (id & 0xFF000000) >> 24, (id & 0xFFFF));
168 PrintAndLogEx(SUCCESS, " DEZ 3.5C : %03" PRIu64 ".%05" PRIu64, (id & 0xFF0000) >> 16, (id & 0xFFFF));
169 PrintAndLogEx(SUCCESS, " DEZ 14/IK2 : %014" PRIu64, id);
170 PrintAndLogEx(SUCCESS, " DEZ 15/IK3 : %015" PRIu64, id2lo);
171 PrintAndLogEx(SUCCESS, " DEZ 20/ZK : %02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64 "%02" PRIu64,
172 (id2lo & 0xf000000000) >> 36,
173 (id2lo & 0x0f00000000) >> 32,
174 (id2lo & 0x00f0000000) >> 28,
175 (id2lo & 0x000f000000) >> 24,
176 (id2lo & 0x0000f00000) >> 20,
177 (id2lo & 0x00000f0000) >> 16,
178 (id2lo & 0x000000f000) >> 12,
179 (id2lo & 0x0000000f00) >> 8,
180 (id2lo & 0x00000000f0) >> 4,
181 (id2lo & 0x000000000f)
183 PrintAndLogEx(INFO, "");
185 uint64_t paxton = (((id >> 32) << 24) | (id & 0xffffff)) + 0x143e00;
186 PrintAndLogEx(SUCCESS, "Other : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id & 0xFFFF), ((id >> 16LL) & 0xFF), (id & 0xFFFFFF));
187 PrintAndLogEx(SUCCESS, "Pattern Paxton : %" PRIu64 " [0x%" PRIX64 "]", paxton, paxton);
189 uint32_t p1id = (id & 0xFFFFFF);
190 uint8_t arr[32] = {0x00};
191 int j = 23;
192 for (int k = 0 ; k < 24; ++k, --j) {
193 arr[k] = (p1id >> k) & 1;
196 uint32_t p1 = 0;
198 p1 |= arr[23] << 21;
199 p1 |= arr[22] << 23;
200 p1 |= arr[21] << 20;
201 p1 |= arr[20] << 22;
203 p1 |= arr[19] << 18;
204 p1 |= arr[18] << 16;
205 p1 |= arr[17] << 19;
206 p1 |= arr[16] << 17;
208 p1 |= arr[15] << 13;
209 p1 |= arr[14] << 15;
210 p1 |= arr[13] << 12;
211 p1 |= arr[12] << 14;
213 p1 |= arr[11] << 6;
214 p1 |= arr[10] << 2;
215 p1 |= arr[9] << 7;
216 p1 |= arr[8] << 1;
218 p1 |= arr[7] << 0;
219 p1 |= arr[6] << 8;
220 p1 |= arr[5] << 11;
221 p1 |= arr[4] << 3;
223 p1 |= arr[3] << 10;
224 p1 |= arr[2] << 4;
225 p1 |= arr[1] << 5;
226 p1 |= arr[0] << 9;
227 PrintAndLogEx(SUCCESS, "Pattern 1 : %d [0x%X]", p1, p1);
229 uint16_t sebury1 = id & 0xFFFF;
230 uint8_t sebury2 = (id >> 16) & 0x7F;
231 uint32_t sebury3 = id & 0x7FFFFF;
232 PrintAndLogEx(SUCCESS, "Pattern Sebury : %d %d %d [0x%X 0x%X 0x%X]", sebury1, sebury2, sebury3, sebury1, sebury2, sebury3);
233 PrintAndLogEx(SUCCESS, "VD / ID : %03" PRIu64 " / %010" PRIu64, (id >> 32LL) & 0xFFFF, (id & 0xFFFFFFFF));
234 PrintAndLogEx(SUCCESS, "Pattern ELECTRA : %" PRIu64 " %" PRIu64, (id >> 24) & 0xFFFF, id & 0xFFFFFF);
236 PrintAndLogEx(INFO, "------------------------------------------------");
240 // takes 1s and 0s and searches for EM410x format - output EM ID
241 static int ask_em410x_binary_decode(bool verbose, uint32_t *hi, uint64_t *lo, uint8_t *bits, size_t *size, size_t *idx) {
243 int ans = Em410xDecode(bits, size, idx, hi, lo);
244 if (ans < 0) {
245 if (ans == -2)
246 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x not enough samples after demod");
247 else if (ans == -4)
248 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x preamble not found");
249 else if (ans == -5)
250 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x Size not correct: %zu", size);
251 else if (ans == -6)
252 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x parity failed");
254 return PM3_ESOFT;
257 if (!lo && !hi) {
258 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x decoded to all zeros");
259 return PM3_ESOFT;
262 PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %zu, Len: %zu, Printing DemodBuffer:", *idx, *size);
263 if (g_debugMode) {
264 printDemodBuff(0, false, false, true);
267 printEM410x(*hi, *lo, verbose, ans);
268 gs_em410xid = *lo;
269 return PM3_SUCCESS;
272 /* Read the ID of an EM410x tag.
273 * Format:
274 * 1111 1111 1 <-- standard non-repeatable header
275 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
276 * ....
277 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
278 * 0 <-- stop bit, end of tag
280 int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) {
281 size_t idx = 0;
282 uint8_t bits[512] = {0};
283 size_t size = sizeof(bits);
284 if (getDemodBuff(bits, &size) == false) {
285 PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x problem during copy from ASK demod");
286 return PM3_ESOFT;
289 int ret = ask_em410x_binary_decode(verbose, hi, lo, bits, &size, &idx);
291 if (ret == PM3_SUCCESS) {
292 // set g_GraphBuffer for clone or sim command
293 setDemodBuff(g_DemodBuffer, (size == 40) ? 64 : 128, idx + 1);
294 setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 1)*g_DemodClock));
296 return ret;
299 int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose) {
300 bool st = true;
302 // em410x simulation etc uses 0/1 as signal data. This must be converted in order to demod it back again
303 if (isGraphBitstream()) {
304 convertGraphFromBitstream();
306 if (ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, false, false, 1, &st) != PM3_SUCCESS) {
307 return PM3_ESOFT;
309 return AskEm410xDecode(verbose, hi, lo);
312 // this read loops on device side.
313 // uses the demod in lfops.c
314 static int CmdEM410xWatch(const char *Cmd) {
315 CLIParserContext *ctx;
316 CLIParserInit(&ctx, "lf em 410x watch",
317 "Enables Electro Marine (EM) compatible reader mode printing details of scanned tags.\n"
318 "Run until the button is pressed or another USB command is issued.",
319 "lf em 410x watch"
322 void *argtable[] = {
323 arg_param_begin,
324 arg_param_end
326 CLIExecWithReturn(ctx, Cmd, argtable, true);
327 CLIParserFree(ctx);
329 PrintAndLogEx(SUCCESS, "Watching for EM410x cards - place tag on Proxmark3 antenna");
330 clearCommandBuffer();
331 SendCommandNG(CMD_LF_EM410X_WATCH, NULL, 0);
332 return lfsim_wait_check(CMD_LF_EM410X_WATCH);
335 // by marshmellow
336 //takes 3 arguments - clock, invert and maxErr as integers
337 //attempts to demodulate ask while decoding manchester
338 //prints binary found and saves in graphbuffer for further commands
339 int demodEM410x(bool verbose) {
340 (void) verbose; // unused so far
341 uint32_t hi = 0;
342 uint64_t lo = 0;
343 return AskEm410xDemod(0, 0, 100, 0, false, &hi, &lo, true);
346 static int CmdEM410xDemod(const char *Cmd) {
347 CLIParserContext *ctx;
348 CLIParserInit(&ctx, "lf em 410x demod",
349 "Try to find EM 410x preamble, if found decode / descramble data",
350 "lf em 410x demod -> demod an EM410x Tag ID from GraphBuffer\n"
351 "lf em 410x demod --clk 32 -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32\n"
352 "lf em 410x demod --clk 32 -i -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/32 and inverting data\n"
353 "lf em 410x demod -i -> demod an EM410x Tag ID from GraphBuffer while inverting data\n"
354 "lf em 410x demod --clk 64 -i --err 0 -> demod an EM410x Tag ID from GraphBuffer using a clock of RF/64 and inverting data and allowing 0 demod errors"
357 void *argtable[] = {
358 arg_param_begin,
359 arg_u64_0(NULL, "clk", "<dec>", "clock (default autodetect)"),
360 arg_u64_0(NULL, "err", "<dec>", "maximum allowed errors (default 100)"),
361 arg_u64_0(NULL, "len", "<dec>", "maximum length"),
362 arg_lit0("i", "invert", "invert output"),
363 arg_lit0("a", "amp", "amplify signal"),
364 arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
365 arg_param_end
367 CLIExecWithReturn(ctx, Cmd, argtable, true);
369 int clk = arg_get_u32_def(ctx, 1, 0);
370 int max_err = arg_get_u32_def(ctx, 2, 100);
371 size_t max_len = arg_get_u32_def(ctx, 3, 0);
372 bool invert = arg_get_lit(ctx, 4);
373 bool amplify = arg_get_lit(ctx, 5);
374 int bin_len = 512;
375 uint8_t bin[512] = {0};
376 CLIGetStrWithReturn(ctx, 6, bin, &bin_len);
377 CLIParserFree(ctx);
379 uint32_t hi = 0;
380 uint64_t lo = 0;
382 if (bin_len) {
383 // 111111111011110010010100001110010101001101110001100100000010010011111100001111
384 size_t demodlen = bin_len;
385 size_t start_idx = 0;
386 uint8_t arr[258];
387 binstr_2_binarray(arr, (char *)bin, bin_len);
388 return ask_em410x_binary_decode(true, &hi, &lo, arr, &demodlen, &start_idx);
391 if (AskEm410xDemod(clk, invert, max_err, max_len, amplify, &hi, &lo, true) != PM3_SUCCESS) {
392 return PM3_ESOFT;
395 return PM3_SUCCESS;
398 // this read is the "normal" read, which download lf signal and tries to demod here.
399 static int CmdEM410xReader(const char *Cmd) {
400 CLIParserContext *ctx;
401 CLIParserInit(&ctx, "lf em 410x reader",
402 "read EM 410x tag",
403 "lf em 410x reader\n"
404 "lf em 410x reader -@ -> continuous reader mode\n"
405 "lf em 410x reader --clk 32 -> using a clock of RF/32\n"
406 "lf em 410x reader --clk 32 -i -> using a clock of RF/32 and inverting data\n"
407 "lf em 410x reader -i -> inverting data\n"
408 "lf em 410x reader --clk 64 -i --err 0 -> using a clock of RF/64 and inverting data and allowing 0 demod errors"
411 void *argtable[] = {
412 arg_param_begin,
413 arg_u64_0(NULL, "clk", "<dec>", "clock (default autodetect)"),
414 arg_u64_0(NULL, "err", "<dec>", "maximum allowed errors (default 100)"),
415 arg_u64_0(NULL, "len", "<dec>", "maximum length"),
416 arg_lit0("i", "invert", "invert output"),
417 arg_lit0("a", "amp", "amplify signal"),
418 arg_lit0("b", NULL, "break on first found"),
419 arg_lit0("@", NULL, "continuous reader mode"),
420 arg_lit0("v", "verbose", "verbose output"),
421 arg_param_end
423 CLIExecWithReturn(ctx, Cmd, argtable, true);
425 int clk = arg_get_u32_def(ctx, 1, 0);
426 int max_err = arg_get_u32_def(ctx, 2, 100);
427 size_t max_len = arg_get_u32_def(ctx, 3, 0);
428 bool invert = arg_get_lit(ctx, 4);
429 bool amplify = arg_get_lit(ctx, 5);
430 bool break_first = arg_get_lit(ctx, 6);
431 bool cm = arg_get_lit(ctx, 7);
432 bool verbose = arg_get_lit(ctx, 8);
433 CLIParserFree(ctx);
435 if (cm) {
436 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
439 do {
440 uint32_t hi = 0;
441 uint64_t lo = 0;
442 lf_read(false, 12288);
443 AskEm410xDemod(clk, invert, max_err, max_len, amplify, &hi, &lo, verbose);
445 if (break_first && gs_em410xid != 0) {
446 break;
448 } while (cm && !kbd_enter_pressed());
450 return PM3_SUCCESS;
453 // emulate an EM410X tag
454 static int CmdEM410xSim(const char *Cmd) {
456 CLIParserContext *ctx;
457 CLIParserInit(&ctx, "lf em 410x sim",
458 "Enables simulation of EM 410x card.\n"
459 "Simulation runs until the button is pressed or another USB command is issued.",
460 "lf em 410x sim --id 0F0368568B\n"
461 "lf em 410x sim --id 0F0368568B --clk 32\n"
462 "lf em 410x sim --id 0F0368568B --gap 0"
465 void *argtable[] = {
466 arg_param_begin,
467 arg_u64_0(NULL, "clk", "<dec>", "<32|64> clock (default 64)"),
468 arg_str1(NULL, "id", "<hex>", "EM Tag ID number (5 hex bytes)"),
469 arg_u64_0(NULL, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
470 arg_param_end
472 CLIExecWithReturn(ctx, Cmd, argtable, false);
474 // clock is 64 in EM410x tags
475 int clk = arg_get_u32_def(ctx, 1, 64);
476 int uid_len = 0;
477 int gap = arg_get_u32_def(ctx, 3, 20);
478 uint8_t uid[5] = {0};
479 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
480 CLIParserFree(ctx);
482 if (uid_len != 5) {
483 PrintAndLogEx(FAILED, "EM ID must include 5 hex bytes (10 hex symbols), got " _YELLOW_("%u"), uid_len);
484 return PM3_EINVARG;
487 PrintAndLogEx(SUCCESS, "Starting simulating EM Tag ID "_YELLOW_("%s")" clock: "_YELLOW_("%d"), sprint_hex_inrow(uid, sizeof(uid)), clk);
488 em410x_construct_emul_graph(uid, clk, gap);
489 CmdLFSim("");
490 return PM3_SUCCESS;
493 static int CmdEM410xBrute(const char *Cmd) {
494 CLIParserContext *ctx;
495 CLIParserInit(&ctx, "lf em 410x brute",
496 "bruteforcing by emulating EM 410x tag",
497 "lf em 410x brute -f ids.txt\n"
498 "lf em 410x brute -f ids.txt --clk 32\n"
499 "lf em 410x brute -f ids.txt --delay 3000\n"
500 "lf em 410x brute -f ids.txt --delay 3000 --clk 32\n"
503 void *argtable[] = {
504 arg_param_begin,
505 arg_u64_0(NULL, "clk", "<dec>", "<32|64> clock (default 64)"),
506 arg_u64_0(NULL, "delay", "<dec>", "pause delay in milliseconds between UIDs simulation (default 1000ms)"),
507 arg_str1("f", "file", "<hex>", "file with EM Tag IDs, one id per line"),
508 arg_u64_0(NULL, "gap", "<dec>", "gap (0's) between ID repeats (default 20)"),
509 arg_param_end
511 CLIExecWithReturn(ctx, Cmd, argtable, false);
513 // clock default 64 in EM410x
514 uint32_t clk = arg_get_u32_def(ctx, 1, 64);
515 int gap = arg_get_u32_def(ctx, 4, 20);
516 // default pause time: 1 second
517 uint32_t delay = arg_get_u32_def(ctx, 2, 1000);
519 int fnlen = 0;
520 char filename[FILE_PATH_SIZE] = {0};
521 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
522 CLIParserFree(ctx);
524 if (fnlen == 0) {
525 PrintAndLogEx(ERR, "Error: Please specify a filename");
526 return PM3_EINVARG;
529 uint32_t uidcnt = 0;
530 uint8_t stUidBlock = 20;
531 uint8_t *p = NULL;
532 uint8_t uid[5] = {0x00};
534 // open file
535 FILE *f = NULL;
536 if ((f = fopen(filename, "r")) == NULL) {
537 PrintAndLogEx(ERR, "Error: Could not open EM Tag IDs file ["_YELLOW_("%s")"]", filename);
538 return PM3_EFILE;
541 // allocate mem for file contents
542 uint8_t *uidblock = calloc(stUidBlock, 5);
543 if (uidblock == NULL) {
544 fclose(f);
545 PrintAndLogEx(ERR, "Error: can't allocate memory");
546 return PM3_EMALLOC;
549 // read file into memory
550 char buf[11];
552 while (fgets(buf, sizeof(buf), f)) {
553 if (strlen(buf) < 10 || buf[9] == '\n') continue;
554 while (fgetc(f) != '\n' && !feof(f)); //goto next line
556 //The line start with # is comment, skip
557 if (buf[0] == '#') continue;
559 int uidlen = 0;
560 if (param_gethex_ex(buf, 0, uid, &uidlen) && (uidlen != 10)) {
561 PrintAndLogEx(FAILED, "EM Tag IDs must include 5 hex bytes (10 hex symbols), got ( " _RED_("%d") " )", uidlen);
562 free(uidblock);
563 fclose(f);
564 return PM3_ESOFT;
567 buf[10] = 0;
569 if (stUidBlock - uidcnt < 2) {
570 p = realloc(uidblock, 5 * (stUidBlock += 10));
571 if (!p) {
572 PrintAndLogEx(WARNING, "Cannot allocate memory for EM Tag IDs");
573 free(uidblock);
574 fclose(f);
575 return PM3_ESOFT;
577 uidblock = p;
579 memset(uidblock + 5 * uidcnt, 0, 5);
580 num_to_bytes(strtoll(buf, NULL, 16), 5, uidblock + 5 * uidcnt);
581 uidcnt++;
582 memset(buf, 0, sizeof(buf));
584 fclose(f);
586 if (uidcnt == 0) {
587 PrintAndLogEx(FAILED, "No EM Tag IDs found in file");
588 free(uidblock);
589 return PM3_ESOFT;
592 PrintAndLogEx(SUCCESS, "Loaded "_YELLOW_("%d")" EM Tag IDs from "_YELLOW_("%s")", pause delay:"_YELLOW_("%d")" ms", uidcnt, filename, delay);
594 // loop
595 uint8_t testuid[5];
596 for (uint32_t c = 0; c < uidcnt; ++c) {
597 if (kbd_enter_pressed()) {
598 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
599 PrintAndLogEx(WARNING, "aborted via keyboard!\n");
600 free(uidblock);
601 return PM3_EOPABORTED;
604 memcpy(testuid, uidblock + 5 * c, 5);
605 PrintAndLogEx(INFO, "Bruteforce %d / %u: simulating EM Tag ID " _YELLOW_("%s")
606 , c + 1
607 , uidcnt
608 , sprint_hex_inrow(testuid, sizeof(testuid))
611 em410x_construct_emul_graph(testuid, clk, gap);
613 lfsim_upload_gb();
615 struct p {
616 uint16_t len;
617 uint16_t gap;
618 } PACKED payload;
619 payload.len = g_GraphTraceLen;
620 payload.gap = 0;
622 clearCommandBuffer();
623 SendCommandNG(CMD_LF_SIMULATE, (uint8_t *)&payload, sizeof(payload));
625 PacketResponseNG resp;
626 if (WaitForResponseTimeout(CMD_LF_SIMULATE, &resp, delay)) {
627 if (resp.status == PM3_EOPABORTED) {
628 PrintAndLogEx(INFO, "Button pressed, user aborted");
629 break;
633 free(uidblock);
634 return PM3_SUCCESS;
637 //currently only supports manchester modulations
638 static int CmdEM410xSpoof(const char *Cmd) {
639 CLIParserContext *ctx;
640 CLIParserInit(&ctx, "lf em 410x spoof",
641 "Watch 'nd Spoof, activates reader\n"
642 "Waits until a EM 410x tag gets presented then Proxmark3 starts simulating the found EM Tag ID",
643 "lf em 410x spoof"
646 void *argtable[] = {
647 arg_param_begin,
648 arg_param_end
650 CLIExecWithReturn(ctx, Cmd, argtable, true);
651 CLIParserFree(ctx);
653 // loops if the captured ID was in XL-format.
654 gs_em410xid = 0;
655 CmdEM410xReader("-b@");
656 PrintAndLogEx(SUCCESS, "Replaying captured EM Tag ID "_YELLOW_("%010" PRIx64), gs_em410xid);
657 CmdLFSim("");
658 return PM3_SUCCESS;
661 static size_t concatbits(uint8_t *dst, size_t dstskip, const uint8_t *src, size_t srcstart, size_t srclen) {
662 // erase dstbuf bits that will be overriden
663 dst[dstskip / 8] &= 0xFF - ((1 << (7 - (dstskip % 8) + 1)) - 1);
664 for (size_t i = (dstskip / 8) + 1; i <= (dstskip + srclen) / 8; i++) {
665 dst[i] = 0;
668 for (size_t i = 0; i < srclen; i++) {
669 // equiv of dstbufbits[dstbufskip + i] = srcbufbits[srcbufstart + i]
670 dst[(dstskip + i) / 8] |= ((src[(srcstart + i) / 8] >> (7 - ((srcstart + i) % 8))) & 1) << (7 - ((dstskip + i) % 8));
673 return dstskip + srclen;
676 static int CmdEM410xClone(const char *Cmd) {
677 CLIParserContext *ctx;
678 CLIParserInit(&ctx, "lf em 410x clone",
679 "clone a EM410x ID to a T55x7, Q5/T5555, EM4305/4469 or Hitag S/8211 tag.",
680 "lf em 410x clone --id 0F0368568B -> encode for T55x7 tag\n"
681 "lf em 410x clone --id 0F0368568B --q5 -> encode for Q5/T5555 tag\n"
682 "lf em 410x clone --id 0F0368568B --em -> encode for EM4305/4469\n"
683 "lf em 410x clone --id 0F0368568B --hs -> encode for Hitag S/8211"
686 void *argtable[] = {
687 arg_param_begin,
688 arg_u64_0(NULL, "clk", "<dec>", "<16|32|40|64> clock (default 64)"),
689 arg_str1(NULL, "id", "<hex>", "EM Tag ID number (5 hex bytes)"),
690 arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
691 arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
692 arg_lit0(NULL, "hs", "optional - specify writing to Hitag S/8211 tag"),
693 arg_lit0(NULL, "electra", "optional - add Electra blocks to tag"),
694 arg_param_end
696 CLIExecWithReturn(ctx, Cmd, argtable, false);
698 // clock default 64 in EM410x
699 uint32_t clk = arg_get_u32_def(ctx, 1, 64);
700 int uid_len = 0;
701 uint8_t uid[5] = {0};
702 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
703 bool q5 = arg_get_lit(ctx, 3);
704 bool em = arg_get_lit(ctx, 4);
705 bool hs = arg_get_lit(ctx, 5);
706 bool add_electra = arg_get_lit(ctx, 6);
707 CLIParserFree(ctx);
709 if (q5 + em + hs > 1) {
710 PrintAndLogEx(FAILED, "Only specify one tag Type");
711 return PM3_EINVARG;
714 if (hs) {
715 if (IfPm3Hitag() == false) {
716 PrintAndLogEx(FAILED, "Device not compiled to support Hitag");
717 return PM3_EINVARG;
719 if (clk == 40) {
720 PrintAndLogEx(FAILED, "supported clock rates for Hitag are " _YELLOW_("16, 32, 64"));
721 return PM3_EINVARG;
725 // Allowed clock rates: 16, 32, 40 and 64
726 if ((clk != 16) && (clk != 32) && (clk != 64) && (clk != 40)) {
727 PrintAndLogEx(FAILED, "supported clock rates are " _YELLOW_("16, 32, 40, 64") " got " _RED_("%d") "\n", clk);
728 return PM3_EINVARG;
731 uint64_t id = bytes_to_num(uid, uid_len);
732 PrintAndLogEx(SUCCESS, "Preparing to clone EM4102 to " _YELLOW_("%s") " tag with EM Tag ID " _GREEN_("%010" PRIX64) " (RF/%d)",
733 q5 ? "Q5/T5555" : (em ? "EM4305/4469" : (hs ? "Hitag S/8211" : "T55x7")), id, clk);
735 uint8_t data[HITAG_BLOCK_SIZE * 2] = {0xFF, 0x80}; // EM410X_HEADER 9 bits of one
736 uint32_t databits = 9;
737 uint8_t c_parity = 0;
739 for (int i = 36; i >= 0; i -= 4) {
740 uint8_t r_parity = 0;
741 uint8_t nibble = id >> i & 0xF;
743 databits = concatbits(data, databits, &nibble, 4, 4);
744 for (size_t j = 0; j < 4; j++) {
745 r_parity ^= nibble >> j & 1;
747 databits = concatbits(data, databits, &r_parity, 7, 1);
748 c_parity ^= nibble;
750 data[7] |= c_parity << 1;
752 PrintAndLogEx(INFO, "Encoded to %s", sprint_hex(data, sizeof(data)));
754 clearCommandBuffer();
755 PacketResponseNG resp;
757 if (hs) {
758 lf_hitag_data_t packet;
759 memset(&packet, 0, sizeof(packet));
761 for (size_t steps = 0; steps < 3; steps++) {
762 switch (steps) {
763 case 0:
764 packet.data[0] = 0xCA; //compatiable for 82xx, no impact on Hitag S
765 // clk -> TTFDR1 TTFDR0
766 // 32 -> 0x00 4 kBit/s
767 // 16 -> 0x10 8 kBit/s
768 // 64 -> 0x20 2 kBit/s
769 packet.data[1] = 0x04;
770 switch (clk) {
771 case 32:
772 break;
773 case 16:
774 packet.data[1] |= 0x10;
775 break;
776 case 64:
777 packet.data[1] |= 0x20;
778 break;
780 packet.data[2] = 0;
781 packet.data[3] = 0; //TODO: keep PWDH0?
782 packet.page = 1;
783 break;
784 case 1:
785 memcpy(packet.data, &data[HITAG_BLOCK_SIZE * 0], HITAG_BLOCK_SIZE);
786 packet.page = 4;
787 break;
788 case 2:
789 memcpy(packet.data, &data[HITAG_BLOCK_SIZE * 1], HITAG_BLOCK_SIZE);
790 packet.page = 5;
791 break;
794 packet.cmd = WHTSF_PLAIN;
795 SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *)&packet, sizeof(packet));
796 if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 4000) == false) {
797 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
798 return PM3_ETIMEOUT;
800 if (resp.status != PM3_SUCCESS) {
801 PrintAndLogEx(WARNING, "Something went wrong");
802 return resp.status;
805 } else {
806 struct {
807 bool Q5;
808 bool EM;
809 bool add_electra;
810 uint8_t clock;
811 uint32_t high;
812 uint32_t low;
813 } PACKED payload;
815 payload.Q5 = q5;
816 payload.EM = em;
817 payload.add_electra = add_electra;
818 payload.clock = clk;
819 payload.high = (uint32_t)(id >> 32);
820 payload.low = (uint32_t)id;
822 SendCommandNG(CMD_LF_EM410X_CLONE, (uint8_t *)&payload, sizeof(payload));
823 WaitForResponse(CMD_LF_EM410X_CLONE, &resp);
826 switch (resp.status) {
827 case PM3_SUCCESS: {
828 PrintAndLogEx(SUCCESS, "Done");
829 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 410x reader`") " to verify");
830 break;
832 default: {
833 PrintAndLogEx(WARNING, "Something went wrong");
834 break;
837 return resp.status;
840 static command_t CommandTable[] = {
841 {"help", CmdHelp, AlwaysAvailable, "This help"},
842 //{"demod", CmdEMdemodASK, IfPm3Lf, "Extract ID from EM410x tag on antenna)"},
843 {"demod", CmdEM410xDemod, AlwaysAvailable, "demodulate a EM410x tag from the GraphBuffer"},
844 {"reader", CmdEM410xReader, IfPm3Lf, "attempt to read and extract tag data"},
845 {"sim", CmdEM410xSim, IfPm3Lf, "simulate EM410x tag"},
846 {"brute", CmdEM410xBrute, IfPm3Lf, "reader bruteforce attack by simulating EM410x tags"},
847 {"watch", CmdEM410xWatch, IfPm3Lf, "watches for EM410x 125/134 kHz tags"},
848 {"spoof", CmdEM410xSpoof, IfPm3Lf, "watches for EM410x 125/134 kHz tags, and replays them" },
849 {"clone", CmdEM410xClone, IfPm3Lf, "clone EM410x Tag ID to T55x7, Q5/T5555 or EM4305/4469"},
850 {NULL, NULL, NULL, NULL}
853 static int CmdHelp(const char *Cmd) {
854 (void)Cmd; // Cmd is not used so far
855 CmdsHelp(CommandTable);
856 return PM3_SUCCESS;
859 int CmdLFEM410X(const char *Cmd) {
860 clearCommandBuffer();
861 return CmdsParse(CommandTable, Cmd);