]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - client/cmdhf14a.c
minor fix when reading blocks
[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 uint8_t * uid = resp.d.asBytes;
172 iso14a_card_select_t * card = (iso14a_card_select_t *)(uid + 12);
173
174 if(resp.arg[0] == 0) {
175 PrintAndLog("iso14443a card select failed");
176 return 0;
177 }
178
179 PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
180 PrintAndLog(" UID : %s", sprint_hex(uid, 12));
181 PrintAndLog(" SAK : %02x [%d]", card->sak, resp.arg[0]);
182
183 switch (card->sak) {
184 case 0x00: PrintAndLog(" SAK : NXP MIFARE Ultralight | Ultralight C"); break;
185 case 0x04: PrintAndLog(" SAK : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
186
187 case 0x08: PrintAndLog(" SAK : NXP MIFARE CLASSIC 1k | Plus 2k"); break;
188 case 0x09: PrintAndLog(" SAK : NXP MIFARE Mini 0.3k"); break;
189 case 0x10: PrintAndLog(" SAK : NXP MIFARE Plus 2k"); break;
190 case 0x11: PrintAndLog(" SAK : NXP MIFARE Plus 4k"); break;
191 case 0x18: PrintAndLog(" SAK : NXP MIFARE Classic 4k | Plus 4k"); break;
192 case 0x20: PrintAndLog(" SAK : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"); break;
193 case 0x24: PrintAndLog(" SAK : NXP MIFARE DESFire | DESFire EV1"); break;
194 case 0x28: PrintAndLog(" SAK : JCOP31 or JCOP41 v2.3.1"); break;
195 case 0x38: PrintAndLog(" SAK : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break;
196 case 0x88: PrintAndLog(" SAK : Infineon MIFARE CLASSIC 1K"); break;
197 case 0x98: PrintAndLog(" SAK : Gemplus MPCOS"); break;
198 default: ;
199 }
200 if(resp.arg[0] == 1) {
201 bool ta1 = 0, tb1 = 0, tc1 = 0;
202 int pos;
203
204 PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len));
205 if (card->ats_len > 0) {
206 PrintAndLog(" - TL : length is %d bytes", card->ats[0]);
207 }
208 if (card->ats_len > 1) {
209 ta1 = (card->ats[1] & 0x10) == 0x10;
210 tb1 = (card->ats[1] & 0x20) == 0x20;
211 tc1 = (card->ats[1] & 0x40) == 0x40;
212 PrintAndLog(" - T0 : TA1 is%s present, TB1 is%s present, "
213 "TC1 is%s present, FSCI is %d",
214 (ta1 ? "" : " NOT"), (tb1 ? "" : " NOT"), (tc1 ? "" : " NOT"),
215 (card->ats[1] & 0x0f));
216 }
217 pos = 2;
218 if (ta1 && card->ats_len > pos) {
219 char dr[16], ds[16];
220 dr[0] = ds[0] = '\0';
221 if (card->ats[pos] & 0x10) strcat(ds, "2, ");
222 if (card->ats[pos] & 0x20) strcat(ds, "4, ");
223 if (card->ats[pos] & 0x40) strcat(ds, "8, ");
224 if (card->ats[pos] & 0x01) strcat(dr, "2, ");
225 if (card->ats[pos] & 0x02) strcat(dr, "4, ");
226 if (card->ats[pos] & 0x04) strcat(dr, "8, ");
227 if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
228 if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
229 PrintAndLog(" - TA1 : different divisors are%s supported, "
230 "DR: [%s], DS: [%s]",
231 (card->ats[pos] & 0x80 ? " NOT" : ""), dr, ds);
232 pos++;
233 }
234 if (tb1 && card->ats_len > pos) {
235 PrintAndLog(" - TB1 : SFGI = %d, FWI = %d",
236 (card->ats[pos] & 0x08),
237 (card->ats[pos] & 0x80) >> 4);
238 pos++;
239 }
240 if (tc1 && card->ats_len > pos) {
241 PrintAndLog(" - TC1 : NAD is%s supported, CID is%s supported",
242 (card->ats[pos] & 0x01) ? "" : " NOT",
243 (card->ats[pos] & 0x02) ? "" : " NOT");
244 pos++;
245 }
246 if (card->ats_len > pos) {
247 char *tip = "";
248 if (card->ats_len - pos > 7) {
249 if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
250 tip = "-> MIFARE Plus X 2K or 4K";
251 } else if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
252 tip = "-> MIFARE Plus S 2K or 4K";
253 }
254 }
255 PrintAndLog(" - HB : %s%s", sprint_hex(card->ats + pos, card->ats_len - pos - 2), tip);
256 if (card->ats[pos] == 0xC1) {
257 PrintAndLog(" c1 -> Mifare or (multiple) virtual cards of various type");
258 PrintAndLog(" %02x -> Length is %d bytes",
259 card->ats[pos + 1], card->ats[pos + 1]);
260 switch (card->ats[pos + 2] & 0xf0) {
261 case 0x10:
262 PrintAndLog(" 1x -> MIFARE DESFire");
263 break;
264 case 0x20:
265 PrintAndLog(" 2x -> MIFARE Plus");
266 break;
267 }
268 switch (card->ats[pos + 2] & 0x0f) {
269 case 0x00:
270 PrintAndLog(" x0 -> <1 kByte");
271 break;
272 case 0x01:
273 PrintAndLog(" x0 -> 1 kByte");
274 break;
275 case 0x02:
276 PrintAndLog(" x0 -> 2 kByte");
277 break;
278 case 0x03:
279 PrintAndLog(" x0 -> 4 kByte");
280 break;
281 case 0x04:
282 PrintAndLog(" x0 -> 8 kByte");
283 break;
284 }
285 switch (card->ats[pos + 3] & 0xf0) {
286 case 0x00:
287 PrintAndLog(" 0x -> Engineering sample");
288 break;
289 case 0x20:
290 PrintAndLog(" 2x -> Released");
291 break;
292 }
293 switch (card->ats[pos + 3] & 0x0f) {
294 case 0x00:
295 PrintAndLog(" x0 -> Generation 1");
296 break;
297 case 0x01:
298 PrintAndLog(" x1 -> Generation 2");
299 break;
300 case 0x02:
301 PrintAndLog(" x2 -> Generation 3");
302 break;
303 }
304 switch (card->ats[pos + 4] & 0x0f) {
305 case 0x00:
306 PrintAndLog(" x0 -> Only VCSL supported");
307 break;
308 case 0x01:
309 PrintAndLog(" x1 -> VCS, VCSL, and SVC supported");
310 break;
311 case 0x0E:
312 PrintAndLog(" xE -> no VCS command supported");
313 break;
314 }
315 }
316 }
317 }
318 else
319 PrintAndLog("proprietary non-iso14443a card found, RATS not supported");
320
321 return resp.arg[0];
322}
323
324// Collect ISO14443 Type A UIDs
325int CmdHF14ACUIDs(const char *Cmd)
326{
327 // requested number of UIDs
328 int n = atoi(Cmd);
329 // collect at least 1 (e.g. if no parameter was given)
330 n = n > 0 ? n : 1;
331
332 PrintAndLog("Collecting %d UIDs", n);
333 PrintAndLog("Start: %u", time(NULL));
334 // repeat n times
335 for (int i = 0; i < n; i++) {
336 // execute anticollision procedure
337 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
338 SendCommand(&c);
339
340 UsbCommand resp;
341 WaitForResponse(CMD_ACK,&resp);
342
343 uint8_t *uid = resp.d.asBytes;
344 iso14a_card_select_t *card = (iso14a_card_select_t *)(uid + 12);
345
346 // check if command failed
347 if (resp.arg[0] == 0) {
348 PrintAndLog("Card select failed.");
349 } else {
350 // check if UID is 4 bytes
351 if ((card->atqa[1] & 0xC0) == 0) {
352 PrintAndLog("%02X%02X%02X%02X",
353 *uid, *(uid + 1), *(uid + 2), *(uid + 3));
354 } else {
355 PrintAndLog("UID longer than 4 bytes");
356 }
357 }
358 }
359 PrintAndLog("End: %u", time(NULL));
360
361 return 1;
362}
363
364// ## simulate iso14443a tag
365// ## greg - added ability to specify tag UID
366int CmdHF14ASim(const char *Cmd)
367{
368 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{0,0,0}};
369
370 // Retrieve the tag type
371 uint8_t tagtype = param_get8ex(Cmd,0,0,10);
372
373 // When no argument was given, just print help message
374 if (tagtype == 0) {
375 PrintAndLog("");
376 PrintAndLog(" Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID");
377 PrintAndLog("");
378 PrintAndLog(" syntax: hf 14a sim <type> <uid>");
379 PrintAndLog(" types: 1 = MIFARE Classic");
380 PrintAndLog(" 2 = MIFARE Ultralight");
381 PrintAndLog(" 3 = MIFARE DESFIRE");
382 PrintAndLog(" 4 = ISO/IEC 14443-4");
383 PrintAndLog("");
384 return 1;
385 }
386
387 // Store the tag type
388 c.arg[0] = tagtype;
389
390 // Retrieve the full 4 or 7 byte long uid
391 uint64_t long_uid = param_get64ex(Cmd,1,0,16);
392
393 // Are we handling the (optional) second part uid?
394 if (long_uid > 0xffffffff) {
395 PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014llx)",long_uid);
396 // Store the second part
397 c.arg[2] = (long_uid & 0xffffffff);
398 long_uid >>= 32;
399 // Store the first part, ignore the first byte, it is replaced by cascade byte (0x88)
400 c.arg[1] = (long_uid & 0xffffff);
401 } else {
402 PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",long_uid);
403 // Only store the first part
404 c.arg[1] = long_uid & 0xffffffff;
405 }
406/*
407 // At lease save the mandatory first part of the UID
408 c.arg[0] = long_uid & 0xffffffff;
409
410
411 // At lease save the mandatory first part of the UID
412 c.arg[0] = long_uid & 0xffffffff;
413
414 if (c.arg[1] == 0) {
415 PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
416 }
417
418 switch (c.arg[0]) {
419 case 1: {
420 PrintAndLog("Emulating ISO/IEC 14443-3 type A tag with 4 byte UID");
421 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)};
422 } break;
423 case 2: {
424 PrintAndLog("Emulating ISO/IEC 14443-4 type A tag with 7 byte UID");
425 } break;
426 default: {
427 PrintAndLog("Error: unkown tag type (%d)",c.arg[0]);
428 PrintAndLog("syntax: hf 14a sim <uid>",c.arg[0]);
429 PrintAndLog(" type1: 4 ",c.arg[0]);
430
431 return 1;
432 } break;
433 }
434*/
435/*
436 unsigned int hi = 0, lo = 0;
437 int n = 0, i = 0;
438 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
439 hi= (hi << 4) | (lo >> 28);
440 lo= (lo << 4) | (n & 0xf);
441 }
442*/
443// 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)};
444// PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
445 SendCommand(&c);
446 return 0;
447}
448
449int CmdHF14ASnoop(const char *Cmd) {
450 int param = 0;
451
452 if (param_getchar(Cmd, 0) == 'h') {
453 PrintAndLog("It get data from the field and saves it into command buffer.");
454 PrintAndLog("Buffer accessible from command hf 14a list.");
455 PrintAndLog("Usage: hf 14a snoop [c][r]");
456 PrintAndLog("c - triggered by first data from card");
457 PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
458 PrintAndLog("sample: hf 14a snoop c r");
459 return 0;
460 }
461
462 for (int i = 0; i < 2; i++) {
463 char ctmp = param_getchar(Cmd, i);
464 if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
465 if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
466 }
467
468 UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}};
469 SendCommand(&c);
470 return 0;
471}
472
473static command_t CommandTable[] =
474{
475 {"help", CmdHelp, 1, "This help"},
476 {"list", CmdHF14AList, 0, "List ISO 14443a history"},
477 {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
478 {"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
479 {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
480 {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
481 {NULL, NULL, 0, NULL}
482};
483
484int CmdHF14A(const char *Cmd) {
485 // flush
486 WaitForResponseTimeout(CMD_ACK,NULL,100);
487
488 // parse
489 CmdsParse(CommandTable, Cmd);
490 return 0;
491}
492
493int CmdHelp(const char *Cmd)
494{
495 CmdsHelp(CommandTable);
496 return 0;
497}
Impressum, Datenschutz