]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - client/cmdanalyse.c
FIX: 'LF PYRAMID' the crc8_MAXIM and crc16_DNP was calling the wrong crc method....
[proxmark3-svn] / client / cmdanalyse.c
... / ...
CommitLineData
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"
11#include "nonce2key/nonce2key.h"
12
13static int CmdHelp(const char *Cmd);
14
15int usage_analyse_lcr(void) {
16 PrintAndLog("Specifying the bytes of a UID with a known LRC will find the last byte value");
17 PrintAndLog("needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX.");
18 PrintAndLog("");
19 PrintAndLog("Usage: analyse lcr [h] <bytes>");
20 PrintAndLog("Options:");
21 PrintAndLog(" h This help");
22 PrintAndLog(" <bytes> bytes to calc missing XOR in a LCR");
23 PrintAndLog("");
24 PrintAndLog("Samples:");
25 PrintAndLog(" analyse lcr 04008064BA");
26 PrintAndLog("expected output: Target (BA) requires final LRC XOR byte value: 5A");
27 return 0;
28}
29
30int usage_analyse_checksum(void) {
31 PrintAndLog("The bytes will be added with eachother and than limited with the applied mask");
32 PrintAndLog("Finally compute ones' complement of the least significant bytes");
33 PrintAndLog("");
34 PrintAndLog("Usage: analyse chksum [h] b <bytes> m <mask>");
35 PrintAndLog("Options:");
36 PrintAndLog(" h This help");
37 PrintAndLog(" b <bytes> bytes to calc missing XOR in a LCR");
38 PrintAndLog(" m <mask> bit mask to limit the outpuyt");
39 PrintAndLog("");
40 PrintAndLog("Samples:");
41 PrintAndLog(" analyse chksum b 137AF00A0A0D m FF");
42 PrintAndLog("expected output: 0x61");
43 return 0;
44}
45
46int usage_analyse_crc(void){
47 PrintAndLog("A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output");
48 PrintAndLog("");
49 PrintAndLog("Usage: analyse crc [h] <bytes>");
50 PrintAndLog("Options:");
51 PrintAndLog(" h This help");
52 PrintAndLog(" <bytes> bytes to calc crc");
53 PrintAndLog("");
54 PrintAndLog("Samples:");
55 PrintAndLog(" analyse crc 137AF00A0A0D");
56 return 0;
57}
58
59static uint8_t calculateLRC( uint8_t* bytes, uint8_t len) {
60 uint8_t LRC = 0;
61 for (uint8_t i = 0; i < len; i++)
62 LRC ^= bytes[i];
63 return LRC;
64}
65
66static uint8_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
67 uint8_t sum = 0;
68 for (uint8_t i = 0; i < len; i++) {
69 sum += CRUMB(bytes[i], 0);
70 sum += CRUMB(bytes[i], 2);
71 sum += CRUMB(bytes[i], 4);
72 sum += CRUMB(bytes[i], 6);
73 }
74 sum &= mask;
75 return sum;
76}
77static uint8_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
78 return ~calcSumCrumbAdd(bytes, len, mask);
79}
80static uint8_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
81 uint8_t sum = 0;
82 for (uint8_t i = 0; i < len; i++) {
83 sum += NIBBLE_LOW(bytes[i]);
84 sum += NIBBLE_HIGH(bytes[i]);
85 }
86 sum &= mask;
87 return sum;
88}
89static uint8_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){
90 return ~calcSumNibbleAdd(bytes, len, mask);
91}
92
93static uint8_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
94 uint8_t sum = 0;
95 for (uint8_t i = 0; i < len; i++)
96 sum += bytes[i];
97 sum &= mask;
98 return sum;
99}
100// Ones complement
101static uint8_t calcSumByteAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
102 return ~calcSumByteAdd(bytes, len, mask);
103}
104
105static uint8_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
106 uint8_t sum = 0;
107 for (uint8_t i = 0; i < len; i++)
108 sum -= bytes[i];
109 sum &= mask;
110 return sum;
111}
112static uint8_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){
113 return ~calcSumByteSub(bytes, len, mask);
114}
115static uint8_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
116 uint8_t sum = 0;
117 for (uint8_t i = 0; i < len; i++) {
118 sum -= NIBBLE_LOW(bytes[i]);
119 sum -= NIBBLE_HIGH(bytes[i]);
120 }
121 sum &= mask;
122 return sum;
123}
124static uint8_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) {
125 return ~calcSumNibbleSub(bytes, len, mask);
126}
127
128// measuring LFSR maximum length
129int CmdAnalyseLfsr(const char *Cmd){
130
131 uint16_t start_state = 0; /* Any nonzero start state will work. */
132 uint16_t lfsr = start_state;
133 //uint32_t period = 0;
134
135 uint8_t iv = param_get8ex(Cmd, 0, 0, 16);
136 uint8_t find = param_get8ex(Cmd, 1, 0, 16);
137
138 printf("LEGIC LFSR IV 0x%02X: \n", iv);
139 printf(" bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n",find);
140
141 for (uint8_t i = 0x01; i < 0x30; i += 1) {
142 //period = 0;
143 legic_prng_init(iv);
144 legic_prng_forward(i);
145 lfsr = legic_prng_get_bits(12);
146
147 printf(" %02X | %03X | %03X | %03X \n",i, lfsr, 0x40 ^ lfsr, find ^ lfsr);
148 }
149 return 0;
150}
151int CmdAnalyseLCR(const char *Cmd) {
152 uint8_t data[50];
153 char cmdp = param_getchar(Cmd, 0);
154 if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_analyse_lcr();
155
156 int len = 0;
157 param_gethex_ex(Cmd, 0, data, &len);
158 if ( len%2 ) return usage_analyse_lcr();
159 len >>= 1;
160 uint8_t finalXor = calculateLRC(data, len);
161 PrintAndLog("Target [%02X] requires final LRC XOR byte value: 0x%02X",data[len-1] ,finalXor);
162 return 0;
163}
164int CmdAnalyseCRC(const char *Cmd) {
165
166 char cmdp = param_getchar(Cmd, 0);
167 if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_analyse_crc();
168
169 int len = strlen(Cmd);
170 if ( len & 1 ) return usage_analyse_crc();
171
172 // add 1 for null terminator.
173 uint8_t *data = malloc(len+1);
174 if ( data == NULL ) return 1;
175
176 if ( param_gethex(Cmd, 0, data, len)) {
177 free(data);
178 return usage_analyse_crc();
179 }
180 len >>= 1;
181
182 //PrintAndLog("\nTests with '%s' hex bytes", sprint_hex(data, len));
183
184 PrintAndLog("\nTests of reflection. Two current methods in source code");
185 PrintAndLog(" reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) );
186 PrintAndLog(" SwapBits(0x3e23L,3) is %04X == 0x3e26", SwapBits(0x3e23L,3) );
187 PrintAndLog(" 0xB400 == %04X", reflect( (1 << 16 | 0xb400),16) );
188
189 //
190 // Test of CRC16, '123456789' string.
191 //
192 PrintAndLog("\nTests with '123456789' string");
193 uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 };
194 uint8_t legic8 = CRC8Legic(dataStr, sizeof(dataStr));
195
196 PrintAndLog("LEGIC: CRC16: %X", CRC16Legic(dataStr, sizeof(dataStr), legic8));
197
198 //these below has been tested OK.
199 PrintAndLog("Confirmed CRC Implementations");
200 PrintAndLog("LEGIC: CRC8 : %X (0xC6 expected)", legic8);
201 PrintAndLog("MAXIM: CRC8 : %X (0xA1 expected)", CRC8Maxim(dataStr, sizeof(dataStr)));
202 PrintAndLog("DNP : CRC16: %X (0x82EA expected)", CRC16_DNP(dataStr, sizeof(dataStr)));
203 PrintAndLog("CCITT: CRC16: %X (0xE5CC expected)", CRC16_CCITT(dataStr, sizeof(dataStr)));
204
205 PrintAndLog("ICLASS org: CRC16: %X (0x expected)",iclass_crc16( (char*)dataStr, sizeof(dataStr)));
206 PrintAndLog("ICLASS ice: CRC16: %X (0x expected)",CRC16_ICLASS(dataStr, sizeof(dataStr)));
207
208
209
210 uint8_t dataStr1234[] = { 0x1,0x2,0x3,0x4};
211 PrintAndLog("ISO15693 org: : CRC16: %X (0xF0B8 expected)", Iso15693Crc(dataStr1234, sizeof(dataStr1234)));
212 PrintAndLog("ISO15693 ice: : CRC16: %X (0xF0B8 expected)", CRC16_Iso15693(dataStr1234, sizeof(dataStr1234)));
213
214 free(data);
215 return 0;
216}
217int CmdAnalyseCHKSUM(const char *Cmd){
218
219 uint8_t data[50];
220 uint8_t cmdp = 0;
221 uint32_t mask = 0xFF;
222 bool errors = false;
223 int len = 0;
224 memset(data, 0x0, sizeof(data));
225
226 while(param_getchar(Cmd, cmdp) != 0x00) {
227 switch(param_getchar(Cmd, cmdp)) {
228 case 'b':
229 case 'B':
230 param_gethex_ex(Cmd, cmdp+1, data, &len);
231 if ( len%2 ) errors = true;
232 len >>= 1;
233 cmdp += 2;
234 break;
235 case 'm':
236 case 'M':
237 mask = param_get32ex(Cmd, cmdp+1, 0, 16);
238 cmdp += 2;
239 break;
240 case 'h':
241 case 'H':
242 return usage_analyse_checksum();
243 default:
244 PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
245 errors = true;
246 break;
247 }
248 if(errors) break;
249 }
250 //Validations
251 if(errors) return usage_analyse_checksum();
252
253 PrintAndLog("\nByte Add | 0x%X", calcSumByteAdd(data, len, mask));
254 PrintAndLog("Nibble Add | 0x%X", calcSumNibbleAdd(data, len, mask));
255 PrintAndLog("Crumb Add | 0x%X", calcSumCrumbAdd(data, len, mask));
256
257 PrintAndLog("\nByte Subtract | 0x%X", calcSumByteSub(data, len, mask));
258 PrintAndLog("Nibble Subtract | 0x%X", calcSumNibbleSub(data, len, mask));
259
260 PrintAndLog("\nCHECKSUM - One's complement");
261 PrintAndLog("Byte Add | 0x%X", calcSumByteAddOnes(data, len, mask));
262 PrintAndLog("Nibble Add | 0x%X", calcSumNibbleAddOnes(data, len, mask));
263 PrintAndLog("Crumb Add | 0x%X", calcSumCrumbAddOnes(data, len, mask));
264
265 PrintAndLog("Byte Subtract | 0x%X", calcSumByteSubOnes(data, len, mask));
266 PrintAndLog("Nibble Subtract | 0x%X", calcSumNibbleSubOnes(data, len, mask));
267
268 return 0;
269}
270
271int CmdAnalyseDates(const char *Cmd){
272 // look for datestamps in a given array of bytes
273 PrintAndLog("To be implemented. Feel free to contribute!");
274 return 0;
275}
276int CmdAnalyseTEASelfTest(const char *Cmd){
277
278 uint8_t v[8], v_le[8];
279 memset(v, 0x00, sizeof(v));
280 memset(v_le, 0x00, sizeof(v_le));
281 uint8_t* v_ptr = v_le;
282
283 uint8_t cmdlen = strlen(Cmd);
284 cmdlen = ( sizeof(v)<<2 < cmdlen ) ? sizeof(v)<<2 : cmdlen;
285
286 if ( param_gethex(Cmd, 0, v, cmdlen) > 0 ){
287 PrintAndLog("can't read hex chars, uneven? :: %u", cmdlen);
288 return 1;
289 }
290
291 SwapEndian64ex(v , 8, 4, v_ptr);
292
293 // ENCRYPTION KEY:
294 uint8_t key[16] = {0x55,0xFE,0xF6,0x30,0x62,0xBF,0x0B,0xC1,0xC9,0xB3,0x7C,0x34,0x97,0x3E,0x29,0xFB };
295 uint8_t keyle[16];
296 uint8_t* key_ptr = keyle;
297 SwapEndian64ex(key , sizeof(key), 4, key_ptr);
298
299 PrintAndLog("TEST LE enc| %s", sprint_hex(v_ptr, 8));
300
301 tea_decrypt(v_ptr, key_ptr);
302 PrintAndLog("TEST LE dec | %s", sprint_hex_ascii(v_ptr, 8));
303
304 tea_encrypt(v_ptr, key_ptr);
305 tea_encrypt(v_ptr, key_ptr);
306 PrintAndLog("TEST enc2 | %s", sprint_hex_ascii(v_ptr, 8));
307
308 return 0;
309}
310
311int CmdAnalyseA(const char *Cmd){
312
313// uid(2e086b1a) nt(230736f6) par(0000000000000000) ks(0b0008000804000e) nr(000000000)
314// uid(2e086b1a) nt(230736f6) par(0000000000000000) ks(0e0b0e0b090c0d02) nr(000000001)
315// uid(2e086b1a) nt(230736f6) par(0000000000000000) ks(0e05060e01080b08) nr(000000002)
316 uint32_t uid = 0x2e086b1a, nt = 0x230736f6, nr = 0x000000001;
317 uint64_t ks_list = 0x0e0b0e0b090c0d02, r_key = 0;
318
319 nonce2key_ex(0, 0 , uid, nt, nr, ks_list, &r_key);
320
321 nr = 0x000000002;
322 ks_list = 0x0e05060e01080b08;
323 nonce2key_ex(0, 0 , uid, nt, nr, ks_list, &r_key);
324
325 printf("Found valid key: %012"llx" \n", r_key);
326 return 0;
327}
328
329
330static command_t CommandTable[] = {
331 {"help", CmdHelp, 1, "This help"},
332 {"lcr", CmdAnalyseLCR, 1, "Generate final byte for XOR LRC"},
333 {"crc", CmdAnalyseCRC, 1, "Stub method for CRC evaluations"},
334 {"chksum", CmdAnalyseCHKSUM, 1, "Checksum with adding, masking and one's complement"},
335 {"dates", CmdAnalyseDates, 1, "Look for datestamps in a given array of bytes"},
336 {"tea", CmdAnalyseTEASelfTest, 1, "Crypto TEA test"},
337 {"lfsr", CmdAnalyseLfsr, 1, "LFSR tests"},
338 {"a", CmdAnalyseA, 1, "num bits test"},
339 {NULL, NULL, 0, NULL}
340};
341
342int CmdAnalyse(const char *Cmd) {
343 clearCommandBuffer();
344 CmdsParse(CommandTable, Cmd);
345 return 0;
346}
347
348int CmdHelp(const char *Cmd) {
349 CmdsHelp(CommandTable);
350 return 0;
351}
Impressum, Datenschutz