1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2014 Iceman 
   4 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   5 // at your option, any later version. See the LICENSE.txt file for the text of 
   7 //----------------------------------------------------------------------------- 
   8 // High frequency MIFARE Desfire commands 
   9 //----------------------------------------------------------------------------- 
  15 //#include <openssl/des.h> 
  16 #include "loclass/des.h" 
  18 #include "proxmark3.h" 
  19 #include "../include/common.h" 
  20 #include "../include/mifare.h" 
  21 #include "../common/iso14443crc.h" 
  24 #include "cmdparser.h" 
  26 #include "cmdhfmfdes.h" 
  31 uint8_t key_zero_data
[16] = { 0x00 }; 
  32 uint8_t key_ones_data
[16] = { 0x01 }; 
  33 uint8_t key_defa_data
[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; 
  34 uint8_t key_picc_data
[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f }; 
  36 static int CmdHelp(const char *Cmd
); 
  37 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
); 
  38 static int32_t le24toh (uint8_t data
[3]); 
  41 int CmdHF14ADesWb(const char *Cmd
) 
  43 /*      uint8_t blockNo = 0; 
  45         uint8_t key[6] = {0, 0, 0, 0, 0, 0}; 
  46         uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
  51                 PrintAndLog("Usage:  hf mf wrbl    <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>"); 
  52                 PrintAndLog("        sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); 
  56         blockNo = param_get8(Cmd, 0); 
  57         cmdp = param_getchar(Cmd, 1); 
  59                 PrintAndLog("Key type must be A or B"); 
  62         if (cmdp != 'A' && cmdp != 'a') keyType = 1; 
  63         if (param_gethex(Cmd, 2, key, 12)) { 
  64                 PrintAndLog("Key must include 12 HEX symbols"); 
  67         if (param_gethex(Cmd, 3, bldata, 32)) { 
  68                 PrintAndLog("Block data must include 32 HEX symbols"); 
  71         PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6)); 
  72         PrintAndLog("--data: %s", sprint_hex(bldata, 16)); 
  74   UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; 
  75         memcpy(c.d.asBytes, key, 6); 
  76         memcpy(c.d.asBytes + 10, bldata, 16); 
  80         if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { 
  81                 uint8_t isOK  = resp.arg[0] & 0xff; 
  82                 PrintAndLog("isOk:%02x", isOK); 
  84                 PrintAndLog("Command execute timeout"); 
  90 int CmdHF14ADesRb(const char *Cmd
) 
  92         // uint8_t blockNo = 0; 
  93         // uint8_t keyType = 0; 
  94         // uint8_t key[6] = {0, 0, 0, 0, 0, 0}; 
  99         // if (strlen(Cmd)<3) { 
 100                 // PrintAndLog("Usage:  hf mf rdbl    <block number> <key A/B> <key (12 hex symbols)>"); 
 101                 // PrintAndLog("        sample: hf mf rdbl 0 A FFFFFFFFFFFF "); 
 105         // blockNo = param_get8(Cmd, 0); 
 106         // cmdp = param_getchar(Cmd, 1); 
 107         // if (cmdp == 0x00) { 
 108                 // PrintAndLog("Key type must be A or B"); 
 111         // if (cmdp != 'A' && cmdp != 'a') keyType = 1; 
 112         // if (param_gethex(Cmd, 2, key, 12)) { 
 113                 // PrintAndLog("Key must include 12 HEX symbols"); 
 116         // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); 
 118   // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; 
 119         // memcpy(c.d.asBytes, key, 6); 
 123         // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { 
 124                 // uint8_t                isOK  = resp.arg[0] & 0xff; 
 125                 // uint8_t              * data  = resp.d.asBytes; 
 128                         // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16)); 
 130                         // PrintAndLog("isOk:%02x", isOK); 
 132                 // PrintAndLog("Command execute timeout"); 
 138 int CmdHF14ADesInfo(const char *Cmd
){ 
 140         UsbCommand c 
= {CMD_MIFARE_DESFIRE_INFO
}; 
 144         if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 145                 PrintAndLog("Command execute timeout"); 
 148         uint8_t isOK  
= resp
.arg
[0] & 0xff; 
 150                 PrintAndLog("Command unsuccessful"); 
 154         PrintAndLog("-- Desfire Information --------------------------------------"); 
 155         PrintAndLog("-------------------------------------------------------------"); 
 156         PrintAndLog("  UID                : %s",sprint_hex(resp
.d
.asBytes
, 7)); 
 157         PrintAndLog("  Batch number       : %s",sprint_hex(resp
.d
.asBytes
+28,5)); 
 158         PrintAndLog("  Production date    : week %02x, 20%02x",resp
.d
.asBytes
[33], resp
.d
.asBytes
[34]); 
 159         PrintAndLog("  -----------------------------------------------------------"); 
 160         PrintAndLog("  Hardware Information"); 
 161         PrintAndLog("      Vendor Id      : %s", GetVendorStr(resp
.d
.asBytes
[7])); 
 162         PrintAndLog("      Type           : 0x%02X",resp
.d
.asBytes
[8]); 
 163         PrintAndLog("      Subtype        : 0x%02X",resp
.d
.asBytes
[9]); 
 164         PrintAndLog("      Version        : %d.%d",resp
.d
.asBytes
[10], resp
.d
.asBytes
[11]); 
 165         PrintAndLog("      Storage size   : %s",GetCardSizeStr(resp
.d
.asBytes
[12])); 
 166         PrintAndLog("      Protocol       : %s",GetProtocolStr(resp
.d
.asBytes
[13])); 
 167         PrintAndLog("  -----------------------------------------------------------"); 
 168         PrintAndLog("  Software Information"); 
 169         PrintAndLog("      Vendor Id      : %s",GetVendorStr(resp
.d
.asBytes
[14])); 
 170         PrintAndLog("      Type           : 0x%02X",resp
.d
.asBytes
[15]); 
 171         PrintAndLog("      Subtype        : 0x%02X",resp
.d
.asBytes
[16]); 
 172         PrintAndLog("      Version        : %d.%d",resp
.d
.asBytes
[17], resp
.d
.asBytes
[18]); 
 173         PrintAndLog("      storage size   : %s", GetCardSizeStr(resp
.d
.asBytes
[19])); 
 174         PrintAndLog("      Protocol       : %s", GetProtocolStr(resp
.d
.asBytes
[20])); 
 175         PrintAndLog("-------------------------------------------------------------"); 
 177         // Master Key settings 
 178         GetKeySettings(NULL
); 
 180         // Free memory on card 
 181         c
.cmd 
= CMD_MIFARE_DESFIRE
; 
 182         c
.arg
[0] = (INIT 
| DISCONNECT
); 
 184         c
.d
.asBytes
[0] = GET_FREE_MEMORY
; 
 186         if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 191         memcpy(tmp
, resp
.d
.asBytes
+3,3);  
 193         PrintAndLog("   Available free memory on card       : %d bytes", le24toh( tmp 
)); 
 194         PrintAndLog("-------------------------------------------------------------"); 
 197                 Card Master key (CMK)        0x00 AID = 00 00 00 (card level) 
 198                 Application Master Key (AMK) 0x00 AID != 00 00 00 
 199                 Application keys (APK)       0x01-0x0D 
 200                 Application free             0x0E 
 201                 Application never            0x0F 
 214 char * GetVendorStr( uint8_t id
){ 
 219                 sprintf(retStr
, "0x%02X (NXP)",id
); 
 221                 sprintf(retStr
,"0x%02X (Unknown)",id
); 
 226   The 7 MSBits (= n) code the storage size itself based on 2^n,  
 227   the LSBit is set to '0' if the size is exactly 2^n 
 228         and set to '1' if the storage size is between 2^n and 2^(n+1).  
 229         For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'. 
 231 char * GetCardSizeStr( uint8_t fsize 
){ 
 236         uint16_t usize 
= 1 << ((fsize 
>>1) + 1); 
 237         uint16_t lsize 
= 1 << (fsize 
>>1); 
 241                 sprintf(retStr
, "0x%02X (%d - %d bytes)",fsize
, usize
, lsize
); 
 243                 sprintf(retStr
, "0x%02X (%d bytes)", fsize
, lsize
);              
 247 char * GetProtocolStr(uint8_t id
){ 
 253                 sprintf(retStr
,"0x%02X (ISO 14443-3, 14443-4)", id
); 
 255                 sprintf(retStr
,"0x%02X (Unknown)", id
);  
 259 void GetKeySettings( uint8_t *aid
){ 
 261         char messStr
[512] = {0x00}; 
 264         uint32_t options 
= NONE
; 
 268         //memset(messStr, 0x00, 512); 
 270         c
.cmd 
= CMD_MIFARE_DESFIRE
; 
 273                 PrintAndLog(" CMK - PICC, Card Master Key settings "); 
 275                 c
.arg
[CMDPOS
] = (INIT 
| DISCONNECT
); 
 276                 c
.arg
[LENPOS
] =  0x01; 
 277                 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
;  // 0x45 
 279                 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;}   
 280                 isOK  
= resp
.arg
[0] & 0xff; 
 282                         PrintAndLog("   Can't select master application");       
 286                 str 
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";      
 287                 PrintAndLog("   [0x08] Configuration changeable       : %s", str
); 
 288                 str 
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES"; 
 289                 PrintAndLog("   [0x04] CMK required for create/delete : %s",str
); 
 290                 str 
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES"; 
 291                 PrintAndLog("   [0x02] Directory list access with CMK : %s",str
); 
 292                 str 
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO"; 
 293                 PrintAndLog("   [0x01] CMK is changeable              : %s", str
); 
 295                 c
.arg
[LENPOS
] = 0x02; //LEN 
 296                 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64 
 297                 c
.d
.asBytes
[1] = 0x00; 
 299                 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) { 
 302                 isOK  
= resp
.arg
[0] & 0xff; 
 304                         PrintAndLog("   Can't read key-version"); 
 308                 PrintAndLog("   Max number of keys       : %d", resp
.d
.asBytes
[4]); 
 309                 PrintAndLog("   Master key Version       : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]); 
 310                 PrintAndLog("   ----------------------------------------------------------"); 
 312                 c
.arg
[LENPOS
] = 0x02; //LEN 
 313                 c
.d
.asBytes
[0] = AUTHENTICATE
; //0x0A 
 314                 c
.d
.asBytes
[1] = 0x00; // KEY 0 
 316                 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;} 
 317                 isOK  
= resp
.d
.asBytes
[2] & 0xff; 
 318                 PrintAndLog("   [0x0A] Authenticate      : %s", ( isOK
==0xAE ) ? "NO":"YES"); 
 320                 c
.d
.asBytes
[0] = AUTHENTICATE_ISO
; //0x1A 
 322                 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;} 
 323                 isOK  
= resp
.d
.asBytes
[2] & 0xff; 
 324                 PrintAndLog("   [0x1A] Authenticate ISO  : %s", ( isOK
==0xAE ) ? "NO":"YES"); 
 326                 c
.d
.asBytes
[0] = AUTHENTICATE_AES
; //0xAA 
 328                 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1000) ) {return;} 
 329                 isOK  
= resp
.d
.asBytes
[2] & 0xff; 
 330                 PrintAndLog("   [0xAA] Authenticate AES  : %s", ( isOK
==0xAE ) ? "NO":"YES"); 
 332                 PrintAndLog("   ----------------------------------------------------------"); 
 335                 PrintAndLog(" AMK - Application Master Key settings"); 
 338                 c
.arg
[0] = (INIT 
| CLEARTRACE
); 
 339                 c
.arg
[LENPOS
] = 0x04; 
 340                 c
.d
.asBytes
[0] = SELECT_APPLICATION
;  // 0x5a 
 341                 memcpy(c
.d
.asBytes
+1, aid
, 3); 
 344                 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 345                         PrintAndLog("   Timed-out"); 
 348                 isOK  
= resp
.arg
[0] & 0xff; 
 350                         PrintAndLog("   Can't select AID: %s",sprint_hex(aid
,3));        
 357                 c
.arg
[LENPOS
] = 0x01; 
 358                 c
.d
.asBytes
[0] = GET_KEY_SETTINGS
; // 0x45               
 360                 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 363                 isOK  
= resp
.arg
[0] & 0xff; 
 365                         PrintAndLog("   Can't read Application Master key settings"); 
 368                         uint8_t rights 
= (resp
.d
.asBytes
[3] >> 4 && 0xff); 
 371                                         str 
= "AMK authentication is necessary to change any key (default)"; 
 374                                         str 
= "Authentication with the key to be changed (same KeyNo) is necessary to change a key"; 
 377                                         str 
= "All keys (except AMK,see Bit0) within this application are frozen"; 
 380                                         str 
= "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed."; 
 383                         PrintAndLog("Changekey Access rights"); 
 384                         PrintAndLog("-- %s",str
); 
 387                         str 
= (resp
.d
.asBytes
[3] & (1 << 3 )) ? "YES":"NO";      
 388                         PrintAndLog("   0x08 Configuration changeable       : %s", str
); 
 389                         str 
= (resp
.d
.asBytes
[3] & (1 << 2 )) ? "NO":"YES"; 
 390                         PrintAndLog("   0x04 AMK required for create/delete : %s",str
); 
 391                         str 
= (resp
.d
.asBytes
[3] & (1 << 1 )) ? "NO":"YES"; 
 392                         PrintAndLog("   0x02 Directory list access with AMK : %s",str
); 
 393                         str 
= (resp
.d
.asBytes
[3] & (1 << 0 )) ? "YES" : "NO"; 
 394                         PrintAndLog("   0x01 AMK is changeable              : %s", str
); 
 399                 c
.arg
[LENPOS
] = 0x02; 
 400                 c
.d
.asBytes
[0] = GET_KEY_VERSION
; //0x64 
 401                 c
.d
.asBytes
[1] = 0x00; 
 403                 if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 404                         PrintAndLog("   Timed-out"); 
 410                 isOK  
= resp
.arg
[0] & 0xff; 
 412                         PrintAndLog("   Can't read Application Master key version. Trying all keys"); 
 413                         numOfKeys 
= MAX_NUM_KEYS
; 
 416                         numOfKeys 
= resp
.d
.asBytes
[4]; 
 418                         PrintAndLog("     Max number of keys  : %d", numOfKeys 
); 
 419                         PrintAndLog("     Application Master key Version  : %d (0x%02x)", resp
.d
.asBytes
[3], resp
.d
.asBytes
[3]); 
 420                         PrintAndLog("-------------------------------------------------------------");                    
 423                 // LOOP over numOfKeys that we got before.  
 424                 // From 0x01 to numOfKeys.  We already got 0x00. (AMK) 
 425                 for(int i
=0x01; i
<=0x0f; ++i
){ 
 433 int CmdHF14ADesEnumApplications(const char *Cmd
){ 
 437         uint32_t options 
= (INIT 
| DISCONNECT
); 
 439         UsbCommand c 
= {CMD_MIFARE_DESFIRE
, {options 
, 0x01 }}; 
 440         c
.d
.asBytes
[0] = GET_APPLICATION_IDS
;  //0x6a 
 445         if ( !WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 448         isOK  
= resp
.arg
[0] & 0xff; 
 450                 PrintAndLog("Command unsuccessful"); 
 454         PrintAndLog("-- Desfire Enumerate Applications ---------------------------"); 
 455         PrintAndLog("-------------------------------------------------------------"); 
 458         UsbCommand respFiles
; 
 461         int max 
= resp
.arg
[1] -3 -2; 
 463         for(int i
=3; i
<=max
; i
+=3){ 
 464                 PrintAndLog(" Aid %d : %02X %02X %02X ",num 
,resp
.d
.asBytes
[i
],resp
.d
.asBytes
[i
+1],resp
.d
.asBytes
[i
+2]); 
 467                 aid
[0] = resp
.d
.asBytes
[i
]; 
 468                 aid
[1] = resp
.d
.asBytes
[i
+1]; 
 469                 aid
[2] = resp
.d
.asBytes
[i
+2]; 
 472                 // Select Application 
 473                 c
.arg
[CMDPOS
] = INIT
; 
 474                 c
.arg
[LENPOS
] = 0x04;  
 475                 c
.d
.asBytes
[0] = SELECT_APPLICATION
;  // 0x5a 
 476                 c
.d
.asBytes
[1] = resp
.d
.asBytes
[i
]; 
 477                 c
.d
.asBytes
[2] = resp
.d
.asBytes
[i
+1];            
 478                 c
.d
.asBytes
[3] = resp
.d
.asBytes
[i
+2]; 
 481                 if (!WaitForResponseTimeout(CMD_ACK
,&respAid
,1500) ) { 
 482                         PrintAndLog("   Timed-out"); 
 485                 isOK  
= respAid
.d
.asBytes
[2] & 0xff; 
 487                         PrintAndLog("   Can't select AID: %s",sprint_hex(resp
.d
.asBytes
+i
,3));   
 492                 c
.arg
[CMDPOS
] = NONE
; 
 493                 c
.arg
[LENPOS
] = 0x01; 
 494                 c
.d
.asBytes
[0] = GET_FILE_IDS
; // 0x6f 
 497                 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) { 
 498                         PrintAndLog("   Timed-out"); 
 501                         isOK  
= respFiles
.d
.asBytes
[2] & 0xff; 
 503                                 PrintAndLog("   Can't get file ids "); 
 505                                 int respfileLen 
= resp
.arg
[1]-3-2;                       
 506                                 for (int j
=0; j
< respfileLen
; ++j
){ 
 507                                         PrintAndLog("   Fileid %d :", resp
.d
.asBytes
[j
+3]); 
 513                 c
.arg
[CMDPOS
] = DISCONNECT
; 
 514                 c
.arg
[LENPOS
] = 0x01; 
 515                 c
.d
.asBytes
[0] = GET_ISOFILE_IDS
; // 0x61 
 518                 if ( !WaitForResponseTimeout(CMD_ACK
,&respFiles
,1500) ) { 
 519                         PrintAndLog("   Timed-out"); 
 522                         isOK  
= respFiles
.d
.asBytes
[2] & 0xff; 
 524                                 PrintAndLog("   Can't get ISO file ids "); 
 526                                 int respfileLen 
= resp
.arg
[1]-3-2;                       
 527                                 for (int j
=0; j
< respfileLen
; ++j
){ 
 528                                         PrintAndLog(" ISO  Fileid %d :", resp
.d
.asBytes
[j
+3]); 
 535         PrintAndLog("-------------------------------------------------------------"); 
 541 // MIAFRE DesFire Authentication 
 544 int CmdHF14ADesAuth(const char *Cmd
){ 
 547         // ------------------------ 
 553         uint8_t keylength 
= 8; 
 554         unsigned char key
[24];   
 557         PrintAndLog("Usage:  hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> "); 
 558                 PrintAndLog("               Auth modes"); 
 559                 PrintAndLog("                 1 = normal, 2 = iso, 3 = aes"); 
 560                 PrintAndLog("               Crypto"); 
 561                 PrintAndLog("                 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES"); 
 563         PrintAndLog("        sample: hf mfdes auth 1 1 0 11223344"); 
 564                 PrintAndLog("        sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f"); 
 567         uint8_t cmdAuthMode     
= param_get8(Cmd
,0); 
 568         uint8_t cmdAuthAlgo     
= param_get8(Cmd
,1); 
 569         uint8_t cmdKeyNo        
= param_get8(Cmd
,2); 
 574                         if ( cmdAuthAlgo 
!= 1 && cmdAuthAlgo 
!= 2) { 
 575                                 PrintAndLog("Crypto algo not valid for the auth mode"); 
 580                         if ( cmdAuthAlgo 
!= 1 && cmdAuthAlgo 
!= 2 && cmdAuthAlgo 
!= 3) { 
 581                                 PrintAndLog("Crypto algo not valid for the auth mode"); 
 586                         if ( cmdAuthAlgo 
!= 4) { 
 587                                 PrintAndLog("Crypto algo not valid for the auth mode"); 
 592                         PrintAndLog("Wrong Auth mode"); 
 597         switch (cmdAuthAlgo
){ 
 600                         PrintAndLog("3DES selected"); 
 604                         PrintAndLog("3 key 3DES selected"); 
 608                         PrintAndLog("AES selected"); 
 613                         PrintAndLog("DES selected"); 
 618         if (param_gethex(Cmd
, 3, key
, keylength
*2)) { 
 619                 PrintAndLog("Key must include %d HEX symbols", keylength
); 
 622         // algo, nyckellängd,  
 623         UsbCommand c 
= {CMD_MIFARE_DESFIRE_AUTH1
, { cmdAuthMode
, cmdAuthAlgo
, cmdKeyNo 
}}; 
 625         c
.d
.asBytes
[0] = keylength
; 
 626         memcpy(c
.d
.asBytes
+1, key
, keylength
); 
 631         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,3000)) { 
 632                 PrintAndLog("Client command execute timeout"); 
 636         uint8_t isOK  
= resp
.arg
[0] & 0xff; 
 638                 uint8_t * data
= resp
.d
.asBytes
; 
 640                 PrintAndLog("  Key        :%s",sprint_hex(key
, keylength
)); 
 641                 PrintAndLog("  SESSION    :%s",sprint_hex(data
, keylength
)); 
 642                 PrintAndLog("-------------------------------------------------------------"); 
 643                 //PrintAndLog("  Expected   :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56"); 
 645                 PrintAndLog("Client command failed."); 
 647         PrintAndLog("-------------------------------------------------------------");    
 652 static void xor(unsigned char * dst
, unsigned char * src
, size_t len
) { 
 653    for( ; len 
> 0; len
--,dst
++,src
++) 
 657 static int32_t le24toh (uint8_t data
[3]) { 
 658     return (data
[2] << 16) | (data
[1] << 8) | data
[0]; 
 661 static command_t CommandTable
[] = 
 663   {"help",              CmdHelp
,                                        1, "This help"}, 
 664   {"auth",              CmdHF14ADesAuth
,                        0, "Tries a MIFARE DesFire Authentication"}, 
 665   {"rb",                CmdHF14ADesRb
,                          0, "Read MIFARE DesFire block"}, 
 666   {"wb",                CmdHF14ADesWb
,                          0, "write MIFARE DesFire block"}, 
 667   {"info",              CmdHF14ADesInfo
,                        0, "Get MIFARE DesFire information"}, 
 668   {"enum",              CmdHF14ADesEnumApplications
,0, "Tries enumerate all applications"}, 
 669   {NULL
, NULL
, 0, NULL
} 
 672 int CmdHFMFDes(const char *Cmd
) 
 675    WaitForResponseTimeout(CMD_ACK
,NULL
,100); 
 676    CmdsParse(CommandTable
, Cmd
); 
 680 int CmdHelp(const char *Cmd
) 
 682   CmdsHelp(CommandTable
);