textual
[RRG-proxmark3.git] / client / src / cmdlfindala.c
blob100d35e3b02d44b64937c83604214a8ddc630e6b
1 //-----------------------------------------------------------------------------
2 //
3 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
4 // at your option, any later version. See the LICENSE.txt file for the text of
5 // the license.
6 //-----------------------------------------------------------------------------
7 // Low frequency Indala commands
8 // PSK1, rf/32, 64 or 224 bits (known)
9 //-----------------------------------------------------------------------------
11 #include "cmdlfindala.h"
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <inttypes.h>
16 #include "cmdparser.h" // command_t
17 #include "comms.h"
18 #include "graph.h"
19 #include "cliparser.h"
20 #include "commonutil.h"
21 #include "ui.h" // PrintAndLog
22 #include "proxgui.h"
23 #include "lfdemod.h" // parityTest, bitbytes_to_byte
24 #include "cmddata.h"
25 #include "cmdlf.h" // lf_read
26 #include "protocols.h" // t55 defines
27 #include "cmdlft55xx.h" // verifywrite
28 #include "cliparser.h"
29 #include "cmdlfem4x05.h" // EM defines
31 #define INDALA_ARR_LEN 64
33 static int CmdHelp(const char *Cmd);
35 //large 224 bit indala formats (different preamble too...)
36 static uint8_t preamble224[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
38 // standard 64 bit indala formats including 26 bit 40134 format
39 static uint8_t preamble64[] = {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
41 #define HEDEN2L_OFFSET 31
42 static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) {
44 uint8_t template[] = {
45 1, 0, 1, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0,
49 1, 0, 0, 0, 1, 0, 0, 0,
50 1, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 1, 0, 0, 1,
52 0, 0, 0, 0, 0, 0, 1, 0
54 uint8_t cardbits[32];
56 num_to_bytebits(cardnumber, sizeof(cardbits), cardbits);
58 if (cardbits[31] == 1) template[HEDEN2L_OFFSET + 8] = 0x1;
59 if (cardbits[30] == 1) template[HEDEN2L_OFFSET + 10] = 0x1;
60 if (cardbits[29] == 1) template[HEDEN2L_OFFSET + 14] = 0x1;
61 if (cardbits[28] == 1) template[HEDEN2L_OFFSET + 15] = 0x1;
62 if (cardbits[27] == 1) template[HEDEN2L_OFFSET + 12] = 0x1;
63 if (cardbits[26] == 1) template[HEDEN2L_OFFSET + 28] = 0x1;
64 if (cardbits[25] == 1) template[HEDEN2L_OFFSET + 3] = 0x1;
65 if (cardbits[24] == 1) template[HEDEN2L_OFFSET + 11] = 0x1;
66 if (cardbits[23] == 1) template[HEDEN2L_OFFSET + 19] = 0x1;
67 if (cardbits[22] == 1) template[HEDEN2L_OFFSET + 26] = 0x1;
68 if (cardbits[21] == 1) template[HEDEN2L_OFFSET + 17] = 0x1;
69 if (cardbits[20] == 1) template[HEDEN2L_OFFSET + 18] = 0x1;
70 if (cardbits[19] == 1) template[HEDEN2L_OFFSET + 20] = 0x1;
71 if (cardbits[18] == 1) template[HEDEN2L_OFFSET + 13] = 0x1;
72 if (cardbits[17] == 1) template[HEDEN2L_OFFSET + 7] = 0x1;
73 if (cardbits[16] == 1) template[HEDEN2L_OFFSET + 23] = 0x1;
75 // Parity
76 uint8_t counter = 0;
77 for (int i = 0; i < sizeof(template) - HEDEN2L_OFFSET; i++) {
78 if (template[i])
79 counter++;
81 template[63] = (counter & 0x1);
83 for (int i = 0; i < sizeof(template); i += 8) {
84 dest[i / 8] = bytebits_to_byte(template + i, 8);
87 PrintAndLogEx(INFO, "Heden-2L card number %u", cardnumber);
90 static void decodeHeden2L(uint8_t *bits) {
92 uint32_t cardnumber = 0;
93 uint8_t offset = HEDEN2L_OFFSET;
95 if (bits[offset + 8]) cardnumber += 1;
96 if (bits[offset + 10]) cardnumber += 2;
97 if (bits[offset + 14]) cardnumber += 4;
98 if (bits[offset + 15]) cardnumber += 8;
99 if (bits[offset + 12]) cardnumber += 16;
100 if (bits[offset + 28]) cardnumber += 32;
101 if (bits[offset + 3]) cardnumber += 64;
102 if (bits[offset + 11]) cardnumber += 128;
103 if (bits[offset + 19]) cardnumber += 256;
104 if (bits[offset + 26]) cardnumber += 512;
105 if (bits[offset + 17]) cardnumber += 1024;
106 if (bits[offset + 18]) cardnumber += 2048;
107 if (bits[offset + 20]) cardnumber += 4096;
108 if (bits[offset + 13]) cardnumber += 8192;
109 if (bits[offset + 7]) cardnumber += 16384;
110 if (bits[offset + 23]) cardnumber += 32768;
112 PrintAndLogEx(SUCCESS, " Heden-2L | %u", cardnumber);
115 // Indala 26 bit decode
116 // by marshmellow, martinbeier
117 // optional arguments - same as PSKDemod (clock & invert & maxerr)
118 int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) {
119 (void) verbose; // unused so far
120 int ans = PSKDemod(clk, invert, maxErr, true);
121 if (ans != PM3_SUCCESS) {
122 PrintAndLogEx(DEBUG, "DEBUG: Error - Indala can't demod signal: %d", ans);
123 return PM3_ESOFT;
126 uint8_t inv = 0;
127 size_t size = DemodBufferLen;
128 int idx = detectIndala(DemodBuffer, &size, &inv);
129 if (idx < 0) {
130 if (idx == -1)
131 PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: not enough samples");
132 else if (idx == -2)
133 PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: only noise found");
134 else if (idx == -4)
135 PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: preamble not found");
136 else if (idx == -5)
137 PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: size not correct: %zu", size);
138 else
139 PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: error demoding psk idx: %d", idx);
140 return PM3_ESOFT;
142 setDemodBuff(DemodBuffer, size, idx);
143 setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock));
145 //convert UID to HEX
146 uint32_t uid1 = bytebits_to_byte(DemodBuffer, 32);
147 uint32_t uid2 = bytebits_to_byte(DemodBuffer + 32, 32);
148 // To be checked, what's this internal ID ?
149 // foo is only used for 64b ids and in that case uid1 must be only preamble, plus the following code is wrong as x<<32 & 0x1FFFFFFF is always zero
150 //uint64_t foo = (((uint64_t)uid1 << 32) & 0x1FFFFFFF) | (uid2 & 0x7FFFFFFF);
151 uint64_t foo = uid2 & 0x7FFFFFFF;
153 if (DemodBufferLen == 64) {
154 PrintAndLogEx(SUCCESS, "Indala (len %zu) Raw: " _GREEN_("%x%08x"), DemodBufferLen, uid1, uid2);
156 uint16_t p1 = 0;
157 p1 |= DemodBuffer[32 + 3] << 8;
158 p1 |= DemodBuffer[32 + 6] << 5;
159 p1 |= DemodBuffer[32 + 8] << 4;
160 p1 |= DemodBuffer[32 + 9] << 3;
161 p1 |= DemodBuffer[32 + 11] << 1;
162 p1 |= DemodBuffer[32 + 16] << 6;
163 p1 |= DemodBuffer[32 + 19] << 7;
164 p1 |= DemodBuffer[32 + 20] << 10;
165 p1 |= DemodBuffer[32 + 21] << 2;
166 p1 |= DemodBuffer[32 + 22] << 0;
167 p1 |= DemodBuffer[32 + 24] << 9;
169 uint8_t fc = 0;
170 fc |= DemodBuffer[57] << 7; // b8
171 fc |= DemodBuffer[49] << 6; // b7
172 fc |= DemodBuffer[44] << 5; // b6
173 fc |= DemodBuffer[47] << 4; // b5
174 fc |= DemodBuffer[48] << 3; // b4
175 fc |= DemodBuffer[53] << 2; // b3
176 fc |= DemodBuffer[39] << 1; // b2
177 fc |= DemodBuffer[58] << 0; // b1
179 uint16_t csn = 0;
180 csn |= DemodBuffer[42] << 15; // b16
181 csn |= DemodBuffer[45] << 14; // b15
182 csn |= DemodBuffer[43] << 13; // b14
183 csn |= DemodBuffer[40] << 12; // b13
184 csn |= DemodBuffer[52] << 11; // b12
185 csn |= DemodBuffer[36] << 10; // b11
186 csn |= DemodBuffer[35] << 9; // b10
187 csn |= DemodBuffer[51] << 8; // b9
188 csn |= DemodBuffer[46] << 7; // b8
189 csn |= DemodBuffer[33] << 6; // b7
190 csn |= DemodBuffer[37] << 5; // b6
191 csn |= DemodBuffer[54] << 4; // b5
192 csn |= DemodBuffer[56] << 3; // b4
193 csn |= DemodBuffer[59] << 2; // b3
194 csn |= DemodBuffer[50] << 1; // b2
195 csn |= DemodBuffer[41] << 0; // b1
197 uint8_t checksum = 0;
198 checksum |= DemodBuffer[62] << 1; // b2
199 checksum |= DemodBuffer[63] << 0; // b1
201 PrintAndLogEx(SUCCESS, "Fmt " _GREEN_("26") " FC: " _GREEN_("%u") " Card: " _GREEN_("%u") " checksum: " _GREEN_("%1d%1d")
202 , fc
203 , csn
204 , checksum >> 1 & 0x01
205 , checksum & 0x01
208 PrintAndLogEx(SUCCESS, "Possible de-scramble patterns");
209 PrintAndLogEx(SUCCESS, " Printed | __%04d__ [0x%X]", p1, p1);
210 PrintAndLogEx(SUCCESS, " Internal ID | %" PRIu64, foo);
211 decodeHeden2L(DemodBuffer);
213 } else {
214 uint32_t uid3 = bytebits_to_byte(DemodBuffer + 64, 32);
215 uint32_t uid4 = bytebits_to_byte(DemodBuffer + 96, 32);
216 uint32_t uid5 = bytebits_to_byte(DemodBuffer + 128, 32);
217 uint32_t uid6 = bytebits_to_byte(DemodBuffer + 160, 32);
218 uint32_t uid7 = bytebits_to_byte(DemodBuffer + 192, 32);
219 PrintAndLogEx(
220 SUCCESS
221 , "Indala (len %zu) Raw: " _GREEN_("%x%08x%08x%08x%08x%08x%08x")
222 , DemodBufferLen
223 , uid1
224 , uid2
225 , uid3
226 , uid4
227 , uid5
228 , uid6
229 , uid7
233 if (g_debugMode) {
234 PrintAndLogEx(DEBUG, "DEBUG: Indala - printing demodbuffer");
235 printDemodBuff(0, false, false, false);
237 return PM3_SUCCESS;
240 int demodIndala(bool verbose) {
241 return demodIndalaEx(0, 0, 100, verbose);
244 static int CmdIndalaDemod(const char *Cmd) {
246 CLIParserContext *ctx;
247 CLIParserInit(&ctx, "lf indala demod",
248 "Tries to psk demodulate the graphbuffer as Indala",
249 "lf indala demod\n"
250 "lf indala demod --clock 32 -> demod a Indala tag from GraphBuffer using a clock of RF/32\n"
251 "lf indala demod --clock 32 -i -> demod a Indala tag from GraphBuffer using a clock of RF/32 and inverting data\n"
252 "lf indala demod --clock 64 -i --maxerror 0 -> demod a Indala tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"
255 void *argtable[] = {
256 arg_param_begin,
257 arg_int0(NULL, "clock", "<dec>", "optional - set clock (as integer), if not set, autodetect."),
258 arg_int0(NULL, "maxerr", "<dec>", "optional - set maximum allowed errors, default = 100"),
259 arg_lit0("i", "invert", "optional - invert output"),
260 arg_param_end
262 CLIExecWithReturn(ctx, Cmd, argtable, true);
263 uint32_t clk = arg_get_u32_def(ctx, 1, 32);
264 uint32_t max_err = arg_get_u32_def(ctx, 2, 100);
265 bool invert = arg_get_lit(ctx, 3);
266 CLIParserFree(ctx);
268 return demodIndalaEx(clk, invert, max_err, true);
271 // older alternative indala demodulate (has some positives and negatives)
272 // returns false positives more often - but runs against more sets of samples
273 // poor psk signal can be difficult to demod this approach might succeed when the other fails
274 // but the other appears to currently be more accurate than this approach most of the time.
275 static int CmdIndalaDemodAlt(const char *Cmd) {
277 CLIParserContext *ctx;
278 CLIParserInit(&ctx, "lf indala altdemod",
279 "Tries to psk demodulate the graphbuffer as Indala\n"
280 "This is uses a alternative way to demodulate and was used from the beginning in the Pm3 client.\n"
281 "It's now considered obsolete but remains because it has sometimes its advantages.",
282 "lf indala altdemod\n"
283 "lf indala altdemod --long -> demod a Indala tag from GraphBuffer as 224 bit long format"
286 void *argtable[] = {
287 arg_param_begin,
288 arg_lit0("l", "long", "optional - demod as 224b long format"),
289 arg_param_end
291 CLIExecWithReturn(ctx, Cmd, argtable, true);
292 bool is_long = arg_get_lit(ctx, 1);
293 CLIParserFree(ctx);
295 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
296 int state = -1;
297 int count = 0;
298 int i, j;
300 // worst case with GraphTraceLen=40000 is < 4096
301 // under normal conditions it's < 2048
302 uint8_t data[MAX_GRAPH_TRACE_LEN] = {0};
303 size_t datasize = getFromGraphBuf(data);
305 uint8_t rawbits[4096];
306 int rawbit = 0;
307 int worst = 0, worstPos = 0;
309 //clear clock grid and demod plot
310 setClockGrid(0, 0);
311 DemodBufferLen = 0;
313 // PrintAndLogEx(NORMAL, "Expecting a bit less than %d raw bits", GraphTraceLen / 32);
314 // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2)
315 for (i = 0; i < datasize - 1; i += 2) {
316 count += 1;
317 if ((data[i] > data[i + 1]) && (state != 1)) {
318 // appears redundant - marshmellow
319 if (state == 0) {
320 for (j = 0; j < count - 8; j += 16) {
321 rawbits[rawbit++] = 0;
323 if ((abs(count - j)) > worst) {
324 worst = abs(count - j);
325 worstPos = i;
328 state = 1;
329 count = 0;
330 } else if ((data[i] < data[i + 1]) && (state != 0)) {
331 //appears redundant
332 if (state == 1) {
333 for (j = 0; j < count - 8; j += 16) {
334 rawbits[rawbit++] = 1;
336 if ((abs(count - j)) > worst) {
337 worst = abs(count - j);
338 worstPos = i;
341 state = 0;
342 count = 0;
346 if (rawbit > 0) {
347 PrintAndLogEx(INFO, "Recovered %d raw bits, expected: %zu", rawbit, GraphTraceLen / 32);
348 PrintAndLogEx(INFO, "worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
349 } else {
350 return PM3_ESOFT;
353 // Finding the start of a UID
354 int uidlen, long_wait;
355 if (is_long) {
356 uidlen = 224;
357 long_wait = 30;
358 } else {
359 uidlen = 64;
360 long_wait = 29;
363 int start;
364 int first = 0;
365 for (start = 0; start <= rawbit - uidlen; start++) {
366 first = rawbits[start];
367 for (i = start; i < start + long_wait; i++) {
368 if (rawbits[i] != first) {
369 break;
372 if (i == (start + long_wait)) {
373 break;
377 if (start == rawbit - uidlen + 1) {
378 PrintAndLogEx(FAILED, "nothing to wait for");
379 return PM3_ESOFT;
382 // Inverting signal if needed
383 if (first == 1) {
384 for (i = start; i < rawbit; i++) {
385 rawbits[i] = !rawbits[i];
389 // Dumping UID
390 uint8_t bits[224] = {0x00};
391 char showbits[225] = {0x00};
392 int bit;
393 i = start;
394 int times = 0;
396 if (uidlen > rawbit) {
397 PrintAndLogEx(WARNING, "Warning: not enough raw bits to get a full UID");
398 for (bit = 0; bit < rawbit; bit++) {
399 bits[bit] = rawbits[i++];
400 // As we cannot know the parity, let's use "." and "/"
401 showbits[bit] = '.' + bits[bit];
403 showbits[bit + 1] = '\0';
404 PrintAndLogEx(SUCCESS, "Partial UID | %s", showbits);
405 return PM3_SUCCESS;
406 } else {
407 for (bit = 0; bit < uidlen; bit++) {
408 bits[bit] = rawbits[i++];
409 showbits[bit] = '0' + bits[bit];
411 times = 1;
414 //convert UID to HEX
415 int idx;
416 uint32_t uid1 = 0;
417 uint32_t uid2 = 0;
419 if (uidlen == 64) {
420 for (idx = 0; idx < 64; idx++) {
421 if (showbits[idx] == '0') {
422 uid1 = (uid1 << 1) | (uid2 >> 31);
423 uid2 = (uid2 << 1) | 0;
424 } else {
425 uid1 = (uid1 << 1) | (uid2 >> 31);
426 uid2 = (uid2 << 1) | 1;
429 PrintAndLogEx(SUCCESS, "UID | %s (%x%08x)", showbits, uid1, uid2);
430 } else {
431 uint32_t uid3 = 0;
432 uint32_t uid4 = 0;
433 uint32_t uid5 = 0;
434 uint32_t uid6 = 0;
435 uint32_t uid7 = 0;
437 for (idx = 0; idx < 224; idx++) {
438 uid1 = (uid1 << 1) | (uid2 >> 31);
439 uid2 = (uid2 << 1) | (uid3 >> 31);
440 uid3 = (uid3 << 1) | (uid4 >> 31);
441 uid4 = (uid4 << 1) | (uid5 >> 31);
442 uid5 = (uid5 << 1) | (uid6 >> 31);
443 uid6 = (uid6 << 1) | (uid7 >> 31);
445 if (showbits[idx] == '0')
446 uid7 = (uid7 << 1) | 0;
447 else
448 uid7 = (uid7 << 1) | 1;
450 PrintAndLogEx(SUCCESS, "UID | %s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
453 // Checking UID against next occurrences
454 for (; i + uidlen <= rawbit;) {
455 int failed = 0;
456 for (bit = 0; bit < uidlen; bit++) {
457 if (bits[bit] != rawbits[i++]) {
458 failed = 1;
459 break;
462 if (failed == 1) {
463 break;
465 times += 1;
468 PrintAndLogEx(DEBUG, "Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
470 // Remodulating for tag cloning
471 // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod)
472 // since this changes graphbuffer data.
473 GraphTraceLen = 32 * uidlen;
474 i = 0;
475 int phase;
476 for (bit = 0; bit < uidlen; bit++) {
477 if (bits[bit] == 0) {
478 phase = 0;
479 } else {
480 phase = 1;
482 for (j = 0; j < 32; j++) {
483 GraphBuffer[i++] = phase;
484 phase = !phase;
488 RepaintGraphWindow();
489 return PM3_SUCCESS;
492 // this read is the "normal" read, which download lf signal and tries to demod here.
493 static int CmdIndalaReader(const char *Cmd) {
494 CLIParserContext *ctx;
495 CLIParserInit(&ctx, "lf indala reader",
496 "read a Indala tag",
497 "lf indala reader -@ -> continuous reader mode"
500 void *argtable[] = {
501 arg_param_begin,
502 arg_int0(NULL, "clock", "<dec>", "optional - set clock (as integer), if not set, autodetect."),
503 arg_int0(NULL, "maxerr", "<dec>", "optional - set maximum allowed errors, default = 100"),
504 arg_lit0("i", "invert", "optional - invert output"),
505 arg_lit0("@", NULL, "optional - continuous reader mode"),
506 arg_param_end
508 CLIExecWithReturn(ctx, Cmd, argtable, true);
509 uint32_t clk = arg_get_u32_def(ctx, 1, 32);
510 uint32_t max_err = arg_get_u32_def(ctx, 2, 100);
511 bool invert = arg_get_lit(ctx, 3);
512 bool cm = arg_get_lit(ctx, 4);
513 CLIParserFree(ctx);
515 if (cm) {
516 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
519 do {
520 lf_read(false, 30000);
521 demodIndalaEx(clk, invert, max_err, !cm);
522 } while (cm && !kbd_enter_pressed());
523 return PM3_SUCCESS;
526 static int CmdIndalaSim(const char *Cmd) {
528 CLIParserContext *ctx;
529 CLIParserInit(&ctx, "lf indala sim",
530 "Enables simulation of Indala card with specified facility-code and card number.\n"
531 "Simulation runs until the button is pressed or another USB command is issued.",
532 "lf indala sim --heden 888\n"
533 "lf indala sim --raw a0000000a0002021\n"
534 "lf indala sim --raw 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"
537 void *argtable[] = {
538 arg_param_begin,
539 arg_strx0("r", "raw", "<hex>", "raw bytes"),
540 arg_int0(NULL, "heden", "<decimal>", "Cardnumber for Heden 2L format"),
541 arg_param_end
543 CLIExecWithReturn(ctx, Cmd, argtable, false);
545 // raw param
546 int raw_len = 0;
547 uint8_t raw[(7 * 4) + 1];
548 memset(raw, 0, sizeof(raw));
549 CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
551 bool is_long_uid = (raw_len == 28);
553 int32_t cardnumber;
554 bool got_cn = false;
555 if (is_long_uid == false) {
557 // Heden param
558 cardnumber = arg_get_int_def(ctx, 2, -1);
559 got_cn = (cardnumber != -1);
562 CLIParserFree(ctx);
564 if (got_cn) {
565 encodeHeden2L(raw, cardnumber);
566 raw_len = 8;
569 // convert to binarray
570 uint8_t bs[224];
571 memset(bs, 0x00, sizeof(bs));
573 uint8_t counter = 0;
574 for (int8_t i = 0; i < raw_len; i++) {
575 uint8_t tmp = raw[i];
576 bs[counter++] = (tmp >> 7) & 1;
577 bs[counter++] = (tmp >> 6) & 1;
578 bs[counter++] = (tmp >> 5) & 1;
579 bs[counter++] = (tmp >> 4) & 1;
580 bs[counter++] = (tmp >> 3) & 1;
581 bs[counter++] = (tmp >> 2) & 1;
582 bs[counter++] = (tmp >> 1) & 1;
583 bs[counter++] = tmp & 1;
586 // a0 00 00 00 bd 98 9a 11
588 // indala PSK
589 // It has to send either 64bits (8bytes) or 224bits (28bytes). Zero padding needed if not.
590 // lf simpsk -1 -c 32 --fc 2 -d 0102030405060708
592 PrintAndLogEx(SUCCESS, "Simulating " _YELLOW_("%s") " Indala raw " _YELLOW_("%s")
593 , (is_long_uid) ? "224 bit" : "64 bit"
594 , sprint_hex_inrow(raw, raw_len)
596 PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command");
598 // indala PSK, clock 32, carrier 0
599 lf_psksim_t *payload = calloc(1, sizeof(lf_psksim_t) + sizeof(bs));
600 payload->carrier = 2;
601 payload->invert = 0;
602 payload->clock = 32;
603 memcpy(payload->data, bs, raw_len * 8);
605 clearCommandBuffer();
606 SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + (raw_len * 8));
607 free(payload);
609 PacketResponseNG resp;
610 WaitForResponse(CMD_LF_PSK_SIMULATE, &resp);
612 PrintAndLogEx(INFO, "Done");
613 if (resp.status != PM3_EOPABORTED)
614 return resp.status;
615 return PM3_SUCCESS;
618 static int CmdIndalaClone(const char *Cmd) {
620 int32_t cardnumber;
621 uint8_t fc = 0;
622 uint16_t cn = 0;
624 CLIParserContext *ctx;
625 CLIParserInit(&ctx, "lf indala clone",
626 "clone Indala UID to T55x7 or Q5/T5555 tag\n"
627 _RED_("\nWarning, encoding with FC/CN doesn't always work"),
628 "lf indala clone --heden 888\n"
629 "lf indala clone --fc 123 --cn 1337\n"
630 "lf indala clone -r a0000000a0002021\n"
631 "lf indala clone -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
633 void *argtable[] = {
634 arg_param_begin,
635 arg_strx0("r", "raw", "<hex>", "raw bytes"),
636 arg_int0(NULL, "heden", "<decimal>", "Cardnumber for Heden 2L format"),
637 arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit H10301 format)"),
638 arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit H10301 format)"),
639 arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"),
640 arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"),
641 arg_param_end
643 CLIExecWithReturn(ctx, Cmd, argtable, false);
644 // raw param
645 int raw_len = 0;
646 uint8_t raw[(7 * 4) + 1];
647 CLIGetHexWithReturn(ctx, 1, raw, &raw_len);
649 bool is_long_uid = (raw_len == 28);
650 bool q5 = arg_get_lit(ctx, 5);
651 bool em = arg_get_lit(ctx, 6);
653 bool got_cn = false, got_26 = false;
654 if (is_long_uid == false) {
656 // Heden param
657 cardnumber = arg_get_int_def(ctx, 2, -1);
658 got_cn = (cardnumber != -1);
660 // 26b FC/CN param
661 fc = arg_get_int_def(ctx, 3, 0);
662 cn = arg_get_int_def(ctx, 4, 0);
663 got_26 = (fc != 0 && cn != 0);
665 CLIParserFree(ctx);
667 if (q5 && em) {
668 PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time");
669 return PM3_EINVARG;
672 uint8_t max = 0;
673 uint32_t blocks[8] = {0};
674 char cardtype[16] = {"T55x7"};
676 if (is_long_uid) {
678 blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
679 if (q5) {
680 blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT);
681 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
684 if (em) {
685 blocks[0] = EM4305_INDALA_224_CONFIG_BLOCK;
686 snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
689 blocks[1] = bytes_to_num(raw, 4);
690 blocks[2] = bytes_to_num(raw + 4, 4);
691 blocks[3] = bytes_to_num(raw + 8, 4);
692 blocks[4] = bytes_to_num(raw + 12, 4);
693 blocks[5] = bytes_to_num(raw + 16, 4);
694 blocks[6] = bytes_to_num(raw + 20, 4);
695 blocks[7] = bytes_to_num(raw + 24, 4);
696 max = 8;
698 // 224 BIT UID
699 // config for Indala (RF/32;PSK2 with RF/2;Maxblock=7)
700 PrintAndLogEx(INFO, "Preparing to clone Indala 224bit to " _YELLOW_("%s") " raw " _GREEN_("%s")
701 , cardtype
702 , sprint_hex_inrow(raw, raw_len)
706 } else {
707 // 64 BIT UID
708 if (got_cn) {
709 encodeHeden2L(raw, cardnumber);
710 raw_len = 8;
711 } else if (got_26) {
713 PrintAndLogEx(INFO, "Using Indala 26b FC " _GREEN_("%u") " CN " _GREEN_("%u"), fc, cn);
715 // Used with the 26bit FC/CSN
716 uint8_t *bits = calloc(INDALA_ARR_LEN, sizeof(uint8_t));
717 if (bits == NULL) {
718 PrintAndLogEx(WARNING, "Failed to allocate memory");
719 return PM3_EMALLOC;
722 if (getIndalaBits(fc, cn, bits) != PM3_SUCCESS) {
723 PrintAndLogEx(ERR, "Error with tag bitstream generation.");
724 free(bits);
725 return PM3_ESOFT;
728 raw[0] = bytebits_to_byte(bits, 8);
729 raw[1] = bytebits_to_byte(bits + 8, 8);
730 raw[2] = bytebits_to_byte(bits + 16, 8);
731 raw[3] = bytebits_to_byte(bits + 24, 8);
732 raw[4] = bytebits_to_byte(bits + 32, 8);
733 raw[5] = bytebits_to_byte(bits + 40, 8);
734 raw[6] = bytebits_to_byte(bits + 48, 8);
735 raw[7] = bytebits_to_byte(bits + 56, 8);
736 raw_len = 8;
738 free(bits);
741 blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
743 if (q5) {
744 blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT);
745 snprintf(cardtype, sizeof(cardtype), "Q5/T5555");
748 if (em) {
749 blocks[0] = EM4305_INDALA_64_CONFIG_BLOCK;
750 snprintf(cardtype, sizeof(cardtype), "EM4305/4469");
753 blocks[1] = bytes_to_num(raw, 4);
754 blocks[2] = bytes_to_num(raw + 4, 4);
755 max = 3;
757 // config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
758 PrintAndLogEx(INFO, "Preparing to clone Indala 64bit to " _YELLOW_("%s") " raw " _GREEN_("%s")
759 , cardtype
760 , sprint_hex_inrow(raw, raw_len)
764 print_blocks(blocks, max);
766 int res;
767 if (em) {
768 res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false);
769 } else {
770 res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
772 PrintAndLogEx(SUCCESS, "Done");
773 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf indala reader`") " to verify");
774 return res;
777 static command_t CommandTable[] = {
778 {"help", CmdHelp, AlwaysAvailable, "this help"},
779 {"demod", CmdIndalaDemod, AlwaysAvailable, "demodulate an Indala tag (PSK1) from GraphBuffer"},
780 {"altdemod", CmdIndalaDemodAlt, AlwaysAvailable, "alternative method to demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
781 {"reader", CmdIndalaReader, IfPm3Lf, "read an Indala tag from the antenna"},
782 {"clone", CmdIndalaClone, IfPm3Lf, "clone Indala tag to T55x7 or Q5/T5555"},
783 {"sim", CmdIndalaSim, IfPm3Lf, "simulate Indala tag"},
784 {NULL, NULL, NULL, NULL}
787 static int CmdHelp(const char *Cmd) {
788 (void)Cmd; // Cmd is not used so far
789 CmdsHelp(CommandTable);
790 return PM3_SUCCESS;
793 int CmdLFINDALA(const char *Cmd) {
794 clearCommandBuffer();
795 return CmdsParse(CommandTable, Cmd);
798 int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) {
799 // preamble
800 // is there a preamble?
801 bits[0] = 1;
802 bits[2] = 1;
803 bits[32] = 1;
805 // add fc
806 bits[57] = ((fc >> 7) & 1); // b8
807 bits[49] = ((fc >> 6) & 1); // b7
808 bits[44] = ((fc >> 5) & 1); // b6
809 bits[47] = ((fc >> 4) & 1); // b5
810 bits[48] = ((fc >> 3) & 1); // b4
811 bits[53] = ((fc >> 2) & 1); // b3
812 bits[39] = ((fc >> 1) & 1); // b2
813 bits[58] = (fc & 1); // b1
815 // add cn
816 bits[42] = ((cn >> 15) & 1); // b16
817 bits[45] = ((cn >> 14) & 1); // b15 - c
818 bits[43] = ((cn >> 13) & 1); // b14
819 bits[40] = ((cn >> 12) & 1); // b13 - c
820 bits[52] = ((cn >> 11) & 1); // b12
821 bits[36] = ((cn >> 10) & 1); // b11
822 bits[35] = ((cn >> 9) & 1); // b10 - c
823 bits[51] = ((cn >> 8) & 1); // b9 - c
824 bits[46] = ((cn >> 7) & 1); // b8
825 bits[33] = ((cn >> 6) & 1); // b7 - c
826 bits[37] = ((cn >> 5) & 1); // b6 - c
827 bits[54] = ((cn >> 4) & 1); // b5
828 bits[56] = ((cn >> 3) & 1); // b4
829 bits[59] = ((cn >> 2) & 1); // b3 - c
830 bits[50] = ((cn >> 1) & 1); // b2
831 bits[41] = (cn & 1); // b1 - c
833 // checksum
834 uint8_t chk = 0;
835 //sum(y2, y4, y7, y8, y10, y11, y14, y16
836 chk += ((cn >> 14) & 1); //y2 == 75 - 30 = 45
837 chk += ((cn >> 12) & 1); //y4 == 70 - 30 = 40
838 chk += ((cn >> 9) & 1); //y7 == 65 - 30 = 35
839 chk += ((cn >> 8) & 1); //y8 == 81 - 30 = 51
840 chk += ((cn >> 6) & 1); //y10 == 63 - 30 = 33
841 chk += ((cn >> 5) & 1); //y11 == 67 - 30 = 37
842 chk += ((cn >> 2) & 1); //y14 == 89 - 30 = 59
843 chk += (cn & 1); //y16 == 71 - 30 = 41
845 if ((chk & 1) == 0) {
846 bits[62] = 0;
847 bits[63] = 1;
848 } else {
849 bits[62] = 1;
850 bits[63] = 0;
853 // add parity
854 bits[34] = 1; // p1 64 - 30 = 34
855 bits[38] = 1; // p2 68 - 30 = 38
857 // 92 = 62
858 // 93 = 63
860 return PM3_SUCCESS;
863 // redesigned by marshmellow adjusted from existing decode functions
864 // indala id decoding
865 int detectIndala(uint8_t *dest, size_t *size, uint8_t *invert) {
867 uint8_t preamble64_i[] = {0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
868 uint8_t preamble224_i[] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
869 size_t idx = 0;
870 size_t found_size = *size;
872 // PSK1
873 bool res = preambleSearch(dest, preamble64, sizeof(preamble64), &found_size, &idx);
874 if (res) {
875 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 64");
876 goto out;
878 idx = 0;
879 found_size = *size;
880 res = preambleSearch(dest, preamble64_i, sizeof(preamble64_i), &found_size, &idx);
881 if (res) {
882 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 64 inverted preamble");
883 goto inv;
887 idx = 0;
888 found_size = *size;
889 res = preambleSearch(dest, preamble224, sizeof(preamble224), &found_size, &idx);
890 if ( res ) {
891 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 224");
892 goto out;
895 idx = 0;
896 found_size = *size;
897 res = preambleSearch(dest, preamble224_i, sizeof(preamble224_i), &found_size, &idx);
898 if ( res ) {
899 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 224 inverted preamble");
900 goto inv;
904 // PSK2
905 psk1TOpsk2(dest, *size);
906 PrintAndLogEx(DEBUG, "DEBUG: detectindala Converting PSK1 -> PSK2");
908 idx = 0;
909 found_size = *size;
910 res = preambleSearch(dest, preamble64, sizeof(preamble64), &found_size, &idx);
911 if (res) {
912 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 64 preamble");
913 goto out;
916 idx = 0;
917 found_size = *size;
918 res = preambleSearch(dest, preamble224, sizeof(preamble224), &found_size, &idx);
919 if (res) {
920 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 224 preamble");
921 goto out;
924 idx = 0;
925 found_size = *size;
926 res = preambleSearch(dest, preamble64_i, sizeof(preamble64_i), &found_size, &idx);
927 if (res) {
928 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 64 inverted preamble");
929 goto inv;
932 idx = 0;
933 found_size = *size;
934 res = preambleSearch(dest, preamble224_i, sizeof(preamble224_i), &found_size, &idx);
935 if (res) {
936 PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 224 inverted preamble");
937 goto inv;
940 return -4;
942 inv:
944 *invert ^= 1;
946 if (*invert && idx > 0) {
947 for (size_t i = idx - 1; i < found_size + idx + 2; i++) {
948 dest[i] ^= 1;
952 PrintAndLogEx(DEBUG, "DEBUG: Warning - Indala had to invert bits");
954 out:
956 *size = found_size;
958 if (found_size < 64) {
959 PrintAndLogEx(INFO, "DEBUG: detectindala | %zu", found_size);
960 return -5;
963 // 224 formats are typically PSK2 (afaik 2017 Marshmellow)
964 // note loses 1 bit at beginning of transformation...
965 return (int) idx;