]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - client/cmdhf14a.c
Finishing touches on new mifare classic hack rework
[proxmark3-svn] / client / cmdhf14a.c
... / ...
CommitLineData
1//-----------------------------------------------------------------------------
2// 2011, Merlok
3// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
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 ISO14443A commands
10//-----------------------------------------------------------------------------
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <unistd.h>
16#include "util.h"
17#include "iso14443crc.h"
18#include "data.h"
19//#include "proxusb.h"
20#include "proxmark3.h"
21#include "ui.h"
22#include "cmdparser.h"
23#include "cmdhf14a.h"
24#include "common.h"
25#include "cmdmain.h"
26#include "mifare.h"
27
28static int CmdHelp(const char *Cmd);
29
30int CmdHF14AList(const char *Cmd)
31{
32 uint8_t got[1920];
33 GetFromBigBuf(got,sizeof(got),0);
34 WaitForResponse(CMD_ACK,NULL);
35
36 PrintAndLog("recorded activity:");
37 PrintAndLog(" ETU :rssi: who bytes");
38 PrintAndLog("---------+----+----+-----------");
39
40 int i = 0;
41 int prev = -1;
42
43 for (;;) {
44 if(i >= 1900) {
45 break;
46 }
47
48 bool isResponse;
49 int timestamp = *((uint32_t *)(got+i));
50 if (timestamp & 0x80000000) {
51 timestamp &= 0x7fffffff;
52 isResponse = 1;
53 } else {
54 isResponse = 0;
55 }
56
57 int metric = 0;
58 int parityBits = *((uint32_t *)(got+i+4));
59 // 4 bytes of additional information...
60 // maximum of 32 additional parity bit information
61 //
62 // TODO:
63 // at each quarter bit period we can send power level (16 levels)
64 // or each half bit period in 256 levels.
65
66
67 int len = got[i+8];
68
69 if (len > 100) {
70 break;
71 }
72 if (i + len >= 1900) {
73 break;
74 }
75
76 uint8_t *frame = (got+i+9);
77
78 // Break and stick with current result if buffer was not completely full
79 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
80
81 char line[1000] = "";
82 int j;
83 for (j = 0; j < len; j++) {
84 int oddparity = 0x01;
85 int k;
86
87 for (k=0;k<8;k++) {
88 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
89 }
90
91 //if((parityBits >> (len - j - 1)) & 0x01) {
92 if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
93 sprintf(line+(j*4), "%02x! ", frame[j]);
94 }
95 else {
96 sprintf(line+(j*4), "%02x ", frame[j]);
97 }
98 }
99
100 char *crc;
101 crc = "";
102 if (len > 2) {
103 uint8_t b1, b2;
104 for (j = 0; j < (len - 1); j++) {
105 // gives problems... search for the reason..
106 /*if(frame[j] == 0xAA) {
107 switch(frame[j+1]) {
108 case 0x01:
109 crc = "[1] Two drops close after each other";
110 break;
111 case 0x02:
112 crc = "[2] Potential SOC with a drop in second half of bitperiod";
113 break;
114 case 0x03:
115 crc = "[3] Segment Z after segment X is not possible";
116 break;
117 case 0x04:
118 crc = "[4] Parity bit of a fully received byte was wrong";
119 break;
120 default:
121 crc = "[?] Unknown error";
122 break;
123 }
124 break;
125 }*/
126 }
127
128 if (strlen(crc)==0) {
129 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
130 if (b1 != frame[len-2] || b2 != frame[len-1]) {
131 crc = (isResponse & (len < 6)) ? "" : " !crc";
132 } else {
133 crc = "";
134 }
135 }
136 } else {
137 crc = ""; // SHORT
138 }
139
140 char metricString[100];
141 if (isResponse) {
142 sprintf(metricString, "%3d", metric);
143 } else {
144 strcpy(metricString, " ");
145 }
146
147 PrintAndLog(" +%7d: %s: %s %s %s",
148 (prev < 0 ? 0 : (timestamp - prev)),
149 metricString,
150 (isResponse ? "TAG" : " "), line, crc);
151
152 prev = timestamp;
153 i += (len + 9);
154 }
155 return 0;
156}
157
158void iso14a_set_timeout(uint32_t timeout) {
159 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_SET_TIMEOUT, 0, timeout}};
160 SendCommand(&c);
161}
162
163int CmdHF14AReader(const char *Cmd)
164{
165 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
166 SendCommand(&c);
167
168 UsbCommand resp;
169 WaitForResponse(CMD_ACK,&resp);
170
171 iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes;
172
173 if(resp.arg[0] == 0) {
174 PrintAndLog("iso14443a card select failed");
175 return 0;
176 }
177
178 PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
179 PrintAndLog(" UID : %s", sprint_hex(card->uid, card->uidlen));
180 PrintAndLog(" SAK : %02x [%d]", card->sak, resp.arg[0]);
181
182 switch (card->sak) {
183 case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break;
184 case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
185
186 case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k"); break;
187 case 0x09: PrintAndLog("TYPE : NXP MIFARE Mini 0.3k"); break;
188 case 0x10: PrintAndLog("TYPE : NXP MIFARE Plus 2k"); break;
189 case 0x11: PrintAndLog("TYPE : NXP MIFARE Plus 4k"); break;
190 case 0x18: PrintAndLog("TYPE : NXP MIFARE Classic 4k | Plus 4k"); break;
191 case 0x20: PrintAndLog("TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"); break;
192 case 0x24: PrintAndLog("TYPE : NXP MIFARE DESFire | DESFire EV1"); break;
193 case 0x28: PrintAndLog("TYPE : JCOP31 or JCOP41 v2.3.1"); break;
194 case 0x38: PrintAndLog("TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break;
195 case 0x88: PrintAndLog("TYPE : Infineon MIFARE CLASSIC 1K"); break;
196 case 0x98: PrintAndLog("TYPE : Gemplus MPCOS"); break;
197 default: ;
198 }
199 if(resp.arg[0] == 1) {
200 bool ta1 = 0, tb1 = 0, tc1 = 0;
201 int pos;
202
203 PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len));
204 if (card->ats_len > 0) {
205 PrintAndLog(" - TL : length is %d bytes", card->ats[0]);
206 }
207 if (card->ats_len > 1) {
208 ta1 = (card->ats[1] & 0x10) == 0x10;
209 tb1 = (card->ats[1] & 0x20) == 0x20;
210 tc1 = (card->ats[1] & 0x40) == 0x40;
211 PrintAndLog(" - T0 : TA1 is%s present, TB1 is%s present, "
212 "TC1 is%s present, FSCI is %d",
213 (ta1 ? "" : " NOT"), (tb1 ? "" : " NOT"), (tc1 ? "" : " NOT"),
214 (card->ats[1] & 0x0f));
215 }
216 pos = 2;
217 if (ta1 && card->ats_len > pos) {
218 char dr[16], ds[16];
219 dr[0] = ds[0] = '\0';
220 if (card->ats[pos] & 0x10) strcat(ds, "2, ");
221 if (card->ats[pos] & 0x20) strcat(ds, "4, ");
222 if (card->ats[pos] & 0x40) strcat(ds, "8, ");
223 if (card->ats[pos] & 0x01) strcat(dr, "2, ");
224 if (card->ats[pos] & 0x02) strcat(dr, "4, ");
225 if (card->ats[pos] & 0x04) strcat(dr, "8, ");
226 if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
227 if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
228 PrintAndLog(" - TA1 : different divisors are%s supported, "
229 "DR: [%s], DS: [%s]",
230 (card->ats[pos] & 0x80 ? " NOT" : ""), dr, ds);
231 pos++;
232 }
233 if (tb1 && card->ats_len > pos) {
234 PrintAndLog(" - TB1 : SFGI = %d, FWI = %d",
235 (card->ats[pos] & 0x08),
236 (card->ats[pos] & 0x80) >> 4);
237 pos++;
238 }
239 if (tc1 && card->ats_len > pos) {
240 PrintAndLog(" - TC1 : NAD is%s supported, CID is%s supported",
241 (card->ats[pos] & 0x01) ? "" : " NOT",
242 (card->ats[pos] & 0x02) ? "" : " NOT");
243 pos++;
244 }
245 if (card->ats_len > pos) {
246 char *tip = "";
247 if (card->ats_len - pos > 7) {
248 if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
249 tip = "-> MIFARE Plus X 2K or 4K";
250 } else if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
251 tip = "-> MIFARE Plus S 2K or 4K";
252 }
253 }
254 PrintAndLog(" - HB : %s%s", sprint_hex(card->ats + pos, card->ats_len - pos - 2), tip);
255 if (card->ats[pos] == 0xC1) {
256 PrintAndLog(" c1 -> Mifare or (multiple) virtual cards of various type");
257 PrintAndLog(" %02x -> Length is %d bytes",
258 card->ats[pos + 1], card->ats[pos + 1]);
259 switch (card->ats[pos + 2] & 0xf0) {
260 case 0x10:
261 PrintAndLog(" 1x -> MIFARE DESFire");
262 break;
263 case 0x20:
264 PrintAndLog(" 2x -> MIFARE Plus");
265 break;
266 }
267 switch (card->ats[pos + 2] & 0x0f) {
268 case 0x00:
269 PrintAndLog(" x0 -> <1 kByte");
270 break;
271 case 0x01:
272 PrintAndLog(" x0 -> 1 kByte");
273 break;
274 case 0x02:
275 PrintAndLog(" x0 -> 2 kByte");
276 break;
277 case 0x03:
278 PrintAndLog(" x0 -> 4 kByte");
279 break;
280 case 0x04:
281 PrintAndLog(" x0 -> 8 kByte");
282 break;
283 }
284 switch (card->ats[pos + 3] & 0xf0) {
285 case 0x00:
286 PrintAndLog(" 0x -> Engineering sample");
287 break;
288 case 0x20:
289 PrintAndLog(" 2x -> Released");
290 break;
291 }
292 switch (card->ats[pos + 3] & 0x0f) {
293 case 0x00:
294 PrintAndLog(" x0 -> Generation 1");
295 break;
296 case 0x01:
297 PrintAndLog(" x1 -> Generation 2");
298 break;
299 case 0x02:
300 PrintAndLog(" x2 -> Generation 3");
301 break;
302 }
303 switch (card->ats[pos + 4] & 0x0f) {
304 case 0x00:
305 PrintAndLog(" x0 -> Only VCSL supported");
306 break;
307 case 0x01:
308 PrintAndLog(" x1 -> VCS, VCSL, and SVC supported");
309 break;
310 case 0x0E:
311 PrintAndLog(" xE -> no VCS command supported");
312 break;
313 }
314 }
315 }
316 } else {
317 PrintAndLog("proprietary non iso14443a-4 card found, RATS not supported");
318 }
319
320 return resp.arg[0];
321}
322
323// Collect ISO14443 Type A UIDs
324int CmdHF14ACUIDs(const char *Cmd)
325{
326 // requested number of UIDs
327 int n = atoi(Cmd);
328 // collect at least 1 (e.g. if no parameter was given)
329 n = n > 0 ? n : 1;
330
331 PrintAndLog("Collecting %d UIDs", n);
332 PrintAndLog("Start: %u", time(NULL));
333 // repeat n times
334 for (int i = 0; i < n; i++) {
335 // execute anticollision procedure
336 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
337 SendCommand(&c);
338
339 UsbCommand resp;
340 WaitForResponse(CMD_ACK,&resp);
341
342 uint8_t *uid = resp.d.asBytes;
343 iso14a_card_select_t *card = (iso14a_card_select_t *)(uid + 12);
344
345 // check if command failed
346 if (resp.arg[0] == 0) {
347 PrintAndLog("Card select failed.");
348 } else {
349 // check if UID is 4 bytes
350 if ((card->atqa[1] & 0xC0) == 0) {
351 PrintAndLog("%02X%02X%02X%02X",
352 *uid, *(uid + 1), *(uid + 2), *(uid + 3));
353 } else {
354 PrintAndLog("UID longer than 4 bytes");
355 }
356 }
357 }
358 PrintAndLog("End: %u", time(NULL));
359
360 return 1;
361}
362
363// ## simulate iso14443a tag
364// ## greg - added ability to specify tag UID
365int CmdHF14ASim(const char *Cmd)
366{
367 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{0,0,0}};
368
369 // Retrieve the tag type
370 uint8_t tagtype = param_get8ex(Cmd,0,0,10);
371
372 // When no argument was given, just print help message
373 if (tagtype == 0) {
374 PrintAndLog("");
375 PrintAndLog(" Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID");
376 PrintAndLog("");
377 PrintAndLog(" syntax: hf 14a sim <type> <uid>");
378 PrintAndLog(" types: 1 = MIFARE Classic");
379 PrintAndLog(" 2 = MIFARE Ultralight");
380 PrintAndLog(" 3 = MIFARE DESFIRE");
381 PrintAndLog(" 4 = ISO/IEC 14443-4");
382 PrintAndLog("");
383 return 1;
384 }
385
386 // Store the tag type
387 c.arg[0] = tagtype;
388
389 // Retrieve the full 4 or 7 byte long uid
390 uint64_t long_uid = param_get64ex(Cmd,1,0,16);
391
392 // Are we handling the (optional) second part uid?
393 if (long_uid > 0xffffffff) {
394 PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014"llx")",long_uid);
395 // Store the second part
396 c.arg[2] = (long_uid & 0xffffffff);
397 long_uid >>= 32;
398 // Store the first part, ignore the first byte, it is replaced by cascade byte (0x88)
399 c.arg[1] = (long_uid & 0xffffff);
400 } else {
401 PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",long_uid);
402 // Only store the first part
403 c.arg[1] = long_uid & 0xffffffff;
404 }
405/*
406 // At lease save the mandatory first part of the UID
407 c.arg[0] = long_uid & 0xffffffff;
408
409
410 // At lease save the mandatory first part of the UID
411 c.arg[0] = long_uid & 0xffffffff;
412
413 if (c.arg[1] == 0) {
414 PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
415 }
416
417 switch (c.arg[0]) {
418 case 1: {
419 PrintAndLog("Emulating ISO/IEC 14443-3 type A tag with 4 byte UID");
420 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
421 } break;
422 case 2: {
423 PrintAndLog("Emulating ISO/IEC 14443-4 type A tag with 7 byte UID");
424 } break;
425 default: {
426 PrintAndLog("Error: unkown tag type (%d)",c.arg[0]);
427 PrintAndLog("syntax: hf 14a sim <uid>",c.arg[0]);
428 PrintAndLog(" type1: 4 ",c.arg[0]);
429
430 return 1;
431 } break;
432 }
433*/
434/*
435 unsigned int hi = 0, lo = 0;
436 int n = 0, i = 0;
437 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
438 hi= (hi << 4) | (lo >> 28);
439 lo= (lo << 4) | (n & 0xf);
440 }
441*/
442// UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
443// PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
444 SendCommand(&c);
445 return 0;
446}
447
448int CmdHF14ASnoop(const char *Cmd) {
449 int param = 0;
450
451 if (param_getchar(Cmd, 0) == 'h') {
452 PrintAndLog("It get data from the field and saves it into command buffer.");
453 PrintAndLog("Buffer accessible from command hf 14a list.");
454 PrintAndLog("Usage: hf 14a snoop [c][r]");
455 PrintAndLog("c - triggered by first data from card");
456 PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
457 PrintAndLog("sample: hf 14a snoop c r");
458 return 0;
459 }
460
461 for (int i = 0; i < 2; i++) {
462 char ctmp = param_getchar(Cmd, i);
463 if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
464 if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
465 }
466
467 UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}};
468 SendCommand(&c);
469 return 0;
470}
471
472static command_t CommandTable[] =
473{
474 {"help", CmdHelp, 1, "This help"},
475 {"list", CmdHF14AList, 0, "List ISO 14443a history"},
476 {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
477 {"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
478 {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
479 {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
480 {NULL, NULL, 0, NULL}
481};
482
483int CmdHF14A(const char *Cmd) {
484 // flush
485 WaitForResponseTimeout(CMD_ACK,NULL,100);
486
487 // parse
488 CmdsParse(CommandTable, Cmd);
489 return 0;
490}
491
492int CmdHelp(const char *Cmd)
493{
494 CmdsHelp(CommandTable);
495 return 0;
496}
Impressum, Datenschutz