textual
[RRG-proxmark3.git] / client / src / cmdanalyse.c
blob509f3d011fb88c7fd199ee801de518a6d4378326
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2016 iceman
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 // Analyse bytes commands
9 //-----------------------------------------------------------------------------
10 #include "cmdanalyse.h"
12 #include <stdlib.h> // size_t
13 #include <string.h>
14 #include <ctype.h> // tolower
15 #include <math.h>
16 #include <inttypes.h> // PRIx64 macro
17 #include "commonutil.h" // reflect...
18 #include "comms.h" // clearCommandBuffer
19 #include "cmdparser.h" // command_t
20 #include "ui.h" // PrintAndLog
21 #include "crc.h"
22 #include "crc16.h" // crc16 ccitt
23 #include "crc32.h" // crc32_ex
24 #include "tea.h"
25 #include "legic_prng.h"
26 #include "cmddata.h" // demodbuffer
27 #include "graph.h"
28 #include "proxgui.h"
29 #include "cliparser.h"
30 #include "generator.h" // generate nuid
31 #include "iso14b.h" // defines for ETU conversions
33 static int CmdHelp(const char *Cmd);
35 static uint8_t calculateLRC(uint8_t *bytes, uint8_t len) {
36 uint8_t lcr = 0;
37 for (uint8_t i = 0; i < len; i++)
38 lcr ^= bytes[i];
39 return lcr;
42 static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){
43 -----------
44 0x9c | 1001 1100
45 0x97 | 1001 0111
46 0x72 | 0111 0010
47 0x5e | 0101 1110
48 -----------------
49 C32F 9d74
51 return 0;
55 static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){
56 return 0;
59 static uint16_t calcSumCrumbAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
60 uint32_t sum = 0;
61 for (uint8_t i = 0; i < len; i++) {
62 sum += CRUMB(bytes[i], 0);
63 sum += CRUMB(bytes[i], 2);
64 sum += CRUMB(bytes[i], 4);
65 sum += CRUMB(bytes[i], 6);
67 sum &= mask;
68 return (sum & 0xFFFF);
70 static uint16_t calcSumCrumbAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
71 return (~calcSumCrumbAdd(bytes, len, mask) & mask);
73 static uint16_t calcSumNibbleAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
74 uint32_t sum = 0;
75 for (uint8_t i = 0; i < len; i++) {
76 sum += NIBBLE_LOW(bytes[i]);
77 sum += NIBBLE_HIGH(bytes[i]);
79 sum &= mask;
80 return (sum & 0xFFFF);
82 static uint16_t calcSumNibbleAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
83 return (~calcSumNibbleAdd(bytes, len, mask) & mask);
85 static uint16_t calcSumCrumbXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
86 uint32_t sum = 0;
87 for (uint8_t i = 0; i < len; i++) {
88 sum ^= CRUMB(bytes[i], 0);
89 sum ^= CRUMB(bytes[i], 2);
90 sum ^= CRUMB(bytes[i], 4);
91 sum ^= CRUMB(bytes[i], 6);
93 sum &= mask;
94 return (sum & 0xFFFF);
96 static uint16_t calcSumNibbleXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
97 uint32_t sum = 0;
98 for (uint8_t i = 0; i < len; i++) {
99 sum ^= NIBBLE_LOW(bytes[i]);
100 sum ^= NIBBLE_HIGH(bytes[i]);
102 sum &= mask;
103 return (sum & 0xFFFF);
105 static uint16_t calcSumByteXor(uint8_t *bytes, uint8_t len, uint32_t mask) {
106 uint32_t sum = 0;
107 for (uint8_t i = 0; i < len; i++) {
108 sum ^= bytes[i];
110 sum &= mask;
111 return (sum & 0xFFFF);
113 static uint16_t calcSumByteAdd(uint8_t *bytes, uint8_t len, uint32_t mask) {
114 uint32_t sum = 0;
115 for (uint8_t i = 0; i < len; i++) {
116 sum += bytes[i];
118 sum &= mask;
119 return (sum & 0xFFFF);
121 // Ones complement
122 static uint16_t calcSumByteAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
123 return (~calcSumByteAdd(bytes, len, mask) & mask);
126 static uint16_t calcSumByteSub(uint8_t *bytes, uint8_t len, uint32_t mask) {
127 uint32_t sum = 0;
128 for (uint8_t i = 0; i < len; i++) {
129 sum -= bytes[i];
131 sum &= mask;
132 return (sum & 0xFFFF);
134 static uint16_t calcSumByteSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
135 return (~calcSumByteSub(bytes, len, mask) & mask);
137 static uint16_t calcSumNibbleSub(uint8_t *bytes, uint8_t len, uint32_t mask) {
138 uint32_t sum = 0;
139 for (uint8_t i = 0; i < len; i++) {
140 sum -= NIBBLE_LOW(bytes[i]);
141 sum -= NIBBLE_HIGH(bytes[i]);
143 sum &= mask;
144 return (sum & 0xFFFF);
146 static uint16_t calcSumNibbleSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) {
147 return (~calcSumNibbleSub(bytes, len, mask) & mask);
150 // BSD shift checksum 8bit version
151 static uint16_t calcBSDchecksum8(uint8_t *bytes, uint8_t len, uint32_t mask) {
152 uint32_t sum = 0;
153 for (uint8_t i = 0; i < len; i++) {
154 sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator
155 sum += bytes[i]; // add next byte
156 sum &= 0xFF; //
158 sum &= mask;
159 return (sum & 0xFFFF);
161 // BSD shift checksum 4bit version
162 static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask) {
163 uint32_t sum = 0;
164 for (uint8_t i = 0; i < len; i++) {
165 sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator
166 sum += NIBBLE_HIGH(bytes[i]); // add high nibble
167 sum &= 0xF; //
168 sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator
169 sum += NIBBLE_LOW(bytes[i]); // add low nibble
170 sum &= 0xF; //
172 sum &= mask;
173 return (sum & 0xFFFF);
176 // 0xFF - ( n1 ^ n... )
177 static uint16_t calcXORchecksum(uint8_t *bytes, uint8_t len, uint32_t mask) {
178 return 0xFF - calcSumByteXor(bytes, len, mask);
182 //2148050707DB0A0E000001C4000000
184 // measuring LFSR maximum length
185 static int CmdAnalyseLfsr(const char *Cmd) {
186 CLIParserContext *ctx;
187 CLIParserInit(&ctx, "analyse lfsr",
188 "looks at LEGIC Prime's lfsr, iterates the first 48 values",
189 "analyse lfsr --iv 55"
192 void *argtable[] = {
193 arg_param_begin,
194 arg_str1(NULL, "iv", "<hex>", "init vector data (1 hex byte)"),
195 arg_str0(NULL, "find", "<hex>", "lfsr data to find (1 hex byte)"),
196 arg_param_end
198 CLIExecWithReturn(ctx, Cmd, argtable, true);
199 int iv_len = 0;
200 uint8_t idata[1] = {0};
201 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idata, sizeof(idata), &iv_len);
203 if (res) {
204 CLIParserFree(ctx);
205 PrintAndLogEx(FAILED, "Error parsing IV byte");
206 return PM3_EINVARG;
209 int f_len = 0;
210 uint8_t fdata[1] = {0};
211 res = CLIParamHexToBuf(arg_get_str(ctx, 2), fdata, sizeof(fdata), &f_len);
212 CLIParserFree(ctx);
214 if (res) {
215 PrintAndLogEx(FAILED, "Error parsing FIND byte");
216 return PM3_EINVARG;
219 uint8_t iv = idata[0];
220 uint8_t find = fdata[0];
222 PrintAndLogEx(INFO, "LEGIC Prime lfsr");
223 PrintAndLogEx(INFO, "iv..... 0x%02X", iv);
224 PrintAndLogEx(INFO, "----+------+-------+--------------");
225 PrintAndLogEx(INFO, " i# | lfsr | ^0x40 | 0x%02X ^ lfsr", find);
226 PrintAndLogEx(INFO, "----+------+-------+--------------");
228 for (uint8_t i = 0x01; i < 0x30; i += 1) {
229 legic_prng_init(iv);
230 legic_prng_forward(i);
231 uint32_t lfsr = legic_prng_get_bits(12); /* Any nonzero start state will work. */
232 PrintAndLogEx(INFO, " %02X | %03X | %03X | %03X", i, lfsr, 0x40 ^ lfsr, find ^ lfsr);
234 PrintAndLogEx(INFO, "----+------+-------+--------------");
235 return PM3_SUCCESS;
238 static int CmdAnalyseLCR(const char *Cmd) {
239 CLIParserContext *ctx;
240 CLIParserInit(&ctx, "analyse lcr",
241 "Specifying the bytes of a UID with a known LRC will find the last byte value\n"
242 "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX.",
243 "analyse lcr -d 04008064BA -> Target (BA) requires final LRC XOR byte value: 5A"
246 void *argtable[] = {
247 arg_param_begin,
248 arg_str1("d", "data", "<hex>", "bytes to calc missing XOR in a LCR"),
249 arg_param_end
251 CLIExecWithReturn(ctx, Cmd, argtable, true);
252 int dlen = 0;
253 uint8_t data[100] = {0x00};
254 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen);
255 CLIParserFree(ctx);
257 if (res) {
258 PrintAndLogEx(FAILED, "Error parsing bytes");
259 return PM3_EINVARG;
262 uint8_t finalXor = calculateLRC(data, (uint8_t)dlen);
263 PrintAndLogEx(SUCCESS, "Target [%02X] requires final LRC XOR byte value: " _YELLOW_("0x%02X"), data[dlen - 1], finalXor);
264 PrintAndLogEx(NORMAL, "");
265 return PM3_SUCCESS;
268 static int CmdAnalyseCRC(const char *Cmd) {
269 CLIParserContext *ctx;
270 CLIParserInit(&ctx, "analyse crc",
271 "A stub method to test different crc implementations inside the PM3 sourcecode.\n"
272 "Just because you figured out the poly, doesn't mean you get the desired output",
273 "analyse crc -d 137AF00A0A0D"
276 void *argtable[] = {
277 arg_param_begin,
278 arg_str1("d", "data", "<hex>", "bytes to calc crc"),
279 arg_param_end
281 CLIExecWithReturn(ctx, Cmd, argtable, true);
282 int dlen = 0;
283 uint8_t data[1024] = {0x00};
284 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen);
285 CLIParserFree(ctx);
287 if (res) {
288 PrintAndLogEx(FAILED, "Error parsing bytes");
289 return PM3_EINVARG;
292 PrintAndLogEx(INFO, "\nTests with (%d) | %s", dlen, sprint_hex(data, (size_t)dlen));
294 // 51 f5 7a d6
295 uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56
296 init_table(CRC_LEGIC);
297 uint8_t legic8 = CRC8Legic(uid, sizeof(uid)) & 0xFF;
298 PrintAndLogEx(INFO, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, (size_t)dlen, legic8), legic8);
299 init_table(CRC_FELICA);
300 PrintAndLogEx(INFO, "FeliCa | %X ", crc16_xmodem(data, (size_t)dlen));
302 PrintAndLogEx(INFO, "\nTests of reflection. Current methods in source code");
303 PrintAndLogEx(INFO, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L, 3));
304 PrintAndLogEx(INFO, " reflect8(0x80) is %02X == 0x01", reflect8(0x80));
305 PrintAndLogEx(INFO, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6));
307 uint8_t b1, b2;
308 // ISO14443 crc B
309 compute_crc(CRC_14443_B, data, (size_t)dlen, &b1, &b2);
310 uint16_t crcBB_1 = (uint16_t)(b1 << 8 | b2);
311 uint16_t bbb = Crc16ex(CRC_14443_B, data, (size_t)dlen);
312 PrintAndLogEx(INFO, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb);
315 // Test of CRC16, '123456789' string.
318 PrintAndLogEx(INFO, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n");
319 uint8_t dataStr[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 };
320 legic8 = CRC8Legic(dataStr, sizeof(dataStr)) & 0xFF;
322 //these below has been tested OK.
323 PrintAndLogEx(INFO, "Confirmed CRC Implementations");
324 PrintAndLogEx(INFO, "-------------------------------------\n");
325 PrintAndLogEx(INFO, "CRC 8 based\n\n");
326 PrintAndLogEx(INFO, "LEGIC: CRC8 : %X (C6 expected)", legic8);
327 PrintAndLogEx(INFO, "MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr)));
328 PrintAndLogEx(INFO, "-------------------------------------\n");
329 PrintAndLogEx(INFO, "CRC16 based\n\n");
331 // input from commandline
332 PrintAndLogEx(INFO, "CCITT | %X (29B1 expected)", Crc16ex(CRC_CCITT, dataStr, sizeof(dataStr)));
334 uint8_t poll[] = {0xb2, 0x4d, 0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
335 PrintAndLogEx(INFO, "FeliCa | %04X (B37F expected)", Crc16ex(CRC_FELICA, poll + 2, sizeof(poll) - 4));
336 PrintAndLogEx(INFO, "FeliCa | %04X (0000 expected)", Crc16ex(CRC_FELICA, poll + 2, sizeof(poll) - 2));
338 uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01};
339 PrintAndLogEx(INFO, "iCLASS | %04x (0143 expected)", Crc16ex(CRC_ICLASS, sel_corr, sizeof(sel_corr) - 2));
340 PrintAndLogEx(INFO, "---------------------------------------------------------------\n\n\n");
342 // ISO14443 crc A
343 compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2);
344 uint16_t crcAA = (uint16_t)(b1 << 8 | b2);
345 PrintAndLogEx(INFO, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, Crc16ex(CRC_14443_A, dataStr, sizeof(dataStr)));
347 // ISO14443 crc B
348 compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2);
349 uint16_t crcBB = (uint16_t)(b1 << 8 | b2);
350 PrintAndLogEx(INFO, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, Crc16ex(CRC_14443_B, dataStr, sizeof(dataStr)));
352 // ISO15693 crc (x.25)
353 compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2);
354 uint16_t crcCC = (uint16_t)(b1 << 8 | b2);
355 PrintAndLogEx(INFO, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, Crc16ex(CRC_15693, dataStr, sizeof(dataStr)));
357 // ICLASS
358 compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2);
359 uint16_t crcDD = (uint16_t)(b1 << 8 | b2);
360 PrintAndLogEx(INFO, "ICLASS crc | %04x or %04x\n", crcDD, Crc16ex(CRC_ICLASS, dataStr, sizeof(dataStr)));
362 // FeliCa
363 compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2);
364 uint16_t crcEE = (uint16_t)(b1 << 8 | b2);
365 PrintAndLogEx(INFO, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, Crc16ex(CRC_FELICA, dataStr, sizeof(dataStr)));
368 uint32_t crc32 = 0;
369 crc32_ex(dataStr, sizeof(dataStr), (uint8_t *)&crc32);
370 PrintAndLogEx(INFO, "CRC32 (desfire) | %08x ( expected)", crc32);
371 PrintAndLogEx(INFO, "---------------------------------------------------------------\n\n\n");
373 return PM3_SUCCESS;
376 static int CmdAnalyseCHKSUM(const char *Cmd) {
378 CLIParserContext *ctx;
379 CLIParserInit(&ctx, "analyse chksum",
380 "The bytes will be added with eachother and than limited with the applied mask\n"
381 "Finally compute ones' complement of the least significant bytes.",
382 "analyse chksum -d 137AF00A0A0D -> expected output: 0x61\n"
383 "analyse chksum -d 137AF00A0A0D -m FF"
386 void *argtable[] = {
387 arg_param_begin,
388 arg_str1("d", "data", "<hex>", "bytes to calc checksum"),
389 arg_str0("m", "mask", "<hex>", "bit mask to limit the output (4 hex bytes max)"),
390 arg_lit0("v", "verbose", "verbose"),
391 arg_param_end
393 CLIExecWithReturn(ctx, Cmd, argtable, true);
394 int dlen = 0;
395 uint8_t data[100] = {0x00};
396 memset(data, 0x0, sizeof(data));
397 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen);
398 if (res) {
399 CLIParserFree(ctx);
400 PrintAndLogEx(FAILED, "Error parsing bytes");
401 return PM3_EINVARG;
403 const char *m = arg_get_str(ctx, 2)->sval[0];
404 bool verbose = arg_get_lit(ctx, 3);
405 CLIParserFree(ctx);
407 size_t mlen = 0;
408 if (m)
409 mlen = strlen(m);
411 if (mlen > 8) {
412 PrintAndLogEx(FAILED, "Mask value is max 4 hex bytes");
413 return PM3_EINVARG;
416 uint16_t mask = 0;
417 if (mlen == 0) {
418 mask = 0xFFFF;
419 } else {
420 for (size_t i = 0; i < mlen; i++) {
421 char c = m[i];
422 // capitalize
423 if (c >= 'a' && c <= 'f')
424 c -= 32;
425 // convert to numeric value
426 if (c >= '0' && c <= '9')
427 c -= '0';
428 else if (c >= 'A' && c <= 'F')
429 c -= 'A' - 10;
430 else
431 continue;
433 mask <<= 4;
434 mask |= (uint8_t)c;
438 PrintAndLogEx(INFO, "Mask value 0x%x", mask);
440 if (verbose) {
441 PrintAndLogEx(INFO, "------------------+-------------+------------------+-----------------+------------------+-----------+-------------");
442 PrintAndLogEx(INFO, " add | sub | add 1's compl | sub 1's compl | xor | |");
443 PrintAndLogEx(INFO, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD | 0xFF - (n^n)");
444 PrintAndLogEx(INFO, "------------------+-------------+------------------+-----------------+------------------+-----------+-------------");
446 PrintAndLogEx(INFO, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X\n",
447 calcSumByteAdd(data, (uint8_t)dlen, mask)
448 , calcSumNibbleAdd(data, (uint8_t)dlen, mask)
449 , calcSumCrumbAdd(data, (uint8_t)dlen, mask)
450 , calcSumByteSub(data, (uint8_t)dlen, mask)
451 , calcSumNibbleSub(data, (uint8_t)dlen, mask)
452 , calcSumByteAddOnes(data, (uint8_t)dlen, mask)
453 , calcSumNibbleAddOnes(data, (uint8_t)dlen, mask)
454 , calcSumCrumbAddOnes(data, (uint8_t)dlen, mask)
455 , calcSumByteSubOnes(data, (uint8_t)dlen, mask)
456 , calcSumNibbleSubOnes(data, (uint8_t)dlen, mask)
457 , calcSumByteXor(data, (uint8_t)dlen, mask)
458 , calcSumNibbleXor(data, (uint8_t)dlen, mask)
459 , calcSumCrumbXor(data, (uint8_t)dlen, mask)
460 , calcBSDchecksum8(data, (uint8_t)dlen, mask)
461 , calcBSDchecksum4(data, (uint8_t)dlen, mask)
462 , calcXORchecksum(data, (uint8_t)dlen, mask)
464 return PM3_SUCCESS;
467 static int CmdAnalyseDates(const char *Cmd) {
468 CLIParserContext *ctx;
469 CLIParserInit(&ctx, "analyse dates",
470 "Tool to look for date/time stamps in a given array of bytes",
471 "analyse dates"
474 void *argtable[] = {
475 arg_param_begin,
476 arg_param_end
478 CLIExecWithReturn(ctx, Cmd, argtable, true);
479 CLIParserFree(ctx);
480 PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!");
481 return PM3_SUCCESS;
484 static int CmdAnalyseTEASelfTest(const char *Cmd) {
485 CLIParserContext *ctx;
486 CLIParserInit(&ctx, "analyse tea",
487 "Crypto TEA self tests",
488 "analyse tea -d 1122334455667788"
491 void *argtable[] = {
492 arg_param_begin,
493 arg_str1("d", "data", "<hex>", "bytes to encrypt ( 8 hex bytes )"),
494 arg_param_end
496 CLIExecWithReturn(ctx, Cmd, argtable, true);
497 int dlen = 0;
498 uint8_t data[8] = {0x00};
499 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen);
500 CLIParserFree(ctx);
501 if (res) {
502 PrintAndLogEx(FAILED, "Error parsing bytes");
503 return PM3_EINVARG;
506 uint8_t v_le[8];
507 memset(v_le, 0x00, sizeof(v_le));
508 uint8_t *v_ptr = v_le;
510 SwapEndian64ex(data, 8, 4, v_ptr);
512 // ENCRYPTION KEY:
513 uint8_t key[16] = {0x55, 0xFE, 0xF6, 0x30, 0x62, 0xBF, 0x0B, 0xC1, 0xC9, 0xB3, 0x7C, 0x34, 0x97, 0x3E, 0x29, 0xFB };
514 uint8_t keyle[16];
515 uint8_t *key_ptr = keyle;
516 SwapEndian64ex(key, sizeof(key), 4, key_ptr);
518 PrintAndLogEx(INFO, "TEA crypto testing");
519 PrintAndLogEx(INFO, "-----------------------------------+---------");
520 PrintAndLogEx(INFO, "LE enc.... %s", sprint_hex_ascii(v_ptr, 8));
522 tea_decrypt(v_ptr, key_ptr);
523 PrintAndLogEx(INFO, "LE dec.... %s", sprint_hex_ascii(v_ptr, 8));
525 tea_encrypt(v_ptr, key_ptr);
526 PrintAndLogEx(INFO, "enc1...... %s", sprint_hex_ascii(v_ptr, 8));
527 tea_encrypt(v_ptr, key_ptr);
528 PrintAndLogEx(INFO, "enc2...... %s", sprint_hex_ascii(v_ptr, 8));
529 PrintAndLogEx(NORMAL, "");
530 return PM3_SUCCESS;
533 static int CmdAnalyseA(const char *Cmd) {
534 CLIParserContext *ctx;
535 CLIParserInit(&ctx, "analyse a",
536 "Iceman's personal garbage test command",
537 "analyse a -d 137AF00A0A0D"
540 void *argtable[] = {
541 arg_param_begin,
542 arg_str1("d", "data", "<hex>", "bytes to manipulate"),
543 arg_param_end
545 CLIExecWithReturn(ctx, Cmd, argtable, true);
546 int dlen = 0;
547 uint8_t data[100] = {0x00};
548 memset(data, 0x0, sizeof(data));
549 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen);
550 if (res) {
551 CLIParserFree(ctx);
552 PrintAndLogEx(FAILED, "Error parsing bytes");
553 return PM3_EINVARG;
556 uint64_t key = 0;
557 res = mfc_algo_touch_one(data, 0, 0, &key);
558 if (res == PM3_SUCCESS) {
559 PrintAndLogEx(SUCCESS, "KEY A | %012" PRIx64, key);
562 CLIParserFree(ctx);
563 return PM3_SUCCESS;
566 //uint8_t syncBit = 99;
567 // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
568 // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
569 // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern
570 // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
571 # define SYNC_16BIT 0xB24D
572 uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16);
573 uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16);
574 uint8_t byte_offset = 99;
575 // reverse byte
576 uint8_t rev = reflect8(bt);
577 PrintAndLogEx(INFO, "input %02x | %02x \n", bt, rev);
578 // add byte to shift register
579 shiftReg = shiftReg << 8 | rev;
581 PrintAndLogEx(INFO, "shiftreg after %08x | pattern %08x \n", shiftReg, SYNC_16BIT);
583 uint8_t n0 = 0, n1 = 0;
585 n0 = (rev & (uint8_t)(~(0xFF >> (8 - 4)))) >> 4;
586 n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4)));
588 PrintAndLogEx(INFO, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1));
591 for (int i = 0; i < 16; i++) {
592 PrintAndLogEx(INFO, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, ((shiftReg >> i) & 0xFFFF));
594 // kolla om SYNC_PATTERN finns.
595 if (((shiftReg >> 7) & 0xFFFF) == SYNC_16BIT) byte_offset = 7;
596 else if (((shiftReg >> 6) & 0xFFFF) == SYNC_16BIT) byte_offset = 6;
597 else if (((shiftReg >> 5) & 0xFFFF) == SYNC_16BIT) byte_offset = 5;
598 else if (((shiftReg >> 4) & 0xFFFF) == SYNC_16BIT) byte_offset = 4;
599 else if (((shiftReg >> 3) & 0xFFFF) == SYNC_16BIT) byte_offset = 3;
600 else if (((shiftReg >> 2) & 0xFFFF) == SYNC_16BIT) byte_offset = 2;
601 else if (((shiftReg >> 1) & 0xFFFF) == SYNC_16BIT) byte_offset = 1;
602 else if (((shiftReg >> 0) & 0xFFFF) == SYNC_16BIT) byte_offset = 0;
604 PrintAndLogEx(INFO, "Offset %u \n", byte_offset);
605 if (byte_offset != 99)
606 break;
608 shiftReg >>= 1;
611 uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset)));
612 PrintAndLogEx(INFO, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1));
617 pm3 --> da hex2bin 4db2 0100110110110010
619 //return PM3_SUCCESS;
621 // split byte into two parts.
622 uint8_t offset = 3, n0 = 0, n1 = 0;
623 rev = 0xB2;
624 for (uint8_t m=0; m<8; m++) {
625 offset = m;
626 n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset;
627 n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset)));
629 PrintAndLogEx(INFO, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) );
630 n0 = 0, n1 = 0;
631 // PrintAndLogEx(INFO, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) );
632 //PrintAndLogEx(INFO, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) );
633 //PrintAndLogEx(INFO, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) ));
635 return PM3_SUCCESS;
636 // from A -- x bits into B and the rest into C.
638 for ( uint8_t i=0; i<8; i++){
639 PrintAndLogEx(INFO, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) );
640 b = a & (a & (0xFF >> (8-i)));
641 a >>=1;
645 // return PM3_SUCCESS;
648 // 14443-A
649 uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc
650 uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc
651 PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES" : "NO");
652 PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES" : "NO");
654 // 14443-B
655 uint8_t u14b[] = {0x05, 0x00, 0x08, 0x39, 0x73};
656 PrintAndLogEx(INFO, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES" : "NO");
658 // 15693 test
659 uint8_t u15_c[] = {0x05, 0x00, 0x08, 0x39, 0x73}; // correct
660 uint8_t u15_w[] = {0x05, 0x00, 0x08, 0x39, 0x72}; // wrong
661 PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES" : "NO");
662 PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES" : "NO");
664 // iCLASS test - wrong crc , swapped bytes.
665 uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43};
666 uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01};
667 PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES" : "NO");
668 PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES" : "NO");
670 // FeliCa test
671 uint8_t felica_w[] = {0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7e};
672 uint8_t felica_c[] = {0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
673 PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES" : "NO");
674 PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES" : "NO");
676 PrintAndLogEx(NORMAL, "\n");
678 return PM3_SUCCESS;
681 //piwi
682 // uid(2e086b1a) nt(230736f6) ks(0b0008000804000e) nr(000000000)
683 // uid(2e086b1a) nt(230736f6) ks(0e0b0e0b090c0d02) nr(000000001)
684 // uid(2e086b1a) nt(230736f6) ks(0e05060e01080b08) nr(000000002)
685 //uint64_t d1[] = {0x2e086b1a, 0x230736f6, 0x0000001, 0x0e0b0e0b090c0d02};
686 //uint64_t d2[] = {0x2e086b1a, 0x230736f6, 0x0000002, 0x0e05060e01080b08};
688 // uid(17758822) nt(c0c69e59) ks(080105020705040e) nr(00000001)
689 // uid(17758822) nt(c0c69e59) ks(01070a05050c0705) nr(00000002)
690 //uint64_t d1[] = {0x17758822, 0xc0c69e59, 0x0000001, 0x080105020705040e};
691 //uint64_t d2[] = {0x17758822, 0xc0c69e59, 0x0000002, 0x01070a05050c0705};
693 // uid(6e442129) nt(8f699195) ks(090d0b0305020f02) nr(00000001)
694 // uid(6e442129) nt(8f699195) ks(03030508030b0c0e) nr(00000002)
695 // uid(6e442129) nt(8f699195) ks(02010f030c0d050d) nr(00000003)
696 // uid(6e442129) nt(8f699195) ks(00040f0f0305030e) nr(00000004)
697 //uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02};
698 //uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e};
701 uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001)
702 uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)
705 uint64_t *keylistA = NULL, *keylistB = NULL;
706 uint32_t keycountA = 0, keycountB = 0;
707 // uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800};
708 // uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f};
709 uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
710 uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
712 keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4], &keylistA);
713 keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB);
715 switch (keycountA) {
716 case 0:
717 PrintAndLogEx(FAILED, "Key test A failed\n");
718 break;
719 case 1:
720 PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]);
721 break;
723 switch (keycountB) {
724 case 0:
725 PrintAndLogEx(FAILED, "Key test B failed\n");
726 break;
727 case 1:
728 PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]);
729 break;
732 free(keylistA);
733 free(keylistB);
735 // qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
736 // keycount = intersection(last_keylist, keylist);
739 uint64_t keys[] = {
740 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961,
741 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3,
742 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c,
743 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9,
744 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a,
745 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba,
746 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b,
747 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe
750 uint64_t keya[] = {
751 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961,
752 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3,
753 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c,
754 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9
756 uint64_t keyb[] = {
757 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a,
758 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba,
759 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b,
760 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe
766 uint64_t xor[] = {
767 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B,
768 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6,
769 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52,
770 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC, 0xB6E97F5F6776,
771 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F,
772 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD,
773 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8,
774 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244
778 uint64_t xorA[] = {
779 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B,
780 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6,
781 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52,
782 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC
784 uint64_t xorB[] = {
785 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F,
786 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD,
787 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8,
788 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244
792 // xor key A | xor key B
793 1 | 0DEFED88E531 | 2F87A1BDC230
794 2 | 7577AFA2E1BC | E43F502B984C
795 3 | 14D7D7BDBEC3 | 8A776AB752D9
796 4 | F5ABD3C6278B | 9A58D96A472F
797 5 | AABDFA08276F | EF3702E01916
798 6 | B77C275C10D6 | 48A03B01D007
799 7 | B6DD0B434080 | 14754B0D659E
800 8 | AAF2444499C6 | 009AD1868FDD
801 9 | 852D7F8EBF90 | 6082DB527C11
802 10 | 3108821DB92C | 4D666ADA4C0E
803 11 | B3756A1FB685 | 2D461D05F163
804 12 | DFE627C86A52 | 3596CFF0FEC8
805 13 | 5D3C093EF375 | 8CBD9258FE22
806 14 | 28C81D6FBF0E | 00D29A7B304B
807 15 | 1204DF4D3ECC | BC33DC6C9244
810 // generate xor table :)
812 for (uint8_t i=0; i<31; i++){
813 uint64_t a = keys[i] ^ keys[i+1];
814 PrintAndLogEx(INFO, "%u | %012" PRIX64 " | \n", i, a);
819 uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16);
820 uint8_t uid[6] = {0};
821 num_to_bytes(id,4,uid);
823 uint8_t key_s0a[] = {
824 uid[1] ^ uid[2] ^ uid[3] ^ 0x11,
825 uid[1] ^ 0x72,
826 uid[2] ^ 0x80,
827 (uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19,
828 0xA3,
829 0x2F
832 PrintAndLogEx(INFO, "UID | %s\n", sprint_hex(uid,4 ));
833 PrintAndLogEx(INFO, "KEY A | %s\n", sprint_hex(key_s0a, 6));
835 // arrays w all keys
836 uint64_t foo[32] = {0};
839 foo[0] = bytes_to_num(key_s0a, 6);
841 //foo[16] = 0xcafe71411fbf;
842 foo[16] = 0xeafe51411fbf;
844 for (uint8_t i=0; i<15; i++){
845 foo[i+1] = foo[i] ^ xorA[i];
846 foo[i+16+1] = foo[i+16] ^ xorB[i];
849 for (uint8_t i=0; i<15; i++){
850 uint64_t a = foo[i];
851 uint64_t b = foo[i+16];
853 PrintAndLogEx(INFO, "%02u | %012" PRIX64 " %s | %012" PRIX64 " %s\n",
856 ( a == keya[i])?"ok":"err",
858 ( b == keyb[i])?"ok":"err"
862 // return PM3_SUCCESS;
865 static int CmdAnalyseNuid(const char *Cmd) {
866 CLIParserContext *ctx;
867 CLIParserInit(&ctx, "analyse nuid",
868 "Generate 4byte NUID from 7byte UID",
869 "analyse nuid -d 11223344556677"
872 void *argtable[] = {
873 arg_param_begin,
874 arg_str0("d", "data", "<hex>", "bytes to send"),
875 arg_lit0("t", "test", "self test"),
876 arg_param_end
878 CLIExecWithReturn(ctx, Cmd, argtable, true);
880 int uidlen = 0;
881 uint8_t uid[7] = {0};
882 int res = CLIParamHexToBuf(arg_get_str(ctx, 1), uid, sizeof(uid), &uidlen);
883 bool selftest = arg_get_lit(ctx, 2);
884 CLIParserFree(ctx);
886 if (res) {
887 PrintAndLogEx(FAILED, "Error parsing bytes");
888 return PM3_EINVARG;
891 uint8_t nuid[4] = {0};
893 /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */
894 /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */
895 /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */
896 if (selftest) {
897 uint8_t uid_test1[] = {0x04, 0x0d, 0x68, 0x1a, 0xb5, 0x22, 0x81};
898 uint8_t nuid_test1[] = {0x8f, 0x43, 0x0f, 0xef};
899 uint8_t uid_test2[] = {0x04, 0x18, 0x3f, 0x09, 0x32, 0x1b, 0x85};
900 uint8_t nuid_test2[] = {0x4f, 0x50, 0x5d, 0x7d};
901 memcpy(uid, uid_test1, sizeof(uid));
902 mfc_generate4b_nuid(uid, nuid);
904 PrintAndLogEx(INFO, "Self tests");
905 bool test1 = (0 == memcmp(nuid, nuid_test1, sizeof(nuid)));
906 PrintAndLogEx((test1) ? SUCCESS : FAILED, "1. %s -> %s ( %s )"
907 , sprint_hex_inrow(uid_test1, sizeof(uid_test1))
908 , sprint_hex(nuid, sizeof(nuid))
909 , test1 ? _GREEN_("ok") : _RED_("fail")
912 memcpy(uid, uid_test2, sizeof(uid));
913 mfc_generate4b_nuid(uid, nuid);
914 bool test2 = (0 == memcmp(nuid, nuid_test2, sizeof(nuid)));
915 PrintAndLogEx((test2) ? SUCCESS : FAILED, "2. %s -> %s ( %s )\n"
916 , sprint_hex_inrow(uid_test2, sizeof(uid_test2))
917 , sprint_hex(nuid, sizeof(nuid))
918 , test2 ? _GREEN_("ok") : _RED_("fail")
921 return PM3_SUCCESS;
924 if (uidlen != 7) {
925 PrintAndLogEx(FAILED, "Error parsing bytes");
926 return PM3_EINVARG;
929 mfc_generate4b_nuid(uid, nuid);
931 PrintAndLogEx(INFO, "UID | %s \n", sprint_hex(uid, 7));
932 PrintAndLogEx(INFO, "NUID | %s \n", sprint_hex(nuid, 4));
933 return PM3_SUCCESS;
936 static int CmdAnalyseDemodBuffer(const char *Cmd) {
937 CLIParserContext *ctx;
938 CLIParserInit(&ctx, "analyse demodbuff",
939 "loads a binary string into demod buffer",
940 "analyse demodbuff -d 0011101001001011"
943 void *argtable[] = {
944 arg_param_begin,
945 arg_str1("d", "data", "<bin>", "binary string to load"),
946 arg_param_end
948 CLIExecWithReturn(ctx, Cmd, argtable, true);
949 const char *s = arg_get_str(ctx, 1)->sval[0];
950 size_t len = MIN(strlen(s), MAX_DEMOD_BUF_LEN);
952 // add 1 for null terminator.
953 uint8_t *data = calloc(len + 1, sizeof(uint8_t));
954 if (data == NULL) {
955 CLIParserFree(ctx);
956 return PM3_EMALLOC;
959 for (size_t i = 0; i <= strlen(s); i++) {
960 char c = s[i];
961 if (c == '1')
962 DemodBuffer[i] = 1;
963 if (c == '0')
964 DemodBuffer[i] = 0;
966 PrintAndLogEx(NORMAL, "%c" NOLF, c);
969 CLIParserFree(ctx);
971 PrintAndLogEx(NORMAL, "");
972 DemodBufferLen = len;
973 free(data);
974 PrintAndLogEx(HINT, "Use `" _YELLOW_("data print") "` to view demod buffer");
975 return PM3_SUCCESS;
978 static int CmdAnalyseFreq(const char *Cmd) {
979 CLIParserContext *ctx;
980 CLIParserInit(&ctx, "analyse freq",
981 "calc wave lengths",
982 "analyse freq"
985 void *argtable[] = {
986 arg_param_begin,
987 arg_param_end
989 CLIExecWithReturn(ctx, Cmd, argtable, true);
990 CLIParserFree(ctx);
992 const double c = 299792458;
993 double len_125 = c / 125000;
994 double len_134 = c / 134000;
995 double len_1356 = c / 13560000;
997 double rf_range_125 = len_125 / (M_PI * 2);
998 double rf_range_134 = len_134 / (M_PI * 2);
999 double rf_range_1356 = len_1356 / (M_PI * 2);
1001 PrintAndLogEx(INFO, "Wavelengths");
1002 PrintAndLogEx(INFO, " 125 kHz has %f m, rf range %f m", len_125, rf_range_125);
1003 PrintAndLogEx(INFO, " 134 kHz has %f m, rf range %f m", len_134, rf_range_134);
1004 PrintAndLogEx(INFO, " 13.56 mHz has %f m, rf range %f m", len_1356, rf_range_1356);
1005 return PM3_SUCCESS;
1008 static int CmdAnalyseFoo(const char *Cmd) {
1010 CLIParserContext *ctx;
1011 CLIParserInit(&ctx, "analyse foo",
1012 "experiments of cliparse",
1013 "analyse foo -r a0000000a0002021"
1016 void *argtable[] = {
1017 arg_param_begin,
1018 arg_strx0("r", "raw", "<hex>", "raw bytes (strx)"),
1019 arg_param_end
1021 CLIExecWithReturn(ctx, Cmd, argtable, false);
1023 // raw param
1024 int datalen = 256;
1025 uint8_t data[256];
1026 CLIGetHexWithReturn(ctx, 1, data, &datalen);
1028 int data3len = 512;
1029 uint8_t data3[512];
1030 CLIGetStrWithReturn(ctx, 1, data3, &data3len);
1032 CLIParserFree(ctx);
1034 PrintAndLogEx(INFO, "-r");
1035 PrintAndLogEx(INFO, "Got: %s", sprint_hex_inrow(data, (size_t)datalen));
1036 PrintAndLogEx(INFO, "Got: %s", data3);
1038 ClearGraph(false);
1039 GraphTraceLen = 15000;
1041 for (int i = 0; i < 4095; i++) {
1042 int o = 0;
1044 // 0010 0000
1045 if (i & 0x2000) o |= 0x80; // corr_i_accum[13]
1046 // 0001 1100
1047 if (i & 0x1C00) o |= 0x40; // corr_i_accum[12] | corr_i_accum[11] | corr_i_accum[10]
1048 // 0000 1110
1049 if (i & 0x0E00) o |= 0x20; // corr_i_accum[12] | corr_i_accum[11] | corr_i_accum[9],
1050 o |= (i & 0x1F0) >> 4; // corr_i_accum[8:4]
1052 GraphBuffer[i] = o;
1055 for (int i = 0; i < 4095; i++) {
1056 int o = 0;
1058 // Send 8 bits of in phase tag signal
1059 //if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111)
1060 if ((i & 0x3800) == 0 || (i & 0x3800) == 0x3800) {
1061 o |= (i & 0xFF0) >> 4; // corr_i_out <= corr_i_accum[11:4];
1062 } else {
1063 // truncate to maximum value
1064 //if (corr_i_accum[13] == 1'b0)
1065 if ((i & 0x2000) == 0) {
1066 o |= 0x7f; // corr_i_out <= 8'b01111111;
1069 GraphBuffer[i + 5000] = o;
1072 for (int i = 0; i < 4095; i++) {
1073 int o = i >> 5;
1074 GraphBuffer[i + 10000] = o;
1077 RepaintGraphWindow();
1078 ShowGraphWindow();
1079 return PM3_SUCCESS;
1082 static int CmdAnalyseUnits(const char *Cmd) {
1084 CLIParserContext *ctx;
1085 CLIParserInit(&ctx, "analyse units",
1086 "experiments of unit conversions found in HF. ETU (1/13.56mhz), US or SSP_CLK (1/3.39MHz)",
1087 "analyse uints --etu 10"
1088 "analyse uints --us 100"
1091 void *argtable[] = {
1092 arg_param_begin,
1093 arg_int0(NULL, "etu", "<dec>", "number in ETU"),
1094 arg_int0(NULL, "us", "<dec>", "number in micro seconds (us)"),
1095 arg_param_end
1097 CLIExecWithReturn(ctx, Cmd, argtable, false);
1099 int etu = arg_get_int_def(ctx, 1, -1);
1100 int us = arg_get_int_def(ctx, 2, -1);
1101 CLIParserFree(ctx);
1103 if (etu == -1 && us == -1) {
1104 PrintAndLogEx(INFO, "US to ETU conversions");
1105 PrintAndLogEx(INFO, " 9 US = %u ETU (expect 1) " _GREEN_("ok"), US_TO_ETU(9));
1106 PrintAndLogEx(INFO, " 10 US = %u ETU (expect 1) " _GREEN_("ok"), US_TO_ETU(10));
1107 PrintAndLogEx(INFO, " 94 US = %u ETU (expect 10) " _GREEN_("ok"), US_TO_ETU(94));
1108 PrintAndLogEx(INFO, " 95 US = %u ETU (expect 10) " _GREEN_("ok"), US_TO_ETU(95));
1109 PrintAndLogEx(INFO, " 302 US = %u ETU (expect 32) " _GREEN_("ok"), US_TO_ETU(302));
1110 PrintAndLogEx(NORMAL, "");
1112 PrintAndLogEx(INFO, "ETU to US conversions");
1113 PrintAndLogEx(INFO, " 1 ETU = %u US (expect 9.43) " _GREEN_("ok"), ETU_TO_US(1));
1114 PrintAndLogEx(INFO, " 10 ETU = %u US (expect 94.39) " _GREEN_("ok"), ETU_TO_US(10));
1115 PrintAndLogEx(INFO, " 32 ETU = %u US (expect 302) " _GREEN_("ok"), ETU_TO_US(32));
1116 PrintAndLogEx(NORMAL, "");
1118 PrintAndLogEx(INFO, "US to SSP CLK 3.39MHz conversions");
1119 PrintAndLogEx(INFO, " 9 US = %u SSP (expect 32) ", US_TO_SSP(9));
1120 PrintAndLogEx(INFO, " 10 US = %u SSP (expect 32 or 48) ", US_TO_SSP(10));
1121 PrintAndLogEx(INFO, " 94 US = %u SSP (expect 320) ", US_TO_SSP(94));
1122 PrintAndLogEx(INFO, " 95 US = %u SSP (expect 320 or 336) ", US_TO_SSP(95));
1123 PrintAndLogEx(INFO, " 302 US = %u SSP (expect 1024) ", US_TO_SSP(302));
1125 PrintAndLogEx(INFO, " 4949000 US = %u SSP ", US_TO_SSP(4949000));
1127 PrintAndLogEx(NORMAL, "");
1129 PrintAndLogEx(INFO, "SSP CLK 3.39MHz to US conversions");
1130 PrintAndLogEx(INFO, " 32 SSP = %u US (expext 9 or 10) " _GREEN_("ok"), SSP_TO_US(32));
1131 PrintAndLogEx(INFO, " 320 SSP = %u US (expext 94 or 95) " _GREEN_("ok"), SSP_TO_US(320));
1132 PrintAndLogEx(INFO, "1024 SSP = %u US (expext 302) " _GREEN_("ok"), SSP_TO_US(1024));
1133 PrintAndLogEx(NORMAL, "");
1135 PrintAndLogEx(INFO, "ETU to SSP CLK 3.39MHz conversions");
1136 PrintAndLogEx(INFO, " 1 ETU = %u SSP (expect 32) " _GREEN_("ok"), ETU_TO_SSP(1));
1137 PrintAndLogEx(INFO, " 10 ETU = %u SSP (expect 320) " _GREEN_("ok"), ETU_TO_SSP(10));
1138 PrintAndLogEx(INFO, " 32 ETU = %u SSP (expect 1024) " _GREEN_("ok"), ETU_TO_SSP(32));
1139 PrintAndLogEx(NORMAL, "");
1141 PrintAndLogEx(INFO, "SSP CLK 3.39MHz to ETU conversions");
1142 PrintAndLogEx(INFO, "1024 SSP = %u ETU (expect 32) " _GREEN_("ok"), SSP_TO_ETU(1024));
1143 PrintAndLogEx(INFO, " 320 SSP = %u ETU (expect 10) " _GREEN_("ok"), SSP_TO_ETU(320));
1144 PrintAndLogEx(INFO, " 32 SSP = %u ETU (expect 1) " _GREEN_("ok"), SSP_TO_ETU(32));
1145 } else if (etu) {
1147 PrintAndLogEx(INFO, " %d ETU = %u us ", ETU_TO_US(etu));
1148 PrintAndLogEx(INFO, " %d ETU = %u SSP ", ETU_TO_SSP(etu));
1149 } else if (us) {
1150 PrintAndLogEx(INFO, " %d us = %u ETU ", US_TO_ETU(us));
1151 PrintAndLogEx(INFO, " %d us = %u SSP ", US_TO_SSP(us));
1154 return PM3_SUCCESS;
1157 static command_t CommandTable[] = {
1158 {"help", CmdHelp, AlwaysAvailable, "This help"},
1159 {"lcr", CmdAnalyseLCR, AlwaysAvailable, "Generate final byte for XOR LRC"},
1160 {"crc", CmdAnalyseCRC, AlwaysAvailable, "Stub method for CRC evaluations"},
1161 {"chksum", CmdAnalyseCHKSUM, AlwaysAvailable, "Checksum with adding, masking and one's complement"},
1162 {"dates", CmdAnalyseDates, AlwaysAvailable, "Look for datestamps in a given array of bytes"},
1163 {"tea", CmdAnalyseTEASelfTest, AlwaysAvailable, "Crypto TEA test"},
1164 {"lfsr", CmdAnalyseLfsr, AlwaysAvailable, "LFSR tests"},
1165 {"a", CmdAnalyseA, AlwaysAvailable, "num bits test"},
1166 {"nuid", CmdAnalyseNuid, AlwaysAvailable, "create NUID from 7byte UID"},
1167 {"demodbuff", CmdAnalyseDemodBuffer, AlwaysAvailable, "Load binary string to demodbuffer"},
1168 {"freq", CmdAnalyseFreq, AlwaysAvailable, "Calc wave lengths"},
1169 {"foo", CmdAnalyseFoo, AlwaysAvailable, "muxer"},
1170 {"units", CmdAnalyseUnits, AlwaysAvailable, "convert ETU <> US <> SSP_CLK (3.39MHz)"},
1171 {NULL, NULL, NULL, NULL}
1174 static int CmdHelp(const char *Cmd) {
1175 (void)Cmd; // Cmd is not used so far
1176 CmdsHelp(CommandTable);
1177 return 0;
1180 int CmdAnalyse(const char *Cmd) {
1181 clearCommandBuffer();
1182 return CmdsParse(CommandTable, Cmd);