]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhficlass.c
Implemented client side changes for iclass hack, attempted to fix issues with trace...
[proxmark3-svn] / client / cmdhficlass.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // Copyright (C) 2011 Gerhard de Koning Gans
4 //
5 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 // at your option, any later version. See the LICENSE.txt file for the text of
7 // the license.
8 //-----------------------------------------------------------------------------
9 // High frequency iClass commands
10 //-----------------------------------------------------------------------------
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
16 #include "data.h"
17 //#include "proxusb.h"
18 #include "proxmark3.h"
19 #include "ui.h"
20 #include "cmdparser.h"
21 #include "cmdhficlass.h"
22 #include "common.h"
23 #include "util.h"
24 #include "cmdmain.h"
25
26 static int CmdHelp(const char *Cmd);
27
28 int xorbits_8(uint8_t val)
29 {
30 uint8_t res = val ^ (val >> 1); //1st pass
31 res = res ^ (res >> 1); // 2nd pass
32 res = res ^ (res >> 2); // 3rd pass
33 res = res ^ (res >> 4); // 4th pass
34 return res & 1;
35 }
36
37 int CmdHFiClassList(const char *Cmd)
38 {
39
40 bool ShowWaitCycles = false;
41 char param = param_getchar(Cmd, 0);
42
43 if (param != 0) {
44 PrintAndLog("List data in trace buffer.");
45 PrintAndLog("Usage: hf iclass list");
46 PrintAndLog("h - help");
47 PrintAndLog("sample: hf iclass list");
48 return 0;
49 }
50
51 uint8_t got[1920];
52 GetFromBigBuf(got,sizeof(got),0);
53 WaitForResponse(CMD_ACK,NULL);
54
55 PrintAndLog("Recorded Activity");
56 PrintAndLog("");
57 PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
58 PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
59 PrintAndLog("");
60 PrintAndLog(" Start | End | Src | Data");
61 PrintAndLog("-----------|-----------|-----|--------");
62
63 int i;
64 uint32_t first_timestamp = 0;
65 uint32_t timestamp;
66 bool tagToReader;
67 uint32_t parityBits;
68 uint8_t len;
69 uint8_t *frame;
70 uint32_t EndOfTransmissionTimestamp = 0;
71
72 uint8_t empty[4] = {0x44,0x44,0x44,0x44};
73
74 for( i=0; i < 1900;)
75 {
76 //First 32 bits contain
77 // isResponse (1 bit)
78 // timestamp (remaining)
79 //Then paritybits
80 //Then length
81 timestamp = *((uint32_t *)(got+i));
82 parityBits = *((uint32_t *)(got+i+4));
83 len = got[i+8];
84 frame = (got+i+9);
85 uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff;
86
87 tagToReader = timestamp & 0x80000000;
88 timestamp &= 0x7fffffff;
89
90 if(i==0) {
91 first_timestamp = timestamp;
92 }
93
94 // Break and stick with current result if buffer
95 // was not completely full
96 if(memcmp(frame,empty,sizeof(empty))) break;
97
98 char line[1000] = "";
99
100 if(len)//We have some data to display
101 {
102 int j,oddparity;
103
104 for(j = 0; j < len ; j++)
105 {
106 oddparity = 0x01 ^ xorbits_8(frame[j] & 0xFF);
107
108 if (tagToReader && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
109 sprintf(line+(j*4), "%02x! ", frame[j]);
110 } else {
111 sprintf(line+(j*4), "%02x ", frame[j]);
112 }
113 }
114 }else
115 {
116 if (ShowWaitCycles) {
117 sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp));
118 }
119 }
120
121 char *crc = "";
122
123 if(len > 2)
124 {
125 uint8_t b1, b2;
126 if(!tagToReader && len == 4) {
127 // Rough guess that this is a command from the reader
128 // For iClass the command byte is not part of the CRC
129 ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2);
130 }
131 else {
132 // For other data.. CRC might not be applicable (UPDATE commands etc.)
133 ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2);
134 }
135
136 if (b1 != frame[len-2] || b2 != frame[len-1]) {
137 crc = (tagToReader & (len < 8)) ? "" : " !crc";
138 }
139 }
140
141 i += (len + 9);
142 EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff;
143
144 // Not implemented for iclass on the ARM-side
145 //if (!ShowWaitCycles) i += 9;
146
147 PrintAndLog(" %9d | %9d | %s | %s %s",
148 (timestamp - first_timestamp),
149 (EndOfTransmissionTimestamp - first_timestamp),
150 (len?(tagToReader ? "Tag" : "Rdr"):" "),
151 line, crc);
152 }
153 return 0;
154 }
155
156 int CmdHFiClassListOld(const char *Cmd)
157 {
158 uint8_t got[1920];
159 GetFromBigBuf(got,sizeof(got),0);
160
161 PrintAndLog("recorded activity:");
162 PrintAndLog(" ETU :rssi: who bytes");
163 PrintAndLog("---------+----+----+-----------");
164
165 int i = 0;
166 int prev = -1;
167
168 for (;;) {
169 if(i >= 1900) {
170 break;
171 }
172
173 bool isResponse;
174 int timestamp = *((uint32_t *)(got+i));
175 if (timestamp & 0x80000000) {
176 timestamp &= 0x7fffffff;
177 isResponse = 1;
178 } else {
179 isResponse = 0;
180 }
181
182
183 int metric = 0;
184
185 int parityBits = *((uint32_t *)(got+i+4));
186 // 4 bytes of additional information...
187 // maximum of 32 additional parity bit information
188 //
189 // TODO:
190 // at each quarter bit period we can send power level (16 levels)
191 // or each half bit period in 256 levels.
192
193
194 int len = got[i+8];
195
196 if (len > 100) {
197 break;
198 }
199 if (i + len >= 1900) {
200 break;
201 }
202
203 uint8_t *frame = (got+i+9);
204
205 // Break and stick with current result if buffer was not completely full
206 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
207
208 char line[1000] = "";
209 int j;
210 for (j = 0; j < len; j++) {
211 int oddparity = 0x01;
212 int k;
213
214 for (k=0;k<8;k++) {
215 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
216 }
217
218 //if((parityBits >> (len - j - 1)) & 0x01) {
219 if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
220 sprintf(line+(j*4), "%02x! ", frame[j]);
221 }
222 else {
223 sprintf(line+(j*4), "%02x ", frame[j]);
224 }
225 }
226
227 char *crc;
228 crc = "";
229 if (len > 2) {
230 uint8_t b1, b2;
231 for (j = 0; j < (len - 1); j++) {
232 // gives problems... search for the reason..
233 /*if(frame[j] == 0xAA) {
234 switch(frame[j+1]) {
235 case 0x01:
236 crc = "[1] Two drops close after each other";
237 break;
238 case 0x02:
239 crc = "[2] Potential SOC with a drop in second half of bitperiod";
240 break;
241 case 0x03:
242 crc = "[3] Segment Z after segment X is not possible";
243 break;
244 case 0x04:
245 crc = "[4] Parity bit of a fully received byte was wrong";
246 break;
247 default:
248 crc = "[?] Unknown error";
249 break;
250 }
251 break;
252 }*/
253 }
254
255 if (strlen(crc)==0) {
256 if(!isResponse && len == 4) {
257 // Rough guess that this is a command from the reader
258 // For iClass the command byte is not part of the CRC
259 ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2);
260 }
261 else {
262 // For other data.. CRC might not be applicable (UPDATE commands etc.)
263 ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2);
264 }
265 //printf("%1x %1x",(unsigned)b1,(unsigned)b2);
266 if (b1 != frame[len-2] || b2 != frame[len-1]) {
267 crc = (isResponse & (len < 8)) ? "" : " !crc";
268 } else {
269 crc = "";
270 }
271 }
272 } else {
273 crc = ""; // SHORT
274 }
275
276 char metricString[100];
277 if (isResponse) {
278 sprintf(metricString, "%3d", metric);
279 } else {
280 strcpy(metricString, " ");
281 }
282
283 PrintAndLog(" +%7d: %s: %s %s %s",
284 (prev < 0 ? 0 : (timestamp - prev)),
285 metricString,
286 (isResponse ? "TAG" : " "), line, crc);
287
288 prev = timestamp;
289 i += (len + 9);
290 }
291 return 0;
292 }
293
294 /*void iso14a_set_timeout(uint32_t timeout) {
295 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_SET_TIMEOUT, 0, timeout}};
296 SendCommand(&c);
297 }*/
298
299 int CmdHFiClassSnoop(const char *Cmd)
300 {
301 UsbCommand c = {CMD_SNOOP_ICLASS};
302 SendCommand(&c);
303 return 0;
304 }
305
306 int CmdHFiClassSim(const char *Cmd)
307 {
308 uint8_t simType = 0;
309 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
310
311 if (strlen(Cmd)<1) {
312 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
313 PrintAndLog(" options");
314 PrintAndLog(" 0 <CSN> simulate the given CSN");
315 PrintAndLog(" 1 simulate default CSN");
316 PrintAndLog(" 2 iterate CSNs, gather MACs");
317 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
318 PrintAndLog(" sample: hf iclass sim 2");
319 return 0;
320 }
321
322 simType = param_get8(Cmd, 0);
323
324 if(simType == 0)
325 {
326 if (param_gethex(Cmd, 1, CSN, 16)) {
327 PrintAndLog("A CSN should consist of 16 HEX symbols");
328 return 1;
329 }
330 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
331
332 }
333 if(simType > 2)
334 {
335 PrintAndLog("Undefined simptype %d", simType);
336 return 1;
337 }
338 uint8_t numberOfCSNs=0;
339
340 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
341 memcpy(c.d.asBytes, CSN, 8);
342
343 if(simType == 2)
344 {
345 c.arg[1] = 10;//10 CSNs
346 uint8_t csns[] ={
347 /* Order Simulated CSN HASH1 Recovered key bytes */
348 /* 1 */ 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0,// 0101000045014545 00,01 45
349 /* 2 */ 0x03,0x0B,0x0E,0xFE,0xF7,0xFF,0x12,0xE0,// 0202000045014545 02
350 /* 3 */ 0x04,0x0D,0x0D,0xFD,0xF7,0xFF,0x12,0xE0,// 0303000045014545 03
351 /* 4 */ 0x04,0x0F,0x0F,0xF7,0xF7,0xFF,0x12,0xE0,// 0901000045014545 09
352 /* 5 */ 0x01,0x13,0x10,0xF4,0xF7,0xFF,0x12,0xE0,// 0C00000045014545 0C
353 /* 6 */ 0x02,0x14,0x10,0xF2,0xF7,0xFF,0x12,0xE0,// 0E00000045014545 0E
354 /* 7 */ 0x05,0x17,0x10,0xEC,0xF7,0xFF,0x12,0xE0,// 1400000045014545 14
355 /* 8 */ 0x00,0x6B,0x6F,0xDF,0xF7,0xFF,0x12,0xE0,// 2121000045014545 21
356 /* 9 */ 0x03,0x6B,0x6E,0xDE,0xF7,0xFF,0x12,0xE0,// 2222000045014545 22
357 /* 10 */ 0x04,0x6D,0x6D,0xDD,0xF7,0xFF,0x12,0xE0,// 2323000045014545 23
358 /* 11 */ 0x00,0x4F,0x4B,0x43,0xF7,0xFF,0x12,0xE0,// 3D45000045014545 3D
359 /* 12 */ 0x00,0x4B,0x4F,0x3F,0xF7,0xFF,0x12,0xE0,// 4141000045014545 41
360 /* 13 */ 0x03,0x4B,0x4E,0x3E,0xF7,0xFF,0x12,0xE0,// 4242000045014545 42
361 /* 14 */ 0x04,0x4D,0x4D,0x3D,0xF7,0xFF,0x12,0xE0,// 4343000045014545 43
362 /* 15 */ 0x04,0x37,0x37,0x7F,0xF7,0xFF,0x12,0xE0,// 0159000045014545 59
363 /* 16 */ 0x00,0x2B,0x2F,0x9F,0xF7,0xFF,0x12,0xE0,// 6161000045014545 61
364 /* 17 */ 0x03,0x2B,0x2E,0x9E,0xF7,0xFF,0x12,0xE0,// 6262000045014545 62
365 /* 18 */ 0x04,0x2D,0x2D,0x9D,0xF7,0xFF,0x12,0xE0,// 6363000045014545 63
366 /* 19 */ 0x00,0x27,0x23,0xBB,0xF7,0xFF,0x12,0xE0,// 456D000045014545 6D
367 /* 20 */ 0x02,0x52,0xAA,0x80,0xF7,0xFF,0x12,0xE0,// 0066000045014545 66
368 /* 21 */ 0x00,0x5C,0xA6,0x80,0xF7,0xFF,0x12,0xE0,// 006A000045014545 6A
369 /* 22 */ 0x01,0x5F,0xA4,0x80,0xF7,0xFF,0x12,0xE0,// 006C000045014545 6C
370 /* 23 */ 0x06,0x5E,0xA2,0x80,0xF7,0xFF,0x12,0xE0,// 006E000045014545 6E
371 /* 24 */ 0x02,0x0E,0x0E,0xFC,0xF7,0xFF,0x12,0xE0,// 0402000045014545 04
372 /* 25 */ 0x05,0x0D,0x0E,0xFA,0xF7,0xFF,0x12,0xE0,// 0602000045014545 06
373 /* 26 */ 0x06,0x0F,0x0D,0xF9,0xF7,0xFF,0x12,0xE0,// 0703000045014545 07
374 /* 27 */ 0x00,0x01,0x05,0x1D,0xF7,0xFF,0x12,0xE0,// 630B000045014545 0B
375 /* 28 */ 0x02,0x07,0x01,0x1D,0xF7,0xFF,0x12,0xE0,// 630F000045014545 0F
376 /* 29 */ 0x04,0x7F,0x7F,0xA7,0xF7,0xFF,0x12,0xE0,// 5911000045014545 11
377 /* 30 */ 0x04,0x60,0x6E,0xE8,0xF7,0xFF,0x12,0xE0,// 1822000045014545 18
378 };
379 memcpy(c.d.asBytes, csns, sizeof(c.d.asBytes));
380
381 }
382
383 SendCommand(&c);
384
385 /*UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);
386 if (resp != NULL) {
387 uint8_t isOK = resp->arg[0] & 0xff;
388 PrintAndLog("isOk:%02x", isOK);
389 } else {
390 PrintAndLog("Command execute timeout");
391 }*/
392
393 return 0;
394 }
395
396 int CmdHFiClassReader(const char *Cmd)
397 {
398 uint8_t readerType = 0;
399
400 if (strlen(Cmd)<1) {
401 PrintAndLog("Usage: hf iclass reader <reader type>");
402 PrintAndLog(" sample: hf iclass reader 0");
403 return 0;
404 }
405
406 readerType = param_get8(Cmd, 0);
407 PrintAndLog("--readertype:%02x", readerType);
408
409 UsbCommand c = {CMD_READER_ICLASS, {readerType}};
410 //memcpy(c.d.asBytes, CSN, 8);
411 SendCommand(&c);
412
413 /*UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);
414 if (resp != NULL) {
415 uint8_t isOK = resp->arg[0] & 0xff;
416 PrintAndLog("isOk:%02x", isOK);
417 } else {
418 PrintAndLog("Command execute timeout");
419 }*/
420
421 return 0;
422 }
423
424 static command_t CommandTable[] =
425 {
426 {"help", CmdHelp, 1, "This help"},
427 {"list", CmdHFiClassList, 0, "List iClass history"},
428 {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
429 {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
430 {"reader", CmdHFiClassReader, 0, "Read an iClass tag"},
431 {NULL, NULL, 0, NULL}
432 };
433
434 int CmdHFiClass(const char *Cmd)
435 {
436 CmdsParse(CommandTable, Cmd);
437 return 0;
438 }
439
440 int CmdHelp(const char *Cmd)
441 {
442 CmdsHelp(CommandTable);
443 return 0;
444 }
Impressum, Datenschutz