1 //----------------------------------------------------------------------------- 
   3 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch 
   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 
   8 //----------------------------------------------------------------------------- 
   9 // High frequency ISO14443A commands 
  10 //----------------------------------------------------------------------------- 
  17 #include "iso14443crc.h" 
  20 #include "proxmark3.h" 
  22 #include "cmdparser.h" 
  28 static int CmdHelp(const char *Cmd
); 
  30 int CmdHF14AList(const char *Cmd
) 
  33   GetFromBigBuf(got
,sizeof(got
),0); 
  34   WaitForResponse(CMD_ACK
,NULL
); 
  36   PrintAndLog("recorded activity:"); 
  37   PrintAndLog(" ETU     :rssi: who bytes"); 
  38   PrintAndLog("---------+----+----+-----------"); 
  49     int timestamp 
= *((uint32_t *)(got
+i
)); 
  50     if (timestamp 
& 0x80000000) { 
  51       timestamp 
&= 0x7fffffff; 
  58     int parityBits 
= *((uint32_t *)(got
+i
+4)); 
  59     // 4 bytes of additional information... 
  60     // maximum of 32 additional parity bit information 
  63     // at each quarter bit period we can send power level (16 levels) 
  64     // or each half bit period in 256 levels. 
  72     if (i 
+ len 
>= 1900) { 
  76     uint8_t *frame 
= (got
+i
+9); 
  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; } 
  83     for (j 
= 0; j 
< len
; j
++) { 
  88         oddparity 
^= (((frame
[j
] & 0xFF) >> k
) & 0x01); 
  91       //if((parityBits >> (len - j - 1)) & 0x01) { 
  92       if (isResponse 
&& (oddparity 
!= ((parityBits 
>> (len 
- j 
- 1)) & 0x01))) { 
  93         sprintf(line
+(j
*4), "%02x!  ", frame
[j
]); 
  96         sprintf(line
+(j
*4), "%02x   ", frame
[j
]); 
 104       for (j 
= 0; j 
< (len 
- 1); j
++) { 
 105         // gives problems... search for the reason.. 
 106         /*if(frame[j] == 0xAA) { 
 109               crc = "[1] Two drops close after each other"; 
 112               crc = "[2] Potential SOC with a drop in second half of bitperiod"; 
 115               crc = "[3] Segment Z after segment X is not possible"; 
 118               crc = "[4] Parity bit of a fully received byte was wrong"; 
 121               crc = "[?] Unknown error"; 
 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"; 
 140     char metricString
[100]; 
 142       sprintf(metricString
, "%3d", metric
); 
 144       strcpy(metricString
, "   "); 
 147     PrintAndLog(" +%7d: %s: %s %s %s", 
 148       (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
 150       (isResponse 
? "TAG" : "   "), line
, crc
); 
 158 void iso14a_set_timeout(uint32_t timeout
) { 
 159         UsbCommand c 
= {CMD_READER_ISO_14443a
, {ISO14A_SET_TIMEOUT
, 0, timeout
}}; 
 163 int CmdHF14AReader(const char *Cmd
) 
 165         UsbCommand c 
= {CMD_READER_ISO_14443a
, {ISO14A_CONNECT
, 0, 0}}; 
 169   WaitForResponse(CMD_ACK
,&resp
); 
 171   uint8_t              * uid  
= resp
.d
.asBytes
; 
 172         iso14a_card_select_t 
* card 
= (iso14a_card_select_t 
*)(uid 
+ 12); 
 174         if(resp
.arg
[0] == 0) { 
 175                 PrintAndLog("iso14443a card select failed"); 
 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]); 
 184                 case 0x00: PrintAndLog(" SAK : NXP MIFARE Ultralight | Ultralight C"); break; 
 185                 case 0x04: PrintAndLog(" SAK : NXP MIFARE (various !DESFire !DESFire EV1)"); break; 
 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; 
 200         if(resp
.arg
[0] == 1) { 
 201                 bool ta1 
= 0, tb1 
= 0, tc1 
= 0; 
 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]); 
 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)); 
 218                 if (ta1 
&& card
->ats_len 
> pos
) { 
 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
); 
 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); 
 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"); 
 246                 if (card
->ats_len 
> pos
) { 
 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"; 
 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) { 
 262                                                 PrintAndLog("                     1x -> MIFARE DESFire"); 
 265                                                 PrintAndLog("                     2x -> MIFARE Plus"); 
 268                                 switch (card
->ats
[pos 
+ 2] & 0x0f) { 
 270                                                 PrintAndLog("                     x0 -> <1 kByte"); 
 273                                                 PrintAndLog("                     x0 -> 1 kByte"); 
 276                                                 PrintAndLog("                     x0 -> 2 kByte"); 
 279                                                 PrintAndLog("                     x0 -> 4 kByte"); 
 282                                                 PrintAndLog("                     x0 -> 8 kByte"); 
 285                                 switch (card
->ats
[pos 
+ 3] & 0xf0) { 
 287                                                 PrintAndLog("                        0x -> Engineering sample"); 
 290                                                 PrintAndLog("                        2x -> Released"); 
 293                                 switch (card
->ats
[pos 
+ 3] & 0x0f) { 
 295                                                 PrintAndLog("                        x0 -> Generation 1"); 
 298                                                 PrintAndLog("                        x1 -> Generation 2"); 
 301                                                 PrintAndLog("                        x2 -> Generation 3"); 
 304                                 switch (card
->ats
[pos 
+ 4] & 0x0f) { 
 306                                                 PrintAndLog("                           x0 -> Only VCSL supported"); 
 309                                                 PrintAndLog("                           x1 -> VCS, VCSL, and SVC supported"); 
 312                                                 PrintAndLog("                           xE -> no VCS command supported"); 
 319                 PrintAndLog("proprietary non-iso14443a card found, RATS not supported"); 
 324 // Collect ISO14443 Type A UIDs 
 325 int CmdHF14ACUIDs(const char *Cmd
) 
 327         // requested number of UIDs 
 329         // collect at least 1 (e.g. if no parameter was given) 
 332         PrintAndLog("Collecting %d UIDs", n
); 
 333         PrintAndLog("Start: %u", time(NULL
)); 
 335         for (int i 
= 0; i 
< n
; i
++) { 
 336                 // execute anticollision procedure 
 337                 UsbCommand c 
= {CMD_READER_ISO_14443a
, {ISO14A_CONNECT
, 0, 0}}; 
 341     WaitForResponse(CMD_ACK
,&resp
); 
 343                 uint8_t *uid  
= resp
.d
.asBytes
; 
 344                 iso14a_card_select_t 
*card 
= (iso14a_card_select_t 
*)(uid 
+ 12); 
 346                 // check if command failed 
 347                 if (resp
.arg
[0] == 0) { 
 348                         PrintAndLog("Card select failed."); 
 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)); 
 355                                 PrintAndLog("UID longer than 4 bytes"); 
 359         PrintAndLog("End: %u", time(NULL
)); 
 364 // ## simulate iso14443a tag 
 365 // ## greg - added ability to specify tag UID 
 366 int CmdHF14ASim(const char *Cmd
) 
 368         UsbCommand c 
= {CMD_SIMULATE_TAG_ISO_14443a
,{0,0,0}}; 
 370         // Retrieve the tag type 
 371         uint8_t tagtype 
= param_get8ex(Cmd
,0,0,10); 
 373         // When no argument was given, just print help message 
 376                 PrintAndLog(" Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID"); 
 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"); 
 387         // Store the tag type 
 390         // Retrieve the full 4 or 7 byte long uid  
 391         uint64_t long_uid 
= param_get64ex(Cmd
,1,0,16); 
 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); 
 399                 // Store the first part, ignore the first byte, it is replaced by cascade byte (0x88) 
 400                 c
.arg
[1] = (long_uid 
& 0xffffff); 
 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; 
 407                 // At lease save the mandatory first part of the UID 
 408                 c.arg[0] = long_uid & 0xffffffff; 
 411         // At lease save the mandatory first part of the UID 
 412         c.arg[0] = long_uid & 0xffffffff; 
 415                 PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]); 
 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)}; 
 424                         PrintAndLog("Emulating ISO/IEC 14443-4 type A tag with 7 byte UID"); 
 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]); 
 436   unsigned int hi = 0, lo = 0; 
 438   while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { 
 439     hi= (hi << 4) | (lo >> 28); 
 440     lo= (lo << 4) | (n & 0xf); 
 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]); 
 449 int CmdHF14ASnoop(const char *Cmd
) { 
 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"); 
 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; 
 468   UsbCommand c 
= {CMD_SNOOP_ISO_14443a
, {param
, 0, 0}}; 
 473 static command_t CommandTable
[] =  
 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
} 
 484 int CmdHF14A(const char *Cmd
) { 
 486         WaitForResponseTimeout(CMD_ACK
,NULL
,100); 
 489   CmdsParse(CommandTable
, Cmd
); 
 493 int CmdHelp(const char *Cmd
) 
 495   CmdsHelp(CommandTable
);