1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   3 // Modified 2010-2012 by <adrian -at- atrox.at> 
   4 // Modified 2012 by <vsza at vsza.hu> 
   6 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   7 // at your option, any later version. See the LICENSE.txt file for the text of 
   9 //----------------------------------------------------------------------------- 
  10 // High frequency ISO15693 commands 
  11 //----------------------------------------------------------------------------- 
  12 // There are three basic operation modes, depending on which device (proxmark/pc) 
  13 // the signal processing, (de)modulation, transmission protocol and logic is done. 
  15 // All steps are done on the proxmark, the output of the commands is returned via 
  16 // USB-debug-print commands. 
  18 // The protocol is done on the PC, passing only Iso15693 data frames via USB. This 
  19 // allows direct communication with a tag on command level 
  21 // The proxmark just samples the antenna and passes this "analog" data via USB to 
  22 // the client. Signal Processing & decoding is done on the pc. This is the slowest 
  23 // variant, but offers the possibility to analyze the waveforms directly.  
  36 #include "cmdparser.h" 
  37 #include "iso15693tools.h" 
  38 #include "protocols.h" 
  42 #define Crc(data,datalen)     Iso15693Crc(data,datalen) 
  43 #define AddCrc(data,datalen)  Iso15693AddCrc(data,datalen) 
  44 #define sprintUID(target,uid)   Iso15693sprintUID(target,uid) 
  47 // 1) Unmodulated time of 56.64us 
  48 // 2) 24 pulses of 423.75khz 
  49 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) 
  51 static const int Iso15693FrameSOF
[] = { 
  52         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
  53         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
  54          1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
  55          1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
  61 static const int Iso15693Logic0
[] = { 
  67 static const int Iso15693Logic1
[] = { 
  75 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) 
  76 // 2) 24 pulses of 423.75khz 
  77 // 3) Unmodulated time of 56.64us 
  79 static const int Iso15693FrameEOF
[] = { 
  84          1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
  85          1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
  86         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
  87         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 
  91 // fast method to just read the UID of a tag (collission detection not supported) 
  92 //              *buf    should be large enough to fit the 64bit uid 
  93 // returns 1 if suceeded 
  94 int getUID(uint8_t *buf
)  
  98         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
  99         uint8_t *req
=c
.d
.asBytes
; 
 102         for (int retry
=0;retry
<3; retry
++) { // don't give up the at the first try               
 104                 req
[0] = ISO15693_REQ_DATARATE_HIGH 
| ISO15693_REQ_INVENTORY 
| ISO15693_REQINV_SLOT1
; 
 105                 req
[1] = ISO15693_INVENTORY
; 
 106                 req
[2] = 0; // mask length 
 107                 reqlen 
= AddCrc(req
,3); 
 112                 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000)) { 
 113                         recv 
= resp
.d
.asBytes
; 
 114                         if (resp
.arg
[0]>=12 && ISO15693_CRC_CHECK
==Crc(recv
,12)) { 
 115                            memcpy(buf
,&recv
[2],8); 
 124 // return a clear-text message to an errorcode 
 125 static char* TagErrorStr(uint8_t error
) { 
 127                 case 0x01: return "The command is not supported"; 
 128                 case 0x02: return "The command is not recognised"; 
 129                 case 0x03: return "The option is not supported."; 
 130                 case 0x0f: return "Unknown error."; 
 131                 case 0x10: return "The specified block is not available (doesn't exist)."; 
 132                 case 0x11: return "The specified block is already -locked and thus cannot be locked again"; 
 133                 case 0x12: return "The specified block is locked and its content cannot be changed."; 
 134                 case 0x13: return "The specified block was not successfully programmed."; 
 135                 case 0x14: return "The specified block was not successfully locked."; 
 136                 default: return "Reserved for Future Use or Custom command error."; 
 142 int CmdHF15Demod(const char *Cmd
) 
 144         // The sampling rate is 106.353 ksps/s, for T = 18.8 us 
 147         int max 
= 0, maxPos 
= 0; 
 151         if (GraphTraceLen 
< 2000) return 0; 
 153         // First, correlate for SOF 
 154         for (i 
= 0; i 
< 200; i
++) { 
 156                 for (j 
= 0; j 
< arraylen(Iso15693FrameSOF
); j 
+= skip
) { 
 157                         corr 
+= Iso15693FrameSOF
[j
] * GraphBuffer
[i 
+ (j 
/ skip
)]; 
 164         PrintAndLog("SOF at %d, correlation %d", maxPos
, 
 165                 max 
/ (arraylen(Iso15693FrameSOF
) / skip
)); 
 167         i 
= maxPos 
+ arraylen(Iso15693FrameSOF
) / skip
; 
 170         memset(outBuf
, 0, sizeof(outBuf
)); 
 173                         int corr0 
= 0, corr00 
= 0, corr01 
= 0, corr1 
= 0, corrEOF 
= 0; 
 174                         for(j 
= 0; j 
< arraylen(Iso15693Logic0
); j 
+= skip
) { 
 175                                 corr0 
+= Iso15693Logic0
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
 177                         corr01 
= corr00 
= corr0
; 
 178                         for(j 
= 0; j 
< arraylen(Iso15693Logic0
); j 
+= skip
) { 
 179                                 corr00 
+= Iso15693Logic0
[j
]*GraphBuffer
[i
+arraylen(Iso15693Logic0
)/skip
+(j
/skip
)]; 
 180                                 corr01 
+= Iso15693Logic1
[j
]*GraphBuffer
[i
+arraylen(Iso15693Logic0
)/skip
+(j
/skip
)]; 
 182                         for(j 
= 0; j 
< arraylen(Iso15693Logic1
); j 
+= skip
) { 
 183                                 corr1 
+= Iso15693Logic1
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
 185                         for(j 
= 0; j 
< arraylen(Iso15693FrameEOF
); j 
+= skip
) { 
 186                                 corrEOF 
+= Iso15693FrameEOF
[j
]*GraphBuffer
[i
+(j
/skip
)]; 
 188                         // Even things out by the length of the target waveform. 
 194                         if(corrEOF 
> corr1 
&& corrEOF 
> corr00 
&& corrEOF 
> corr01
) { 
 195                                 PrintAndLog("EOF at %d", i
); 
 197                 } else if (corr1 
> corr0
) { 
 198                         i 
+= arraylen(Iso15693Logic1
) / skip
; 
 201                         i 
+= arraylen(Iso15693Logic0
) / skip
; 
 208                 if ((i 
+ (int)arraylen(Iso15693FrameEOF
)) >= GraphTraceLen
) { 
 209                         PrintAndLog("ran off end!"); 
 214                 PrintAndLog("error, uneven octet! (discard extra bits!)"); 
 215                 PrintAndLog("   mask=%02x", mask
); 
 217         PrintAndLog("%d octets", k
); 
 219         for (i 
= 0; i 
< k
; i
++) { 
 220                 PrintAndLog("# %2d: %02x ", i
, outBuf
[i
]); 
 222         PrintAndLog("CRC=%04x", Iso15693Crc(outBuf
, k 
- 2)); 
 228 // * Acquire Samples as Reader (enables carrier, sends inquiry) 
 229 int CmdHF15Read(const char *Cmd
) 
 231         UsbCommand c 
= {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693
}; 
 236 // Record Activity without enabling carrier 
 237 int CmdHF15Snoop(const char *Cmd
) 
 239         UsbCommand c 
= {CMD_SNOOP_ISO_15693
}; 
 244 int HF15Reader(const char *Cmd
, bool verbose
) 
 249                 if (verbose
) PrintAndLog("No Tag found."); 
 253         PrintAndLog("UID:               %s", sprintUID(NULL
,uid
)); 
 254         PrintAndLog("Manufacturer byte: %02X, %s", uid
[6], getManufacturerName(uid
[6])); 
 255         PrintAndLog("Chip ID:           %02X, %s", uid
[5], getChipInfo(uid
[6], uid
[5])); 
 259 int CmdHF15Reader(const char *Cmd
) 
 261         UsbCommand c 
= {CMD_READER_ISO_15693
, {strtol(Cmd
, NULL
, 0), 0, 0}}; 
 266 // Simulation is still not working very good 
 267 int CmdHF15Sim(const char *Cmd
) 
 269         char cmdp 
= param_getchar(Cmd
, 0); 
 270         uint8_t uid
[8] = {0x00}; 
 272         //E0 16 24 00 00 00 00 00 
 273         if (cmdp 
== 'h' || cmdp 
== 'H') { 
 274                 PrintAndLog("Usage:  hf 15 sim <UID>"); 
 276                 PrintAndLog("     sample: hf 15 sim E016240000000000"); 
 280         if (param_gethex(Cmd
, 0, uid
, 16)) { 
 281                 PrintAndLog("UID must include 16 HEX symbols"); 
 285         PrintAndLog("Starting simulating UID %02X %02X %02X %02X %02X %02X %02X %02X", 
 286                         uid
[0],uid
[1],uid
[2],uid
[3],uid
[4], uid
[5], uid
[6], uid
[7]); 
 287         PrintAndLog("Press the button to stop simulation"); 
 289         UsbCommand c 
= {CMD_SIMTAG_ISO_15693
, {0, 0, 0}}; 
 290         memcpy(c
.d
.asBytes
,uid
,8); 
 296 // finds the AFI (Application Family Idendifier) of a card, by trying all values 
 297 // (There is no standard way of reading the AFI, allthough some tags support this) 
 298 int CmdHF15Afi(const char *Cmd
) 
 300         UsbCommand c 
= {CMD_ISO_15693_FIND_AFI
, {strtol(Cmd
, NULL
, 0), 0, 0}}; 
 305 // Reads all memory pages 
 306 int CmdHF15DumpMem(const char*Cmd
) { 
 310         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
 311         uint8_t *req
=c
.d
.asBytes
; 
 317                 PrintAndLog("No Tag found."); 
 321         PrintAndLog("Reading memory from tag"); 
 322         PrintAndLog("UID:               %s", sprintUID(NULL
,uid
)); 
 323         PrintAndLog("Manufacturer byte: %02X, %s", uid
[6], getManufacturerName(uid
[6])); 
 324         PrintAndLog("Chip ID:           %02X, %s", uid
[5], getChipInfo(uid
[6], uid
[5])); 
 326         for (int retry
=0; retry
<5; retry
++) { 
 328                 req
[0]= ISO15693_REQ_DATARATE_HIGH 
| ISO15693_REQ_ADDRESS
; 
 329                 req
[1] = ISO15693_READBLOCK
; 
 330                 memcpy(&req
[2],uid
,8); 
 332                 reqlen 
= AddCrc(req
,11); 
 337                 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000)) { 
 338                         recv 
= resp
.d
.asBytes
; 
 339                         if (ISO15693_CRC_CHECK
==Crc(recv
,resp
.arg
[0])) { 
 340                                 if (!(recv
[0] & ISO15693_RES_ERROR
)) { 
 342                                         *output
=0; // reset outputstring 
 343                                         sprintf(output
, "Block %02x   ",blocknum
); 
 344                                         for ( int i
=1; i
<resp
.arg
[0]-2; i
++) { // data in hex 
 345                                                 sprintf(output
+strlen(output
),"%02X ",recv
[i
]); 
 348                                         for ( int i
=1; i
<resp
.arg
[0]-2; i
++) { // data in cleaned ascii 
 349                                                 sprintf(output
+strlen(output
),"%c",(recv
[i
]>31 && recv
[i
]<127)?recv
[i
]:'.');                                     
 351                                         PrintAndLog("%s",output
);        
 353                                         // PrintAndLog("bn=%i",blocknum); 
 355                                         PrintAndLog("Tag returned Error %i: %s",recv
[1],TagErrorStr(recv
[1]));  
 358                         } // else PrintAndLog("crc"); 
 359                 } // else PrintAndLog("r null"); 
 362 //      if (resp.arg[0]<3) 
 363 //              PrintAndLog("Lost Connection"); 
 364 //      else if (ISO15693_CRC_CHECK!=Crc(resp.d.asBytes,resp.arg[0])) 
 365 //              PrintAndLog("CRC Failed"); 
 367 //              PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));  
 374 static command_t CommandTable15
[] =  
 376         {"help",    CmdHF15Help
,    1, "This help"}, 
 377         {"demod",   CmdHF15Demod
,   1, "Demodulate ISO15693 from tag"}, 
 378         {"read",    CmdHF15Read
,    0, "Read HF tag (ISO 15693)"}, 
 379         {"snoop",   CmdHF15Snoop
,   0, "Eavesdrop ISO 15693 communications"}, 
 380         {"reader",  CmdHF15Reader
,  0, "Act like an ISO15693 reader"}, 
 381         {"sim",     CmdHF15Sim
,     0, "Fake an ISO15693 tag"}, 
 382         {"cmd",     CmdHF15Cmd
,     0, "Send direct commands to ISO15693 tag"}, 
 383         {"findafi", CmdHF15Afi
,     0, "Brute force AFI of an ISO15693 tag"}, 
 384         {"dumpmemory", CmdHF15DumpMem
,     0, "Read all memory pages of an ISO15693 tag"}, 
 385         {"csetuid",     CmdHF15CSetUID
, 0,      "Set UID for magic Chinese card"}, 
 386         {NULL
, NULL
, 0, NULL
} 
 389 int CmdHF15(const char *Cmd
) 
 391         CmdsParse(CommandTable15
, Cmd
); 
 395 int CmdHF15Help(const char *Cmd
) 
 397         CmdsHelp(CommandTable15
); 
 402 // "HF 15 Cmd" Interface 
 403 // Allows direct communication with the tag on command level 
 405 int CmdHF15CmdInquiry(const char *Cmd
)  
 409         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
 410         uint8_t *req
=c
.d
.asBytes
; 
 413         req
[0] = ISO15693_REQ_DATARATE_HIGH 
| ISO15693_REQ_INVENTORY 
| ISO15693_REQINV_SLOT1
; 
 414         req
[1] = ISO15693_INVENTORY
; 
 415         req
[2] = 0; // mask length 
 416         reqlen
=AddCrc(req
,3); 
 421         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000)) { 
 422                 if (resp
.arg
[0]>=12) { 
 423                         recv 
= resp
.d
.asBytes
; 
 424                         PrintAndLog("UID:               %s", sprintUID(NULL
,recv
+2)); 
 425                         PrintAndLog("Manufacturer byte: %02X, %s", recv
[8], getManufacturerName(recv
[8])); 
 426                         PrintAndLog("Chip ID:           %02X, %s", recv
[7], getChipInfo(recv
[8], recv
[7])); 
 428                         PrintAndLog("Response to short, just %i bytes. No tag?\n",resp
.arg
[0]); 
 431                 PrintAndLog("timeout."); 
 437 // Turns debugging on(1)/off(0) 
 438 int CmdHF15CmdDebug( const char *cmd
) { 
 439         int debug 
= atoi(cmd
); 
 440         if (strlen(cmd
) < 1) { 
 441                 PrintAndLog("Usage: hf 15 debug <0|1>"); 
 442                 PrintAndLog("   0 no debugging"); 
 443                 PrintAndLog("   1 turn debugging on");   
 447         UsbCommand c 
= {CMD_ISO_15693_DEBUG
, {debug
, 0, 0}}; 
 453 int CmdHF15CmdRaw (const char *cmd
) { 
 456         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
 463         unsigned int datalen
=0, temp
; 
 468                 PrintAndLog("Usage: hf 15 cmd raw  [-r] [-2] [-c] <0A 0B 0C ... hex>"); 
 469                 PrintAndLog("       -r    do not read response"); 
 470                 PrintAndLog("       -2    use slower '1 out of 256' mode"); 
 471                 PrintAndLog("       -c    calculate and append CRC"); 
 472                 PrintAndLog(" Tip: turn on debugging for verbose output");               
 477         while (*cmd
==' ' || *cmd
=='\t') cmd
++; 
 479         while (cmd
[i
]!='\0') { 
 480                 if (cmd
[i
]==' ' || cmd
[i
]=='\t') { i
++; continue; } 
 495                                         PrintAndLog("Invalid option"); 
 501                 if ((cmd
[i
]>='0' && cmd
[i
]<='9') || 
 502                     (cmd
[i
]>='a' && cmd
[i
]<='f') || 
 503                     (cmd
[i
]>='A' && cmd
[i
]<='F') ) { 
 504                     buf
[strlen(buf
)+1]=0; 
 505                     buf
[strlen(buf
)]=cmd
[i
]; 
 508                     if (strlen(buf
)>=2) { 
 509                         sscanf(buf
,"%x",&temp
); 
 510                         data
[datalen
]=(uint8_t)(temp 
& 0xff); 
 516                 PrintAndLog("Invalid char on input"); 
 519         if (crc
) datalen
=AddCrc(data
,datalen
); 
 524         memcpy(c
.d
.asBytes
,data
,datalen
); 
 529                 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000)) { 
 530                         recv 
= resp
.d
.asBytes
; 
 531                         PrintAndLog("received %i octets",resp
.arg
[0]); 
 532                         hexout 
= (char *)malloc(resp
.arg
[0] * 3 + 1); 
 533                         if (hexout 
!= NULL
) { 
 534                                 for (int i 
= 0; i 
< resp
.arg
[0]; i
++) { // data in hex 
 535                                         sprintf(&hexout
[i 
* 3], "%02X ", recv
[i
]); 
 537                                 PrintAndLog("%s", hexout
); 
 541                         PrintAndLog("timeout while waiting for reply."); 
 550  * parses common HF 15 CMD parameters and prepares some data structures 
 554 int prepareHF15Cmd(char **cmd
, UsbCommand 
*c
, uint8_t iso15cmd
[], int iso15cmdlen
) { 
 556         uint8_t *req
=c
->d
.asBytes
; 
 557         uint8_t uid
[8] = {0x00}; 
 561         while (**cmd
==' ' || **cmd
=='\t') (*cmd
)++; 
 563         if (strstr(*cmd
,"-2")==*cmd
) { 
 564                 c
->arg
[1]=0; // use 1of256 
 569         while (**cmd
==' ' || **cmd
=='\t') (*cmd
)++; 
 571         if (strstr(*cmd
,"-o")==*cmd
) { 
 572                 req
[reqlen
]=ISO15693_REQ_OPTION
; 
 577         while (**cmd
==' ' || **cmd
=='\t') (*cmd
)++; 
 581                         PrintAndLog("missing addr"); 
 586                         // you must have selected the tag earlier 
 587                         req
[reqlen
++] |= ISO15693_REQ_DATARATE_HIGH 
| ISO15693_REQ_SELECT
; 
 588                         memcpy(&req
[reqlen
],&iso15cmd
[0],iso15cmdlen
); 
 589                         reqlen 
+= iso15cmdlen
;              
 593                         // unaddressed mode may not be supported by all vendors 
 594                         req
[reqlen
++] |= ISO15693_REQ_DATARATE_HIGH
; 
 595                         memcpy(&req
[reqlen
],&iso15cmd
[0],iso15cmdlen
); 
 596                         reqlen 
+= iso15cmdlen
;              
 599                         // we scan for the UID ourself 
 600                         req
[reqlen
++] |= ISO15693_REQ_DATARATE_HIGH 
| ISO15693_REQ_ADDRESS
; 
 601                         memcpy(&req
[reqlen
],&iso15cmd
[0],iso15cmdlen
); 
 604                                 PrintAndLog("No Tag found"); 
 607                         memcpy(req
+reqlen
,uid
,8); 
 608                         PrintAndLog("Detected UID %s",sprintUID(NULL
,uid
)); 
 612                         req
[reqlen
++] |= ISO15693_REQ_DATARATE_HIGH 
| ISO15693_REQ_ADDRESS
; 
 613                         memcpy(&req
[reqlen
],&iso15cmd
[0],iso15cmdlen
); 
 616 /*                      sscanf(cmd,"%hX%hX%hX%hX%hX%hX%hX%hX", 
 617                                 (short unsigned int *)&uid[7],(short unsigned int *)&uid[6], 
 618                                 (short unsigned int *)&uid[5],(short unsigned int *)&uid[4], 
 619                                 (short unsigned int *)&uid[3],(short unsigned int *)&uid[2], 
 620                                 (short unsigned int *)&uid[1],(short unsigned int *)&uid[0]); */ 
 621                         for (int i
=0;i
<8 && (*cmd
)[i
*2] && (*cmd
)[i
*2+1];i
++) { // parse UID 
 622                                 sscanf((char[]){(*cmd
)[i
*2],(*cmd
)[i
*2+1],0},"%X",&temp
); 
 626                         PrintAndLog("Using UID %s",sprintUID(NULL
,uid
)); 
 627                         memcpy(&req
[reqlen
],&uid
[0],8);             
 630         // skip to next space            
 631         while (**cmd
!=' ' && **cmd
!='\t') (*cmd
)++; 
 632         // skip over the space 
 633         while (**cmd
==' ' || **cmd
=='\t') (*cmd
)++; 
 640  * Commandline handling: HF15 CMD SYSINFO 
 641  * get system information from tag/VICC 
 643 int CmdHF15CmdSysinfo(const char *Cmd
) { 
 646         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
 647         uint8_t *req
=c
.d
.asBytes
; 
 651         char output
[2048]=""; 
 658                 PrintAndLog("Usage:  hf 15 cmd sysinfo    [options] <uid|s|u|*>"); 
 659                 PrintAndLog("           options:"); 
 660                 PrintAndLog("               -2        use slower '1 out of 256' mode"); 
 661                 PrintAndLog("           uid (either): "); 
 662                 PrintAndLog("               <8B hex>  full UID eg E011223344556677"); 
 663                 PrintAndLog("               s         selected tag"); 
 664                 PrintAndLog("               u         unaddressed mode"); 
 665                 PrintAndLog("               *         scan for tag"); 
 666                 PrintAndLog("           start#:       page number to start 0-255");   
 667                 PrintAndLog("           count#:       number of pages");   
 671         prepareHF15Cmd(&cmd
, &c
,(uint8_t[]){ISO15693_GET_SYSTEM_INFO
},1);        
 674         reqlen
=AddCrc(req
,reqlen
); 
 679         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000) && resp
.arg
[0]>2) { 
 680                 recv 
= resp
.d
.asBytes
; 
 681                 if (ISO15693_CRC_CHECK
==Crc(recv
,resp
.arg
[0])) { 
 682                         if (!(recv
[0] & ISO15693_RES_ERROR
)) { 
 683                                 *output
=0; // reset outputstring 
 684                                 PrintAndLog("UID:               %s", sprintUID(NULL
,recv
+2)); 
 685                                 PrintAndLog("Manufacturer byte: %02X, %s", recv
[8], getManufacturerName(recv
[8])); 
 686                                 PrintAndLog("Chip ID:           %02X, %s", recv
[7], getChipInfo(recv
[8], recv
[7])); 
 689                                         sprintf(output
+strlen(output
),"DSFID supported, set to %02X\n\r",recv
[i
++]); 
 691                                         strcat(output
,"DSFID not supported\n\r"); 
 693                                         sprintf(output
+strlen(output
),"AFI supported, set to %03X\n\r",recv
[i
++]); 
 695                                         strcat(output
,"AFI not supported\n\r"); 
 696                                 if (recv
[1] & 0x04) { 
 697                                         strcat(output
,"Tag provides info on memory layout (vendor dependent)\n\r"); 
 698                                         sprintf(output
+strlen(output
)," %i (or %i) bytes/page x %i pages \n\r", 
 699                                                         (recv
[i
+1]&0x1F)+1, (recv
[i
+1]&0x1F), recv
[i
]+1); 
 702                                         strcat(output
,"Tag does not provide information on memory layout\n\r"); 
 703                                 if (recv
[1] & 0x08) sprintf(output
+strlen(output
),"IC reference given: %02X\n\r",recv
[i
++]); 
 704                                         else strcat(output
,"IC reference not given\n\r"); 
 707                                 PrintAndLog("%s",output
);        
 709                                 PrintAndLog("Tag returned Error %i: %s",recv
[0],TagErrorStr(recv
[0]));  
 712                         PrintAndLog("CRC failed"); 
 715                 PrintAndLog("timeout: no answer"); 
 722  * Commandline handling: HF15 CMD READMULTI 
 723  * Read multiple blocks at once (not all tags support this) 
 725 int CmdHF15CmdReadmulti(const char *Cmd
) { 
 728         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
 729         uint8_t *req
=c
.d
.asBytes
; 
 730         int reqlen
=0, pagenum
,pagecount
; 
 733         char output
[2048]=""; 
 739                 PrintAndLog("Usage:  hf 15 cmd readmulti  [options] <uid|s|u|*> <start#> <count#>"); 
 740                 PrintAndLog("           options:"); 
 741                 PrintAndLog("               -2        use slower '1 out of 256' mode"); 
 742                 PrintAndLog("           uid (either): "); 
 743                 PrintAndLog("               <8B hex>  full UID eg E011223344556677"); 
 744                 PrintAndLog("               s         selected tag"); 
 745                 PrintAndLog("               u         unaddressed mode"); 
 746                 PrintAndLog("               *         scan for tag"); 
 747                 PrintAndLog("           start#:       page number to start 0-255");   
 748                 PrintAndLog("           count#:       number of pages");   
 752         prepareHF15Cmd(&cmd
, &c
,(uint8_t[]){ISO15693_READ_MULTI_BLOCK
},1);       
 755         pagenum
=strtol(cmd
,NULL
,0); 
 757         // skip to next space            
 758         while (*cmd
!=' ' && *cmd
!='\t') cmd
++; 
 759         // skip over the space 
 760         while (*cmd
==' ' || *cmd
=='\t') cmd
++; 
 762         pagecount
=strtol(cmd
,NULL
,0); 
 763         if (pagecount
>0) pagecount
--; // 0 means 1 page, 1 means 2 pages, ...    
 765         req
[reqlen
++]=(uint8_t)pagenum
; 
 766         req
[reqlen
++]=(uint8_t)pagecount
; 
 768         reqlen
=AddCrc(req
,reqlen
); 
 774         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000) && resp
.arg
[0]>2) { 
 775                 recv 
= resp
.d
.asBytes
; 
 776                 if (ISO15693_CRC_CHECK
==Crc(recv
,resp
.arg
[0])) { 
 777                         if (!(recv
[0] & ISO15693_RES_ERROR
)) { 
 778                                 *output
=0; // reset outputstring 
 779                                 for ( int i
=1; i
<resp
.arg
[0]-2; i
++) { 
 780                                         sprintf(output
+strlen(output
),"%02X ",recv
[i
]); 
 783                                 for ( int i
=1; i
<resp
.arg
[0]-2; i
++) { 
 784                                         sprintf(output
+strlen(output
),"%c",recv
[i
]>31 && recv
[i
]<127?recv
[i
]:'.');                                       
 786                                 PrintAndLog("%s",output
);        
 788                                 PrintAndLog("Tag returned Error %i: %s",recv
[0],TagErrorStr(recv
[0]));  
 791                         PrintAndLog("CRC failed"); 
 794                 PrintAndLog("no answer"); 
 801  * Commandline handling: HF15 CMD READ 
 802  * Reads a single Block 
 804 int CmdHF15CmdRead(const char *Cmd
) { 
 807         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
 808         uint8_t *req
=c
.d
.asBytes
; 
 809         int reqlen
=0, pagenum
; 
 818                 PrintAndLog("Usage:  hf 15 cmd read    [options] <uid|s|u|*> <page#>"); 
 819                 PrintAndLog("           options:"); 
 820                 PrintAndLog("               -2        use slower '1 out of 256' mode"); 
 821                 PrintAndLog("           uid (either): "); 
 822                 PrintAndLog("               <8B hex>  full UID eg E011223344556677"); 
 823                 PrintAndLog("               s         selected tag"); 
 824                 PrintAndLog("               u         unaddressed mode"); 
 825                 PrintAndLog("               *         scan for tag"); 
 826                 PrintAndLog("           page#:        page number 0-255");   
 830         prepareHF15Cmd(&cmd
, &c
,(uint8_t[]){ISO15693_READBLOCK
},1);      
 833         pagenum
=strtol(cmd
,NULL
,0); 
 835                 PrintAndLog("invalid pagenum"); 
 839         req
[reqlen
++]=(uint8_t)pagenum
; 
 841         reqlen
=AddCrc(req
,reqlen
); 
 847         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000) && resp
.arg
[0]>2) { 
 848                 recv 
= resp
.d
.asBytes
; 
 849                 if (ISO15693_CRC_CHECK
==Crc(recv
,resp
.arg
[0])) { 
 850                         if (!(recv
[0] & ISO15693_RES_ERROR
)) { 
 851                                 *output
=0; // reset outputstring 
 852                                 //sprintf(output, "Block %2i   ",blocknum); 
 853                                 for ( int i
=1; i
<resp
.arg
[0]-2; i
++) { 
 854                                         sprintf(output
+strlen(output
),"%02X ",recv
[i
]); 
 857                                 for ( int i
=1; i
<resp
.arg
[0]-2; i
++) { 
 858                                         sprintf(output
+strlen(output
),"%c",recv
[i
]>31 && recv
[i
]<127?recv
[i
]:'.');                                       
 860                                 PrintAndLog("%s",output
);        
 862                                 PrintAndLog("Tag returned Error %i: %s",recv
[1],TagErrorStr(recv
[1]));  
 865                         PrintAndLog("CRC failed"); 
 868                 PrintAndLog("no answer"); 
 876  * Commandline handling: HF15 CMD WRITE 
 877  * Writes a single Block - might run into timeout, even when successful 
 879 int CmdHF15CmdWrite(const char *Cmd
) { 
 882         UsbCommand c 
= {CMD_ISO_15693_COMMAND
, {0, 1, 1}}; // len,speed,recv? 
 883         uint8_t *req
=c
.d
.asBytes
; 
 884         int reqlen
=0, pagenum
, temp
; 
 893                 PrintAndLog("Usage:  hf 15 cmd write    [options] <uid|s|u|*> <page#> <hexdata>"); 
 894                 PrintAndLog("           options:"); 
 895                 PrintAndLog("               -2        use slower '1 out of 256' mode"); 
 896                 PrintAndLog("               -o        set OPTION Flag (needed for TI)"); 
 897                 PrintAndLog("           uid (either): "); 
 898                 PrintAndLog("               <8B hex>  full UID eg E011223344556677"); 
 899                 PrintAndLog("               s         selected tag"); 
 900                 PrintAndLog("               u         unaddressed mode"); 
 901                 PrintAndLog("               *         scan for tag"); 
 902                 PrintAndLog("           page#:        page number 0-255");   
 903                 PrintAndLog("           hexdata:      data to be written eg AA BB CC DD");   
 907         prepareHF15Cmd(&cmd
, &c
,(uint8_t[]){ISO15693_WRITEBLOCK
},1);     
 910         // *cmd -> page num ; *cmd2 -> data  
 912         while (*cmd2
!=' ' && *cmd2
!='\t' && *cmd2
) cmd2
++; 
 916         pagenum
=strtol(cmd
,NULL
,0); 
 918                 PrintAndLog("invalid pagenum"); 
 921         req
[reqlen
++]=(uint8_t)pagenum
; 
 924         while (cmd2
[0] && cmd2
[1]) { // hexdata, read by 2 hexchars  
 929                 sscanf((char[]){cmd2
[0],cmd2
[1],0},"%X",&temp
); 
 930                 req
[reqlen
++]=temp 
& 0xff; 
 934         reqlen
=AddCrc(req
,reqlen
); 
 940         if (WaitForResponseTimeout(CMD_ACK
,&resp
,2000) && resp
.arg
[0]>2) { 
 941                 recv 
= resp
.d
.asBytes
; 
 942                 if (ISO15693_CRC_CHECK
==Crc(recv
,resp
.arg
[0])) { 
 943                         if (!(recv
[0] & ISO15693_RES_ERROR
)) {                                   
 946                                 PrintAndLog("Tag returned Error %i: %s",recv
[1],TagErrorStr(recv
[1]));  
 949                         PrintAndLog("CRC failed"); 
 952                 PrintAndLog("timeout: no answer - data may be written anyway"); 
 958 int CmdHF15CSetUID(const char *Cmd
) 
 960   uint8_t uid
[8] = {0x00}; 
 961   uint8_t oldUid
[8], newUid
[8] = {0x00}; 
 963   uint8_t needHelp 
= 0; 
 966   if (param_getchar(Cmd
, 0) && param_gethex(Cmd
, 0, uid
, 16)) {  
 967     PrintAndLog("UID must include 16 HEX symbols"); 
 971   if (uid
[0] != 0xe0) { 
 972     PrintAndLog("UID must begin with the byte 'E0'"); 
 976   while(param_getchar(Cmd
, cmdp
) != 0x00) 
 978     switch(param_getchar(Cmd
, cmdp
)) 
 985       PrintAndLog("ERROR: Unknown parameter '%c'", param_getchar(Cmd
, cmdp
)); 
 992   if (strlen(Cmd
) < 1 || needHelp
) { 
 994     PrintAndLog("Usage:  hf 15 csetuid <UID 16 hex symbols>"); 
 995     PrintAndLog("sample:  hf 15 csetuid E004013344556677"); 
 996     PrintAndLog("Set UID for magic Chinese card (only works with such cards)"); 
1001   PrintAndLog("new UID | %s", sprint_hex(uid
, 8)); 
1002   PrintAndLog("Using backdoor Magic tag function"); 
1004   if (!getUID(oldUid
)) { 
1005     PrintAndLog("Can't get old UID."); 
1012   UsbCommand c 
= {CMD_CSETUID_ISO_15693
, {0, 0, 0}}; 
1013   memcpy(c
.d
.asBytes
, uid
, 8); 
1017   for (int i
=0; i
<4; i
++) { 
1018     if (WaitForResponseTimeout(CMD_ACK
,&resp
,1000)) { 
1019       recv 
= resp
.d
.asBytes
; 
1020       PrintAndLog("received %i octets",resp
.arg
[0]); 
1021       hexout 
= (char *)malloc(resp
.arg
[0] * 3 + 1); 
1022       if (hexout 
!= NULL
) { 
1023         for (int i 
= 0; i 
< resp
.arg
[0]; i
++) { // data in hex 
1024           sprintf(&hexout
[i 
* 3], "%02X ", recv
[i
]); 
1026         PrintAndLog("%s", hexout
); 
1030       PrintAndLog("timeout while waiting for reply."); 
1034   if (!getUID(newUid
)) { 
1035     PrintAndLog("Can't get new UID."); 
1040   PrintAndLog("old UID : %02X %02X %02X %02X %02X %02X %02X %02X", oldUid
[7], oldUid
[6], oldUid
[5], oldUid
[4], oldUid
[3], oldUid
[2], oldUid
[1], oldUid
[0]); 
1041   PrintAndLog("new UID : %02X %02X %02X %02X %02X %02X %02X %02X", newUid
[7], newUid
[6], newUid
[5], newUid
[4], newUid
[3], newUid
[2], newUid
[1], newUid
[0]); 
1046 static command_t CommandTable15Cmd
[] = 
1048         {"help",    CmdHF15CmdHelp
,    1, "This Help"}, 
1049         {"inquiry", CmdHF15CmdInquiry
, 0, "Search for tags in range"}, 
1051         {"select",  CmdHF15CmdSelect, 0, "Select an tag with a specific UID for further commands"}, 
1053         {"read",    CmdHF15CmdRead
,    0, "Read a block"},       
1054         {"write",   CmdHF15CmdWrite
,    0, "Write a block"},     
1055         {"readmulti",CmdHF15CmdReadmulti
,    0, "Reads multiple Blocks"}, 
1056         {"sysinfo",CmdHF15CmdSysinfo
,    0, "Get Card Information"}, 
1057         {"raw",          CmdHF15CmdRaw
,         0,      "Send raw hex data to tag"}, 
1058         {"csetuid",     CmdHF15CSetUID
, 0,      "Set UID for magic Chinese card"}, 
1059         {"debug",    CmdHF15CmdDebug
,    0, "Turn debugging on/off"}, 
1060         {NULL
, NULL
, 0, NULL
} 
1063 int CmdHF15Cmd(const char *Cmd
) 
1065         CmdsParse(CommandTable15Cmd
, Cmd
); 
1069 int CmdHF15CmdHelp(const char *Cmd
) 
1071         CmdsHelp(CommandTable15Cmd
);