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