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