1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2016 iceman
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
7 //-----------------------------------------------------------------------------
8 // Analyse bytes commands
9 //-----------------------------------------------------------------------------
10 #include "cmdanalyse.h"
12 #include <stdlib.h> // size_t
14 #include <ctype.h> // tolower
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
22 #include "crc16.h" // crc16 ccitt
23 #include "crc32.h" // crc32_ex
25 #include "legic_prng.h"
26 #include "cmddata.h" // demodbuffer
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
) {
37 for (uint8_t i
= 0; i
< len
; i
++)
42 static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){
55 static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){
59 static uint16_t calcSumCrumbAdd(uint8_t *bytes
, uint8_t len
, uint32_t mask
) {
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);
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
) {
75 for (uint8_t i
= 0; i
< len
; i
++) {
76 sum
+= NIBBLE_LOW(bytes
[i
]);
77 sum
+= NIBBLE_HIGH(bytes
[i
]);
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
) {
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);
94 return (sum
& 0xFFFF);
96 static uint16_t calcSumNibbleXor(uint8_t *bytes
, uint8_t len
, uint32_t mask
) {
98 for (uint8_t i
= 0; i
< len
; i
++) {
99 sum
^= NIBBLE_LOW(bytes
[i
]);
100 sum
^= NIBBLE_HIGH(bytes
[i
]);
103 return (sum
& 0xFFFF);
105 static uint16_t calcSumByteXor(uint8_t *bytes
, uint8_t len
, uint32_t mask
) {
107 for (uint8_t i
= 0; i
< len
; i
++) {
111 return (sum
& 0xFFFF);
113 static uint16_t calcSumByteAdd(uint8_t *bytes
, uint8_t len
, uint32_t mask
) {
115 for (uint8_t i
= 0; i
< len
; i
++) {
119 return (sum
& 0xFFFF);
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
) {
128 for (uint8_t i
= 0; i
< len
; i
++) {
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
) {
139 for (uint8_t i
= 0; i
< len
; i
++) {
140 sum
-= NIBBLE_LOW(bytes
[i
]);
141 sum
-= NIBBLE_HIGH(bytes
[i
]);
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
) {
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
159 return (sum
& 0xFFFF);
161 // BSD shift checksum 4bit version
162 static uint16_t calcBSDchecksum4(uint8_t *bytes
, uint8_t len
, uint32_t mask
) {
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
168 sum
= ((sum
& 0xF) >> 1) | ((sum
& 0x1) << 3); // rotate accumulator
169 sum
+= NIBBLE_LOW(bytes
[i
]); // add low nibble
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"
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)"),
198 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
200 uint8_t idata
[1] = {0};
201 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), idata
, sizeof(idata
), &iv_len
);
205 PrintAndLogEx(FAILED
, "Error parsing IV byte");
210 uint8_t fdata
[1] = {0};
211 res
= CLIParamHexToBuf(arg_get_str(ctx
, 2), fdata
, sizeof(fdata
), &f_len
);
215 PrintAndLogEx(FAILED
, "Error parsing FIND byte");
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) {
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
, "----+------+-------+--------------");
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"
248 arg_str1("d", "data", "<hex>", "bytes to calc missing XOR in a LCR"),
251 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
253 uint8_t data
[100] = {0x00};
254 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), data
, sizeof(data
), &dlen
);
258 PrintAndLogEx(FAILED
, "Error parsing bytes");
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
, "");
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"
278 arg_str1("d", "data", "<hex>", "bytes to calc crc"),
281 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
283 uint8_t data
[1024] = {0x00};
284 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), data
, sizeof(data
), &dlen
);
288 PrintAndLogEx(FAILED
, "Error parsing bytes");
292 PrintAndLogEx(INFO
, "\nTests with (%d) | %s", dlen
, sprint_hex(data
, (size_t)dlen
));
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));
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");
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
)));
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
)));
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
)));
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
)));
369 crc32_ex(dataStr
, sizeof(dataStr
), (uint8_t *)&crc32
);
370 PrintAndLogEx(INFO
, "CRC32 (desfire) | %08x ( expected)", crc32
);
371 PrintAndLogEx(INFO
, "---------------------------------------------------------------\n\n\n");
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"
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"),
393 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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
);
400 PrintAndLogEx(FAILED
, "Error parsing bytes");
403 const char *m
= arg_get_str(ctx
, 2)->sval
[0];
404 bool verbose
= arg_get_lit(ctx
, 3);
412 PrintAndLogEx(FAILED
, "Mask value is max 4 hex bytes");
420 for (size_t i
= 0; i
< mlen
; i
++) {
423 if (c
>= 'a' && c
<= 'f')
425 // convert to numeric value
426 if (c
>= '0' && c
<= '9')
428 else if (c
>= 'A' && c
<= 'F')
438 PrintAndLogEx(INFO
, "Mask value 0x%x", mask
);
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
)
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",
478 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
480 PrintAndLogEx(NORMAL
, "To be implemented. Feel free to contribute!");
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"
493 arg_str1("d", "data", "<hex>", "bytes to encrypt ( 8 hex bytes )"),
496 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
498 uint8_t data
[8] = {0x00};
499 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), data
, sizeof(data
), &dlen
);
502 PrintAndLogEx(FAILED
, "Error parsing bytes");
507 memset(v_le
, 0x00, sizeof(v_le
));
508 uint8_t *v_ptr
= v_le
;
510 SwapEndian64ex(data
, 8, 4, v_ptr
);
513 uint8_t key
[16] = {0x55, 0xFE, 0xF6, 0x30, 0x62, 0xBF, 0x0B, 0xC1, 0xC9, 0xB3, 0x7C, 0x34, 0x97, 0x3E, 0x29, 0xFB };
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
, "");
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"
542 arg_str1("d", "data", "<hex>", "bytes to manipulate"),
545 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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
);
552 PrintAndLogEx(FAILED
, "Error parsing bytes");
557 res
= mfc_algo_touch_one(data
, 0, 0, &key
);
558 if (res
== PM3_SUCCESS
) {
559 PrintAndLogEx(SUCCESS
, "KEY A | %012" PRIx64
, key
);
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;
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)
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;
624 for (uint8_t m=0; m<8; 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) );
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))) ));
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)));
645 // return PM3_SUCCESS;
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");
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");
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");
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");
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);
717 PrintAndLogEx(FAILED, "Key test A failed\n");
720 PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]);
725 PrintAndLogEx(FAILED, "Key test B failed\n");
728 PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]);
735 // qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
736 // keycount = intersection(last_keylist, keylist);
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
751 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961,
752 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3,
753 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c,
754 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9
757 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a,
758 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba,
759 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b,
760 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe
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
779 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B,
780 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6,
781 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52,
782 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC
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,
827 (uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19,
832 PrintAndLogEx(INFO, "UID | %s\n", sprint_hex(uid,4 ));
833 PrintAndLogEx(INFO, "KEY A | %s\n", sprint_hex(key_s0a, 6));
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++){
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"
874 arg_str0("d", "data", "<hex>", "bytes to send"),
875 arg_lit0("t", "test", "self test"),
878 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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);
887 PrintAndLogEx(FAILED
, "Error parsing bytes");
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 */
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")
925 PrintAndLogEx(FAILED
, "Error parsing bytes");
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));
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"
945 arg_str1("d", "data", "<bin>", "binary string to load"),
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));
959 for (size_t i
= 0; i
<= strlen(s
); i
++) {
966 PrintAndLogEx(NORMAL
, "%c" NOLF
, c
);
971 PrintAndLogEx(NORMAL
, "");
972 DemodBufferLen
= len
;
974 PrintAndLogEx(HINT
, "Use `" _YELLOW_("data print") "` to view demod buffer");
978 static int CmdAnalyseFreq(const char *Cmd
) {
979 CLIParserContext
*ctx
;
980 CLIParserInit(&ctx
, "analyse freq",
989 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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
);
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
[] = {
1018 arg_strx0("r", "raw", "<hex>", "raw bytes (strx)"),
1021 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1026 CLIGetHexWithReturn(ctx
, 1, data
, &datalen
);
1030 CLIGetStrWithReturn(ctx
, 1, data3
, &data3len
);
1034 PrintAndLogEx(INFO
, "-r");
1035 PrintAndLogEx(INFO
, "Got: %s", sprint_hex_inrow(data
, (size_t)datalen
));
1036 PrintAndLogEx(INFO
, "Got: %s", data3
);
1039 GraphTraceLen
= 15000;
1041 for (int i
= 0; i
< 4095; i
++) {
1045 if (i
& 0x2000) o
|= 0x80; // corr_i_accum[13]
1047 if (i
& 0x1C00) o
|= 0x40; // corr_i_accum[12] | corr_i_accum[11] | corr_i_accum[10]
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]
1055 for (int i
= 0; i
< 4095; i
++) {
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];
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
++) {
1074 GraphBuffer
[i
+ 10000] = o
;
1077 RepaintGraphWindow();
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
[] = {
1093 arg_int0(NULL
, "etu", "<dec>", "number in ETU"),
1094 arg_int0(NULL
, "us", "<dec>", "number in micro seconds (us)"),
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);
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));
1147 PrintAndLogEx(INFO
, " %d ETU = %u us ", ETU_TO_US(etu
));
1148 PrintAndLogEx(INFO
, " %d ETU = %u SSP ", ETU_TO_SSP(etu
));
1150 PrintAndLogEx(INFO
, " %d us = %u ETU ", US_TO_ETU(us
));
1151 PrintAndLogEx(INFO
, " %d us = %u SSP ", US_TO_SSP(us
));
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
);
1180 int CmdAnalyse(const char *Cmd
) {
1181 clearCommandBuffer();
1182 return CmdsParse(CommandTable
, Cmd
);