textual
[RRG-proxmark3.git] / client / src / cmdlfio.c
blobb32fee7f1a0fba52877881500273a394dde5d4ca
1 //-----------------------------------------------------------------------------
2 // marshmellow
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Low frequency Kantech ioProx commands
9 // FSK2a, rf/64, 64 bits (complete)
10 //-----------------------------------------------------------------------------
12 #include "cmdlfio.h"
13 #include <stdio.h> // sscanf
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include "commonutil.h" // ARRAYLEN
18 #include "cmdparser.h" // command_t
19 #include "comms.h"
20 #include "graph.h"
21 #include "cmdlf.h"
22 #include "ui.h" // PrintAndLog
23 #include "lfdemod.h" // parityTest, bitbytes_to_byte
24 #include "protocols.h" // for T55xx config register definitions
25 #include "cmddata.h"
26 #include "cmdlft55xx.h" // verifywrite
27 #include "cliparser.h"
28 #include "cmdlfem4x05.h" // EM defines
30 static int CmdHelp(const char *Cmd);
32 // this read loops on device side.
33 // uses the demod in lfops.c
34 static int CmdIOProxWatch(const char *Cmd) {
35 CLIParserContext *ctx;
36 CLIParserInit(&ctx, "lf io watch",
37 "Enables ioProx compatible reader mode printing details.\n"
38 "By default, values are printed and logged until the button is pressed or another USB command is issued.",
39 "lf io watch"
42 void *argtable[] = {
43 arg_param_begin,
44 arg_param_end
46 CLIExecWithReturn(ctx, Cmd, argtable, true);
47 CLIParserFree(ctx);
49 PrintAndLogEx(SUCCESS, "Watching for IO Prox cards - place tag on antenna");
50 PrintAndLogEx(INFO, "Press pm3-button to stop reading cards");
51 clearCommandBuffer();
52 SendCommandNG(CMD_LF_IO_WATCH, NULL, 0);
53 return lfsim_wait_check(CMD_LF_IO_WATCH);
56 //IO-Prox demod - FSK RF/64 with preamble of 000000001
57 //print ioProx ID and some format details
58 int demodIOProx(bool verbose) {
59 (void) verbose; // unused so far
60 int idx = 0, retval = PM3_SUCCESS;
61 uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
62 size_t size = getFromGraphBuf(bits);
63 if (size < 65) {
64 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer");
65 return PM3_ESOFT;
67 //get binary from fsk wave
68 int waveIdx = 0;
69 idx = detectIOProx(bits, &size, &waveIdx);
70 if (idx < 0) {
71 if (g_debugMode) {
72 if (idx == -1) {
73 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples");
74 } else if (idx == -2) {
75 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox just noise detected");
76 } else if (idx == -3) {
77 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox error during fskdemod");
78 } else if (idx == -4) {
79 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox preamble not found");
80 } else if (idx == -5) {
81 PrintAndLogEx(DEBUG, "DEBUG: Error - IO size not correct, size %zu", size);
82 } else if (idx == -6) {
83 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox separator bits not found");
84 } else {
85 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox error demoding fsk %d", idx);
88 return PM3_ESOFT;
90 setDemodBuff(bits, size, idx);
91 setClockGrid(64, waveIdx + (idx * 64));
93 if (idx == 0) {
94 if (g_debugMode) {
95 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox data not found - FSK Bits: %zu", size);
96 if (size > 92) PrintAndLogEx(DEBUG, "%s", sprint_bin_break(bits, 92, 16));
98 return PM3_ESOFT;
101 //Index map
102 //0 10 20 30 40 50 60
103 //| | | | | | |
104 //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
105 //-----------------------------------------------------------------------------
106 //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
108 //XSF(version)facility:codeone+codetwo (raw)
110 PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d", bits[idx], bits[idx + 1], bits[idx + 2], bits[idx + 3], bits[idx + 4], bits[idx + 5], bits[idx + 6], bits[idx + 7], bits[idx + 8]);
111 PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d", bits[idx + 9], bits[idx + 10], bits[idx + 11], bits[idx + 12], bits[idx + 13], bits[idx + 14], bits[idx + 15], bits[idx + 16], bits[idx + 17]);
112 PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d facility", bits[idx + 18], bits[idx + 19], bits[idx + 20], bits[idx + 21], bits[idx + 22], bits[idx + 23], bits[idx + 24], bits[idx + 25], bits[idx + 26]);
113 PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d version", bits[idx + 27], bits[idx + 28], bits[idx + 29], bits[idx + 30], bits[idx + 31], bits[idx + 32], bits[idx + 33], bits[idx + 34], bits[idx + 35]);
114 PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d code1", bits[idx + 36], bits[idx + 37], bits[idx + 38], bits[idx + 39], bits[idx + 40], bits[idx + 41], bits[idx + 42], bits[idx + 43], bits[idx + 44]);
115 PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d code2", bits[idx + 45], bits[idx + 46], bits[idx + 47], bits[idx + 48], bits[idx + 49], bits[idx + 50], bits[idx + 51], bits[idx + 52], bits[idx + 53]);
116 PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d%d checksum", bits[idx + 54], bits[idx + 55], bits[idx + 56], bits[idx + 57], bits[idx + 58], bits[idx + 59], bits[idx + 60], bits[idx + 61], bits[idx + 62], bits[idx + 63]);
118 uint32_t code = bytebits_to_byte(bits + idx, 32);
119 uint32_t code2 = bytebits_to_byte(bits + idx + 32, 32);
120 uint8_t version = bytebits_to_byte(bits + idx + 27, 8); //14,4
121 uint8_t facilitycode = bytebits_to_byte(bits + idx + 18, 8) ;
122 uint16_t number = (bytebits_to_byte(bits + idx + 36, 8) << 8) | (bytebits_to_byte(bits + idx + 45, 8)); //36,9
123 uint8_t crc = bytebits_to_byte(bits + idx + 54, 8);
124 uint8_t calccrc = 0;
126 for (uint8_t i = 1; i < 6; ++i) {
127 calccrc += bytebits_to_byte(bits + idx + 9 * i, 8);
129 calccrc &= 0xff;
130 calccrc = 0xff - calccrc;
132 char crc_str[36] = {0};
134 if (crc == calccrc) {
135 snprintf(crc_str, sizeof(crc_str), "(" _GREEN_("ok") ")");
136 } else {
137 snprintf(crc_str, sizeof(crc_str), "(" _RED_("fail") ") 0x%02X != 0x%02X", crc, calccrc);
138 retval = PM3_ESOFT;
141 PrintAndLogEx(SUCCESS, "IO Prox - " _GREEN_("XSF(%02d)%02x:%05d") ", Raw: %08x%08x %s", version, facilitycode, number, code, code2, crc_str);
143 if (g_debugMode) {
144 if (crc != calccrc)
145 PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox crc failed");
147 PrintAndLogEx(DEBUG, "DEBUG: IO prox idx: %d, Len: %zu, Printing demod buffer:", idx, size);
148 printDemodBuff(0, false, false, true);
149 printDemodBuff(0, false, false, false);
151 return retval;
154 static int CmdIOProxDemod(const char *Cmd) {
155 CLIParserContext *ctx;
156 CLIParserInit(&ctx, "lf io demod",
157 "Try to find ioProx preamble, if found decode / descramble data",
158 "lf io demod"
161 void *argtable[] = {
162 arg_param_begin,
163 arg_param_end
165 CLIExecWithReturn(ctx, Cmd, argtable, true);
166 CLIParserFree(ctx);
167 return demodIOProx(true);
169 // this read is the "normal" read, which download lf signal and tries to demod here.
170 static int CmdIOProxReader(const char *Cmd) {
171 CLIParserContext *ctx;
172 CLIParserInit(&ctx, "lf io reader",
173 "read a ioProx tag",
174 "lf io reader -@ -> continuous reader mode"
177 void *argtable[] = {
178 arg_param_begin,
179 arg_lit0("@", NULL, "optional - continuous reader mode"),
180 arg_param_end
182 CLIExecWithReturn(ctx, Cmd, argtable, true);
183 bool cm = arg_get_lit(ctx, 1);
184 CLIParserFree(ctx);
186 do {
187 lf_read(false, 12000);
188 demodIOProx(!cm);
189 } while (cm && !kbd_enter_pressed());
191 return PM3_SUCCESS;
194 static int CmdIOProxSim(const char *Cmd) {
196 CLIParserContext *ctx;
197 CLIParserInit(&ctx, "lf io sim",
198 "Enables simulation of ioProx card with specified facility-code and card number.\n"
199 "Simulation runs until the button is pressed or another USB command is issued.",
200 "lf io sim --vn 1 --fc 101 --cn 1337"
203 void *argtable[] = {
204 arg_param_begin,
205 arg_u64_1(NULL, "vn", "<dec>", "8bit version"),
206 arg_u64_1(NULL, "fc", "<dec>", "8bit facility code"),
207 arg_u64_1(NULL, "cn", "<dec>", "16bit card number"),
208 arg_param_end
210 CLIExecWithReturn(ctx, Cmd, argtable, false);
212 uint8_t version = arg_get_u32_def(ctx, 1, 0);
213 uint8_t fc = arg_get_u32_def(ctx, 2, 0);
214 uint16_t cn = arg_get_u32_def(ctx, 3, 0);
216 CLIParserFree(ctx);
218 if ((cn & 0xFFFF) != cn) {
219 cn &= 0xFFFF;
220 PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (ioProx): %u", cn);
223 PrintAndLogEx(SUCCESS, "Simulating ioProx version: " _YELLOW_("%u") " FC: " _YELLOW_("%u (0x%02x)") " CN: " _YELLOW_("%u"), version, fc, fc, cn);
224 PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command");
226 uint8_t bs[64];
227 memset(bs, 0x00, sizeof(bs));
229 if (getIOProxBits(version, fc, cn, bs) != PM3_SUCCESS) {
230 PrintAndLogEx(ERR, "Error with tag bitstream generation.");
231 return PM3_ESOFT;
233 // ioProx uses: fcHigh: 10, fcLow: 8, clk: 64, invert: 1
234 // arg1 --- fcHigh<<8 + fcLow
235 // arg2 --- Invert and clk setting
236 // size --- 64 bits == 8 bytes
237 lf_fsksim_t *payload = calloc(1, sizeof(lf_fsksim_t) + sizeof(bs));
238 payload->fchigh = 10;
239 payload->fclow = 8;
240 payload->separator = 1;
241 payload->clock = 64;
242 memcpy(payload->data, bs, sizeof(bs));
244 clearCommandBuffer();
245 SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + sizeof(bs));
246 free(payload);
247 PacketResponseNG resp;
248 WaitForResponse(CMD_LF_FSK_SIMULATE, &resp);
249 PrintAndLogEx(INFO, "Done");
250 if (resp.status != PM3_EOPABORTED)
251 return resp.status;
252 return PM3_SUCCESS;
255 static int CmdIOProxClone(const char *Cmd) {
257 CLIParserContext *ctx;
258 CLIParserInit(&ctx, "lf io clone",
259 "clone a ioProx card with specified facility-code and card number\n"
260 "to a T55x7, Q5/T5555 or EM4305/4469 tag.\n"
261 "Tag must be on the antenna when issuing this command.",
262 "lf io clone --vn 1 --fc 101 --cn 1337"
265 void *argtable[] = {
266 arg_param_begin,
267 arg_u64_1(NULL, "vn", "<dec>", "8bit version"),
268 arg_u64_1(NULL, "fc", "<dec>", "8bit facility code"),
269 arg_u64_1(NULL, "cn", "<dec>", "16bit card number"),
270 arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
271 arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
272 arg_param_end
274 CLIExecWithReturn(ctx, Cmd, argtable, false);
276 uint8_t version = arg_get_u32_def(ctx, 1, 0);
277 uint8_t fc = arg_get_u32_def(ctx, 2, 0);
278 uint16_t cn = arg_get_u32_def(ctx, 3, 0);
279 bool q5 = arg_get_lit(ctx, 4);
280 bool em = arg_get_lit(ctx, 5);
281 CLIParserFree(ctx);
283 if (q5 && em) {
284 PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
285 return PM3_EINVARG;
288 uint8_t bits[64];
289 memset(bits, 0, sizeof(bits));
291 if ((cn & 0xFFFF) != cn) {
292 cn &= 0xFFFF;
293 PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (ioProx): %u", cn);
296 if (getIOProxBits(version, fc, cn, bits) != PM3_SUCCESS) {
297 PrintAndLogEx(ERR, "Error with tag bitstream generation.");
298 return PM3_ESOFT;
301 uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
302 char cardtype[16] = {"T55x7"};
303 // Q5
304 if (q5) {
305 blocks[0] = T5555_FIXED | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
306 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
309 // EM4305
310 if (em) {
311 blocks[0] = EM4305_IOPROX_CONFIG_BLOCK;
312 snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
315 blocks[1] = bytebits_to_byte(bits, 32);
316 blocks[2] = bytebits_to_byte(bits + 32, 32);
318 PrintAndLogEx(INFO, "Preparing to clone ioProx to " _YELLOW_("%s") " with Version: " _GREEN_("%u") " FC: " _GREEN_("%u (0x%02x)") " CN: " _GREEN_("%u")
319 , cardtype
320 , version
321 , fc
322 , fc
323 , cn
325 print_blocks(blocks, ARRAYLEN(blocks));
327 int res;
328 if (em) {
329 res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
330 } else {
331 res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
333 PrintAndLogEx(SUCCESS, "Done");
334 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf io reader`") " to verify");
335 return res;
338 static command_t CommandTable[] = {
339 {"help", CmdHelp, AlwaysAvailable, "this help"},
340 {"demod", CmdIOProxDemod, AlwaysAvailable, "demodulate an ioProx tag from the GraphBuffer"},
341 {"reader", CmdIOProxReader, IfPm3Lf, "attempt to read and extract tag data"},
342 {"clone", CmdIOProxClone, IfPm3Lf, "clone ioProx tag to T55x7 or Q5/T5555"},
343 {"sim", CmdIOProxSim, IfPm3Lf, "simulate ioProx tag"},
344 {"watch", CmdIOProxWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
345 {NULL, NULL, NULL, NULL}
348 static int CmdHelp(const char *Cmd) {
349 (void)Cmd; // Cmd is not used so far
350 CmdsHelp(CommandTable);
351 return PM3_SUCCESS;
354 int CmdLFIO(const char *Cmd) {
355 clearCommandBuffer();
356 return CmdsParse(CommandTable, Cmd);
359 //Index map
360 //0 10 20 30 40 50 60
361 //| | | | | | |
362 //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
363 //-----------------------------------------------------------------------------
364 //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 crc 11
365 //XSF(version)facility:codeone+codetwo (raw)
366 int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) {
367 #define SEPARATOR 1
368 uint8_t pos = 0;
369 // the return bits, preamble 0000 0000 0
370 uint8_t pre[64];
371 memset(pre, 0, sizeof(pre));
373 // skip 9 zeros as preamble
374 pos = 9;
376 // another fixed byte 11110000 = 0xF0
377 num_to_bytebits(0xF0, 8, pre + pos);
378 pos += 8;
379 pre[pos] = SEPARATOR;
380 pos++;
382 // add facilitycode
383 num_to_bytebits(fc, 8, pre + pos);
384 pos += 8;
385 pre[pos] = SEPARATOR;
386 pos++;
388 // add version
389 num_to_bytebits(version, 8, pre + pos);
390 pos += 8;
391 pre[pos] = SEPARATOR;
392 pos++;
394 // cardnumber high byte
395 num_to_bytebits(((cn & 0xFF00) >> 8), 8, pre + pos);
396 pos += 8;
397 pre[pos] = SEPARATOR;
398 pos++;
400 // cardnumber low byte
401 num_to_bytebits((cn & 0xFF), 8, pre + pos);
402 pos += 8;
403 pre[pos] = SEPARATOR;
404 pos++;
406 // calculate and add CRC
407 uint16_t crc = 0;
408 for (uint8_t i = 1; i < 6; ++i)
409 crc += bytebits_to_byte(pre + 9 * i, 8);
411 crc &= 0xFF;
412 crc = 0xff - crc;
413 num_to_bytebits(crc, 8, pre + pos);
414 pos += 8;
416 // Final two ONES
417 pre[pos] = SEPARATOR;
418 pre[++pos] = SEPARATOR;
420 memcpy(bits, pre, sizeof(pre));
422 PrintAndLogEx(SUCCESS, "IO raw bits:\n %s \n", sprint_bin(bits, 64));
423 return PM3_SUCCESS;