1 //----------------------------------------------------------------------------- 
   2 // Ultralight Code (c) 2013,2014 Midnitesnake & Andy Davies of Pentura 
   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 ULTRALIGHT (C) commands 
   9 //----------------------------------------------------------------------------- 
  10 #include "loclass/des.h" 
  16 #define MAX_UL_BLOCKS   0x0f 
  17 #define MAX_ULC_BLOCKS  0x2f 
  18 #define MAX_ULEV1a_BLOCKS 0x0b; 
  19 #define MAX_ULEV1b_BLOCKS 0x20; 
  21 uint8_t default_3des_keys
[7][16] = { 
  22                 { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key 
  23                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },// all zeroes 
  24                 { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },// 0x00-0x0F 
  25                 { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key 
  26                 { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },// all ones 
  27                 { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF },// all FF 
  28                 { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF }     // 11 22 33 
  31 static int CmdHelp(const char *Cmd
); 
  33 // return 1 if tag responded to 0x1A. 
  34 uint8_t requestAuthentication( uint8_t* nonce
){ 
  36         UsbCommand c 
= {CMD_READER_ISO_14443a
, {ISO14A_CONNECT 
| ISO14A_RAW 
| ISO14A_APPEND_CRC 
,2 ,0}}; 
  37         c
.d
.asBytes
[0] = 0x1A; 
  38         c
.d
.asBytes
[1] = 0x00; 
  41         WaitForResponse(CMD_ACK
, &resp
);  // skip select answer. 
  43         if ( !(resp
.arg
[0] & 0xff) )  
  46         if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) { 
  48                 if ( resp
.arg
[0] & 0xff ) { 
  49                         memcpy(nonce
, resp
.d
.asBytes
+1, 8); 
  56 typedef enum TAGTYPE_UL 
{ 
  63         UL_MAGIC    
= UL 
| MAGIC
, 
  64         UL_C_MAGIC  
= UL_C 
| MAGIC
, 
  68 uint8_t GetHF14AMfU_Type(void){ 
  70         TagTypeUL_t tagtype 
= UNKNOWN
; 
  71         iso14a_card_select_t card
; 
  73         // select and run 0x60 (GET_VERSION - EV1 command) 
  74         UsbCommand c 
= {CMD_READER_ISO_14443a
, {ISO14A_CONNECT 
| ISO14A_RAW 
| ISO14A_APPEND_CRC
, 1, 0}}; 
  75         c
.d
.asBytes
[0] = 0x60; 
  78         WaitForResponse(CMD_ACK
, &resp
); 
  80         if ( resp
.arg
[0] == 0 ) return UL_ERROR
; 
  82         memcpy(&card
, (iso14a_card_select_t 
*)resp
.d
.asBytes
, sizeof(iso14a_card_select_t
)); 
  84         // Ultralight - ATQA / SAK  
  85         if ( card
.atqa
[1] != 0x00 && card
.atqa
[0] != 0x44 && card
.sak 
!= 0x00 ) return UL_ERROR
; 
  88         if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) { 
  90                 uint8_t version
[8] = {0,0,0,0,0,0,0,0}; 
  91                 memcpy(&version
, resp
.d
.asBytes
, sizeof(version
)); 
  92                 uint8_t len  
= resp
.arg
[0] & 0xff; 
  94                 if ( len 
== 0x0A && version
[6] == 0x0B )  
  96                 else if ( len 
== 0x0A && version
[6] != 0x0B )  
  98                 else if ( len 
== 0x01 ) 
 100                 else if ( len 
== 0x00 ) 
 104         // Magic UL-C, mine have a static nonce response to 0x1A command. 
 105         uint8_t nonce1
[8] = {0,0,0,0,0,0,0,0}; 
 106         uint8_t nonce2
[8] = {0,0,0,0,0,0,0,0}; 
 107         uint8_t status 
= requestAuthentication(nonce1
); 
 109                 requestAuthentication(nonce2
); 
 110                 if ( !memcmp(nonce1
, nonce2
, 8) ){ 
 111                         tagtype 
= UL_C_MAGIC
; 
 114                 // Magic Ultralight test here - TODO 
 119 int CmdHF14AMfUInfo(const char *Cmd
){ 
 121         uint8_t datatemp
[7] = {0x00}; 
 123         uint8_t data
[16] = {0x00}; 
 126         TagTypeUL_t tagtype 
= GetHF14AMfU_Type(); 
 127         if (tagtype 
== UL_ERROR
) return -1; 
 129         PrintAndLog("\n-- Tag Information ---------"); 
 130         PrintAndLog("-------------------------------------------------------------"); 
 133                 PrintAndLog("      TYPE : MIFARE Ultralight %s", (tagtype 
& MAGIC
)?"(magic)":""); 
 134         else if ( tagtype 
& UL_C
) 
 135                 PrintAndLog("      TYPE : MIFARE Ultralight C %s", (tagtype 
& MAGIC
)?"(magic)":"" ); 
 136         else if ( tagtype 
& UL_EV1_48
) 
 137                 PrintAndLog("      TYPE : MIFARE Ultralight EV1 48 bytes");  
 138         else if ( tagtype 
& UL_EV1_128
)  
 139                 PrintAndLog("      TYPE : MIFARE Ultralight EV1 128 bytes"); 
 141                 PrintAndLog("      TYPE : Unknown %x",tagtype
); 
 143         // read pages 0,1,2,4 
 144         UsbCommand c 
= {CMD_MIFAREU_READCARD
, {0, 4}}; 
 148         if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) { 
 149                 isOK  
= resp
.arg
[0] & 0xff; 
 150                 memcpy(data
, resp
.d
.asBytes
, sizeof(data
)); 
 153                         PrintAndLog("Error reading from tag"); 
 157                 PrintAndLog("Command execute timed out"); 
 162         memcpy( datatemp
, data
, 3); 
 163         memcpy( datatemp
+3, data
+4, 4); 
 165         PrintAndLog("       UID : %s ", sprint_hex(datatemp
, 7)); 
 166         PrintAndLog("    UID[0] : (Manufacturer Byte) = %02x, Manufacturer: %s",  datatemp
[0], getTagInfo(datatemp
[0]) ); 
 169         // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2  
 170         int crc0 
= 0x88 ^ data
[0] ^ data
[1] ^data
[2]; 
 171         if ( data
[3] == crc0 
) 
 172                 PrintAndLog("      BCC0 : %02x - Ok", data
[3]); 
 174                 PrintAndLog("      BCC0 : %02x - crc should be %02x", data
[3], crc0
); 
 176         int crc1 
= data
[4] ^ data
[5] ^ data
[6] ^data
[7]; 
 177         if ( data
[8] == crc1 
) 
 178                 PrintAndLog("      BCC1 : %02x - Ok", data
[8]); 
 180                 PrintAndLog("      BCC1 : %02x - crc should be %02x", data
[8], crc1 
); 
 182         PrintAndLog("  Internal : %s ", sprint_hex(data 
+ 9, 1)); 
 184         memcpy(datatemp
, data
+10, 2); 
 185         PrintAndLog("      Lock : %s - %s", sprint_hex(datatemp
, 2),printBits( 2, &datatemp
) ); 
 186         PrintAndLog("OneTimePad : %s ", sprint_hex(data 
+ 3*4, 4)); 
 191         if ((tagtype 
& UL_C
)){ 
 193                 PrintAndLog("Trying some default 3des keys"); 
 195                 for (uint8_t i 
= 0; i 
< 5; ++i 
){ 
 196                         key 
= default_3des_keys
[i
]; 
 197                         if (try3DesAuthentication(key
)){ 
 198                                 PrintAndLog("Found default 3des key: %s", sprint_hex(key
,16)); 
 203         else if ((tagtype 
& (UL_EV1_48 
| UL_EV1_128
))) { 
 204                 //********** TODO ******************************** 
 205                 // --problem, there is a failed pwd tries counter in UL-EV1 
 206                 //PrintAndLog("Trying some known EV1 passwords."); 
 212 //  Mifare Ultralight Write Single Block 
 214 int CmdHF14AMfUWrBl(const char *Cmd
){ 
 215         uint8_t blockNo    
= -1; 
 216         bool chinese_card  
= FALSE
; 
 217         uint8_t bldata
[16] = {0x00}; 
 220         char cmdp 
= param_getchar(Cmd
, 0); 
 221         if (strlen(Cmd
) < 3 || cmdp 
== 'h' || cmdp 
== 'H') { 
 222                 PrintAndLog("Usage:  hf mfu wrbl <block number> <block data (8 hex symbols)> [w]"); 
 223                 PrintAndLog("       [block number]"); 
 224                 PrintAndLog("       [block data] - (8 hex symbols)"); 
 225                 PrintAndLog("       [w] - Chinese magic ultralight tag"); 
 227                 PrintAndLog("        sample: hf mfu wrbl 0 01020304"); 
 232         blockNo 
= param_get8(Cmd
, 0); 
 234         if (blockNo 
> MAX_UL_BLOCKS
){ 
 235                 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!"); 
 239         if (param_gethex(Cmd
, 1, bldata
, 8)) { 
 240                 PrintAndLog("Block data must include 8 HEX symbols"); 
 244         if (strchr(Cmd
,'w') != 0  || strchr(Cmd
,'W') != 0 ) { 
 250                         PrintAndLog("Access Denied"); 
 252                         PrintAndLog("--specialblock no:%02x", blockNo
); 
 253                         PrintAndLog("--data: %s", sprint_hex(bldata
, 4)); 
 254                         UsbCommand d 
= {CMD_MIFAREU_WRITEBL
, {blockNo
}}; 
 255                         memcpy(d
.d
.asBytes
,bldata
, 4); 
 257                         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 258                                 uint8_t isOK  
= resp
.arg
[0] & 0xff; 
 259                                 PrintAndLog("isOk:%02x", isOK
); 
 261                                 PrintAndLog("Command execute timeout"); 
 265                 PrintAndLog("--block no:%02x", blockNo
); 
 266                 PrintAndLog("--data: %s", sprint_hex(bldata
, 4));                
 267                 UsbCommand e 
= {CMD_MIFAREU_WRITEBL
, {blockNo
}}; 
 268                 memcpy(e
.d
.asBytes
,bldata
, 4); 
 270                 if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 271                         uint8_t isOK  
= resp
.arg
[0] & 0xff; 
 272                         PrintAndLog("isOk:%02x", isOK
); 
 274                         PrintAndLog("Command execute timeout"); 
 281 //  Mifare Ultralight Read Single Block 
 283 int CmdHF14AMfURdBl(const char *Cmd
){ 
 286         uint8_t blockNo 
= -1;    
 287         char cmdp 
= param_getchar(Cmd
, 0); 
 289         if (strlen(Cmd
) < 1 || cmdp 
== 'h' || cmdp 
== 'H') {     
 290                 PrintAndLog("Usage:  hf mfu rdbl <block number>"); 
 291                 PrintAndLog("        sample: hfu mfu rdbl 0"); 
 295         blockNo 
= param_get8(Cmd
, 0); 
 297         if (blockNo 
> MAX_UL_BLOCKS
){ 
 298                 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight"); 
 302         UsbCommand c 
= {CMD_MIFAREU_READBL
, {blockNo
}}; 
 306         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 307                 uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 309                         uint8_t *data 
= resp
.d
.asBytes
; 
 310                         PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo
, blockNo
, sprint_hex(data
, 4)); 
 313                         PrintAndLog("Failed reading block: (%02x)", isOK
); 
 316                 PrintAndLog("Command execute time-out"); 
 322 int usage_hf_mfu_dump(void) 
 324         PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); 
 325         PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); 
 326         PrintAndLog("It autodetects card type.\n");      
 327         PrintAndLog("Usage:  hf mfu dump <filename w/o .bin>"); 
 328         PrintAndLog("   sample : hf mfu dump"); 
 329         PrintAndLog("          : hf mfu dump myfile"); 
 330         PrintAndLog("          : hf mfu dump 1 myfile"); 
 334 //  Mifare Ultralight / Ultralight-C / Ultralight-EV1 
 335 //  Read and Dump Card Contents,  using auto detection of tag size. 
 337 //  TODO: take a password to read UL-C / UL-EV1 tags. 
 338 int CmdHF14AMfUDump(const char *Cmd
){ 
 340         char cmdp 
= param_getchar(Cmd
, 0); 
 341         if (cmdp 
== 'h' || cmdp 
== 'H')  
 342                 return usage_hf_mfu_dump(); 
 345         char filename
[FILE_PATH_SIZE
] = {0x00}; 
 346         char *fnameptr 
= filename
; 
 347         char *str 
= "Dumping Ultralight%s%s Card Data..."; 
 349         uint8_t *lockbytes_t 
= NULL
; 
 350         uint8_t lockbytes
[2] = {0x00}; 
 351         uint8_t *lockbytes_t2 
= NULL
; 
 352         uint8_t lockbytes2
[2] = {0x00}; 
 353         bool bit
[16]  = {0x00}; 
 354         bool bit2
[16] = {0x00}; 
 355         uint8_t data
[176] = {0x00}; 
 359         bool tmplockbit 
= false; 
 361         TagTypeUL_t tagtype 
= GetHF14AMfU_Type(); 
 362         if (tagtype 
== UL_ERROR
) return -1; 
 364         if ( tagtype 
& UL 
) { 
 366                 PrintAndLog(str
,"", (tagtype 
& MAGIC
)?" (magic)":"" ); 
 368         else if ( tagtype 
& UL_C 
) { 
 370                 PrintAndLog(str
,"-C", (tagtype 
& MAGIC
)?" (magic)":"" ); 
 372         else if ( tagtype 
& UL_EV1_48 
) { 
 374                 PrintAndLog(str
," EV1_48",""); 
 376         else if ( tagtype 
& UL_EV1_128 
) { 
 378                 PrintAndLog(str
," EV1_128",""); 
 381                 PrintAndLog("Dumping unknown Ultralight, using default values."); 
 384         UsbCommand c 
= {CMD_MIFAREU_READCARD
, {0,Pages
}}; 
 388         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 389                 PrintAndLog("Command execute time-out"); 
 394                 PrintAndLog("Read command failed"); 
 397         memcpy(data
, resp
.d
.asBytes
, sizeof(data
)); 
 402         lockbytes_t 
= data 
+ 8; 
 403         lockbytes
[0] = lockbytes_t
[2]; 
 404         lockbytes
[1] = lockbytes_t
[3]; 
 405         for(j 
= 0; j 
< 16; j
++){ 
 406                 bit
[j
] = lockbytes
[j
/8] & ( 1 <<(7-j%8
)); 
 409         // Load bottom lockbytes if available 
 411                 lockbytes_t2 
= data 
+ (40*4); 
 412                 lockbytes2
[0] = lockbytes_t2
[2]; 
 413                 lockbytes2
[1] = lockbytes_t2
[3]; 
 414                 for (j 
= 0; j 
< 16; j
++) { 
 415                         bit2
[j
] = lockbytes2
[j
/8] & ( 1 <<(7-j%8
)); 
 419         for (i 
= 0; i 
< Pages
; ++i
) { 
 421                         PrintAndLog("Block %02x:%s ", i
,sprint_hex(data 
+ i 
* 4, 4)); 
 425                         case 3: tmplockbit 
= bit
[4]; break; 
 426                         case 4: tmplockbit 
= bit
[3]; break; 
 427                         case 5: tmplockbit 
= bit
[2]; break; 
 428                         case 6: tmplockbit 
= bit
[1]; break; 
 429                         case 7: tmplockbit 
= bit
[0]; break; 
 430                         case 8: tmplockbit 
= bit
[15]; break; 
 431                         case 9: tmplockbit 
= bit
[14]; break; 
 432                         case 10: tmplockbit 
= bit
[13]; break; 
 433                         case 11: tmplockbit 
= bit
[12]; break; 
 434                         case 12: tmplockbit 
= bit
[11]; break; 
 435                         case 13: tmplockbit 
= bit
[10]; break; 
 436                         case 14: tmplockbit 
= bit
[9]; break; 
 437                         case 15: tmplockbit 
= bit
[8]; break; 
 441                         case 19: tmplockbit 
= bit2
[6]; break; 
 445                         case 23: tmplockbit 
= bit2
[5]; break;  
 449                         case 27: tmplockbit 
= bit2
[4]; break;                
 453                         case 31: tmplockbit 
= bit2
[2]; break; 
 457                         case 35: tmplockbit 
= bit2
[1]; break;  
 461                         case 39: tmplockbit 
= bit2
[0]; break;  
 462                         case 40: tmplockbit 
= bit2
[12]; break; 
 463                         case 41: tmplockbit 
= bit2
[11]; break; 
 464                         case 42: tmplockbit 
= bit2
[10]; break; //auth0 
 465                         case 43: tmplockbit 
= bit2
[9]; break;  //auth1 
 468                 PrintAndLog("Block %02x:%s [%d]", i
,sprint_hex(data 
+ i 
* 4, 4),tmplockbit
); 
 471         int len 
= param_getstr(Cmd
,0,filename
); 
 472         if (len 
> FILE_PATH_SIZE
-5)  
 473                 len 
= FILE_PATH_SIZE
-5; 
 475         // user supplied filename? 
 477                 // UID = data 0-1-2 4-5-6-7  (skips a beat) 
 478                 sprintf(fnameptr
,"%02X%02X%02X%02X%02X%02X%02X.bin", 
 479                         data
[0],data
[1], data
[2], data
[4],data
[5],data
[6], data
[7]); 
 481                 sprintf(fnameptr 
+ len
," .bin"); 
 484         if ((fout 
= fopen(filename
,"wb")) == NULL
) {  
 485                 PrintAndLog("Could not create file name %s", filename
); 
 488         fwrite( data
, 1, Pages
*4, fout 
); 
 491         PrintAndLog("Dumped %d pages, wrote %d bytes to %s", Pages
, Pages
*4, filename
); 
 495 // Needed to Authenticate to Ultralight C tags 
 496 void rol (uint8_t *data
, const size_t len
){ 
 497         uint8_t first 
= data
[0]; 
 498         for (size_t i 
= 0; i 
< len
-1; i
++) { 
 504 //------------------------------------------------------------------------------- 
 505 // Ultralight C Methods 
 506 //------------------------------------------------------------------------------- 
 509 // Ultralight C Authentication Demo {currently uses hard-coded key} 
 511 int CmdHF14AMfucAuth(const char *Cmd
){ 
 516         char cmdp 
= param_getchar(Cmd
, 0); 
 518         //Change key to user defined one 
 519         if (cmdp 
== 'k' || cmdp 
== 'K'){ 
 520                 keyNo 
= param_get8(Cmd
, 1); 
 525         if (cmdp 
== 'h' || cmdp 
== 'H') 
 529                 PrintAndLog("Usage:  hf mfu cauth k <key number>"); 
 530                 PrintAndLog("      0 (default): 3DES standard key"); 
 531                 PrintAndLog("      1 : all 0x00 key"); 
 532                 PrintAndLog("      2 : 0x00-0x0F key"); 
 533                 PrintAndLog("      3 : nfc key"); 
 534                 PrintAndLog("      4 : all 0x01 key"); 
 535                 PrintAndLog("      5 : all 0xff key"); 
 536                 PrintAndLog("      6 : 0x00-0xFF key");          
 537                 PrintAndLog("\n      sample : hf mfu cauth k"); 
 538                 PrintAndLog("               : hf mfu cauth k 3"); 
 542         uint8_t *key 
= default_3des_keys
[keyNo
]; 
 543         if (try3DesAuthentication(key
)>0) 
 544                 PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key
, 16)); 
 546                 PrintAndLog("Authentication failed"); 
 551 int try3DesAuthentication( uint8_t *key
){ 
 556         des3_context ctx 
= { 0 }; 
 558         uint8_t random_a
[8] = { 1,1,1,1,1,1,1,1 }; 
 559         uint8_t random_b
[8] = { 0 }; 
 560         uint8_t enc_random_b
[8] = { 0 }; 
 561         uint8_t rnd_ab
[16] = { 0 }; 
 562         uint8_t iv
[8] = { 0 }; 
 564         UsbCommand c 
= {CMD_MIFAREUC_AUTH1
, {blockNo
}}; 
 567         if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) )    return -1; 
 568         if ( !(resp
.arg
[0] & 0xff) ) return -2; 
 571         memcpy(enc_random_b
,resp
.d
.asBytes
+1,8); 
 573         des3_set2key_dec(&ctx
, key
); 
 574         // context, mode, length, IV, input, output  
 575         des3_crypt_cbc( &ctx
, DES_DECRYPT
, sizeof(random_b
), iv 
, enc_random_b 
, random_b
); 
 578         memcpy(rnd_ab  
,random_a
,8); 
 579         memcpy(rnd_ab
+8,random_b
,8); 
 581         des3_set2key_enc(&ctx
, key
); 
 582         // context, mode, length, IV, input, output  
 583         des3_crypt_cbc(&ctx
, DES_ENCRYPT
, sizeof(rnd_ab
), enc_random_b
, rnd_ab
, rnd_ab
); 
 586         c
.cmd 
= CMD_MIFAREUC_AUTH2
; 
 588         memcpy(c
.d
.asBytes
, rnd_ab
, 16); 
 591         if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) return -1;                           
 592         if ( !(resp
.arg
[0] & 0xff)) return -2; 
 594         uint8_t enc_resp
[8] = { 0 }; 
 595         uint8_t resp_random_a
[8] = { 0 }; 
 596         memcpy(enc_resp
, resp
.d
.asBytes
+1, 8); 
 598         des3_set2key_dec(&ctx
, key
); 
 599         // context, mode, length, IV, input, output 
 600         des3_crypt_cbc( &ctx
, DES_DECRYPT
, 8, enc_random_b
, enc_resp
, resp_random_a
); 
 602         if ( !memcmp(resp_random_a
, random_a
, 8)) 
 606         //PrintAndLog("      RndA  :%s", sprint_hex(random_a, 8)); 
 607         //PrintAndLog("  enc(RndB) :%s", sprint_hex(enc_random_b, 8)); 
 608         //PrintAndLog("       RndB :%s", sprint_hex(random_b, 8)); 
 609         //PrintAndLog("        A+B :%s", sprint_hex(random_a_and_b, 16)); 
 610         //PrintAndLog("   enc(A+B) :%s", sprint_hex(random_a_and_b, 16)); 
 611         //PrintAndLog(" enc(RndA') :%s", sprint_hex(data2+1, 8)); 
 615 A test function to validate that the polarssl-function works the same  
 616 was as the openssl-implementation.  
 617 Commented out, since it requires openssl  
 619 int CmdTestDES(const char * cmd) 
 621         uint8_t key[16] = {0x00};        
 623         memcpy(key,key3_3des_data,16);   
 624         DES_cblock RndA, RndB; 
 626         PrintAndLog("----------OpenSSL DES implementation----------"); 
 628                 uint8_t e_RndB[8] = {0x00}; 
 629                 unsigned char RndARndB[16] = {0x00}; 
 631                 DES_cblock iv = { 0 }; 
 632                 DES_key_schedule ks1,ks2; 
 633                 DES_cblock key1,key2; 
 635                 memcpy(key,key3_3des_data,16);   
 637                 memcpy(key2,key+8,8); 
 640                 DES_set_key((DES_cblock *)key1,&ks1); 
 641                 DES_set_key((DES_cblock *)key2,&ks2); 
 643                 DES_random_key(&RndA); 
 644                 PrintAndLog("     RndA:%s",sprint_hex(RndA, 8)); 
 645                 PrintAndLog("     e_RndB:%s",sprint_hex(e_RndB, 8)); 
 646                 //void DES_ede2_cbc_encrypt(const unsigned char *input, 
 647                 //    unsigned char *output, long length, DES_key_schedule *ks1, 
 648                 //    DES_key_schedule *ks2, DES_cblock *ivec, int enc); 
 649                 DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0); 
 651                 PrintAndLog("     RndB:%s",sprint_hex(RndB, 8)); 
 653                 memcpy(RndARndB,RndA,8); 
 654                 memcpy(RndARndB+8,RndB,8); 
 655                 PrintAndLog("     RA+B:%s",sprint_hex(RndARndB, 16)); 
 656                 DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1); 
 657                 PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB, 16)); 
 660         PrintAndLog("----------PolarSSL implementation----------"); 
 662                 uint8_t random_a[8]     = { 0 }; 
 663                 uint8_t enc_random_a[8] = { 0 }; 
 664                 uint8_t random_b[8]     = { 0 }; 
 665                 uint8_t enc_random_b[8] = { 0 }; 
 666                 uint8_t random_a_and_b[16] = { 0 }; 
 667                 des3_context ctx        = { 0 }; 
 669                 memcpy(random_a, RndA,8); 
 671                 uint8_t output[8]       = { 0 }; 
 672                 uint8_t iv[8]           = { 0 }; 
 674                 PrintAndLog("     RndA  :%s",sprint_hex(random_a, 8)); 
 675                 PrintAndLog("     e_RndB:%s",sprint_hex(enc_random_b, 8)); 
 677                 des3_set2key_dec(&ctx, key); 
 679                 des3_crypt_cbc(&ctx      // des3_context *ctx 
 680                         , DES_DECRYPT        // int mode 
 681                         , sizeof(random_b)   // size_t length 
 682                         , iv                 // unsigned char iv[8] 
 683                         , enc_random_b       // const unsigned char *input 
 684                         , random_b           // unsigned char *output 
 687                 PrintAndLog("     RndB:%s",sprint_hex(random_b, 8)); 
 690                 memcpy(random_a_and_b  ,random_a,8); 
 691                 memcpy(random_a_and_b+8,random_b,8); 
 693                 PrintAndLog("     RA+B:%s",sprint_hex(random_a_and_b, 16)); 
 695                 des3_set2key_enc(&ctx, key); 
 697                 des3_crypt_cbc(&ctx          // des3_context *ctx 
 698                         , DES_ENCRYPT            // int mode 
 699                         , sizeof(random_a_and_b)   // size_t length 
 700                         , enc_random_b           // unsigned char iv[8] 
 701                         , random_a_and_b         // const unsigned char *input 
 702                         , random_a_and_b         // unsigned char *output 
 705                 PrintAndLog("enc(RA+B):%s",sprint_hex(random_a_and_b, 16)); 
 711 // Ultralight C Read Single Block 
 713 int CmdHF14AMfUCRdBl(const char *Cmd
) 
 717         uint8_t blockNo 
= -1; 
 718         unsigned char key
[16]; 
 719         char cmdp 
= param_getchar(Cmd
, 0); 
 721         if (strlen(Cmd
) < 1 || cmdp 
== 'h' || cmdp 
== 'H') { 
 722                 PrintAndLog("Usage:  hf mfu crdbl  <block number> <password>"); 
 724                 PrintAndLog("sample: hf mfu crdbl 0"); 
 725                 PrintAndLog("        hf mfu crdbl 0 112233445566778899AABBCCDDEEFF"); 
 729         blockNo 
= param_get8(Cmd
, 0); 
 731                 PrintAndLog("Wrong block number"); 
 735         if (blockNo 
> MAX_ULC_BLOCKS 
){ 
 736                 PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C"); 
 741         if ( strlen(Cmd
) > 3){ 
 742                 if (param_gethex(Cmd
, 1, key
, 32)) { 
 743                         PrintAndLog("Key must include %d HEX symbols", 32); 
 751         UsbCommand c 
= {CMD_MIFAREU_READBL
, {blockNo
}}; 
 754                 memcpy(c
.d
.asBytes
,key
,16); 
 758         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 759                 uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 761                         uint8_t *data 
= resp
.d
.asBytes
; 
 762                         PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo
, blockNo
, sprint_hex(data
, 4)); 
 765                         PrintAndLog("Failed reading block: (%02x)", isOK
); 
 768                 PrintAndLog("Command execute time-out"); 
 774 //  Mifare Ultralight C Write Single Block 
 776 int CmdHF14AMfUCWrBl(const char *Cmd
){ 
 778         uint8_t blockNo 
= -1; 
 779         bool chinese_card 
= FALSE
; 
 780         uint8_t bldata
[16] = {0x00}; 
 783         char cmdp 
= param_getchar(Cmd
, 0); 
 785         if (strlen(Cmd
) < 3 || cmdp 
== 'h' || cmdp 
== 'H') {     
 786                 PrintAndLog("Usage:  hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]"); 
 787                 PrintAndLog("       [block number]"); 
 788                 PrintAndLog("       [block data] - (8 hex symbols)"); 
 789                 PrintAndLog("       [w] - Chinese magic ultralight tag"); 
 791                 PrintAndLog("        sample: hf mfu cwrbl 0 01020304"); 
 796         blockNo 
= param_get8(Cmd
, 0); 
 797         if (blockNo 
> MAX_ULC_BLOCKS 
){ 
 798                 PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!"); 
 802         if (param_gethex(Cmd
, 1, bldata
, 8)) { 
 803                 PrintAndLog("Block data must include 8 HEX symbols"); 
 807         if (strchr(Cmd
,'w') != 0  || strchr(Cmd
,'W') != 0 ) { 
 811         if ( blockNo 
<= 3 ) { 
 813                          PrintAndLog("Access Denied");   
 815                         PrintAndLog("--Special block no: 0x%02x", blockNo
); 
 816                         PrintAndLog("--Data: %s", sprint_hex(bldata
, 4)); 
 817                         UsbCommand d 
= {CMD_MIFAREU_WRITEBL
, {blockNo
}}; 
 818                         memcpy(d
.d
.asBytes
,bldata
, 4); 
 820                         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 821                                 uint8_t isOK  
= resp
.arg
[0] & 0xff; 
 822                                 PrintAndLog("isOk:%02x", isOK
); 
 824                                 PrintAndLog("Command execute timeout"); 
 828                         PrintAndLog("--Block no : 0x%02x", blockNo
); 
 829                         PrintAndLog("--Data: %s", sprint_hex(bldata
, 4));                
 830                         UsbCommand e 
= {CMD_MIFAREU_WRITEBL
, {blockNo
}}; 
 831                         memcpy(e
.d
.asBytes
,bldata
, 4); 
 833                         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 834                                 uint8_t isOK  
= resp
.arg
[0] & 0xff; 
 835                                 PrintAndLog("isOk : %02x", isOK
); 
 837                                 PrintAndLog("Command execute timeout"); 
 844 // Mifare Ultralight C - Set password 
 846 int CmdHF14AMfucSetPwd(const char *Cmd
){ 
 848         uint8_t pwd
[16] = {0x00}; 
 850         char cmdp 
= param_getchar(Cmd
, 0); 
 852         if (strlen(Cmd
) == 0  || cmdp 
== 'h' || cmdp 
== 'H') {   
 853                 PrintAndLog("Usage:  hf mfu setpwd <password (32 hex symbols)>"); 
 854                 PrintAndLog("       [password] - (32 hex symbols)"); 
 856                 PrintAndLog("sample: hf mfu setpwd 000102030405060708090a0b0c0d0e0f"); 
 861         if (param_gethex(Cmd
, 0, pwd
, 32)) { 
 862                 PrintAndLog("Password must include 32 HEX symbols"); 
 866         UsbCommand c 
= {CMD_MIFAREUC_SETPWD
};    
 867         memcpy( c
.d
.asBytes
, pwd
, 16); 
 872         if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 873                 if ( (resp
.arg
[0] & 0xff) == 1) 
 874                         PrintAndLog("Ultralight-C new password: %s", sprint_hex(pwd
,16)); 
 876                         PrintAndLog("Failed writing at block %d", resp
.arg
[1] & 0xff); 
 881                 PrintAndLog("command execution time out"); 
 889 // Magic UL / UL-C tags  - Set UID 
 891 int CmdHF14AMfucSetUid(const char *Cmd
){ 
 895         uint8_t uid
[7] = {0x00}; 
 896         char cmdp 
= param_getchar(Cmd
, 0); 
 898         if (strlen(Cmd
) == 0  || cmdp 
== 'h' || cmdp 
== 'H') {   
 899                 PrintAndLog("Usage:  hf mfu setuid <uid (14 hex symbols)>"); 
 900                 PrintAndLog("       [uid] - (14 hex symbols)"); 
 901                 PrintAndLog("\nThis only works for Magic Ultralight tags."); 
 903                 PrintAndLog("sample: hf mfu setuid 11223344556677"); 
 908         if (param_gethex(Cmd
, 0, uid
, 14)) { 
 909                 PrintAndLog("UID must include 14 HEX symbols"); 
 914         c
.cmd 
= CMD_MIFAREU_READBL
; 
 917         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 918                 PrintAndLog("Command execute timeout"); 
 923         uint8_t oldblock2
[4] = {0x00}; 
 924         memcpy(resp
.d
.asBytes
, oldblock2
, 4); 
 927         c
.cmd 
= CMD_MIFAREU_WRITEBL
; 
 929         c
.d
.asBytes
[0] = uid
[0]; 
 930         c
.d
.asBytes
[1] = uid
[1]; 
 931         c
.d
.asBytes
[2] = uid
[2]; 
 932         c
.d
.asBytes
[3] =  0x88 ^ uid
[0] ^ uid
[1] ^ uid
[2]; 
 934         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 935                 PrintAndLog("Command execute timeout"); 
 941         c
.d
.asBytes
[0] = uid
[3]; 
 942         c
.d
.asBytes
[1] = uid
[4]; 
 943         c
.d
.asBytes
[2] = uid
[5]; 
 944         c
.d
.asBytes
[3] = uid
[6]; 
 946         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 947                 PrintAndLog("Command execute timeout"); 
 953         c
.d
.asBytes
[0] = uid
[3] ^ uid
[4] ^ uid
[5] ^ uid
[6]; 
 954         c
.d
.asBytes
[1] = oldblock2
[1]; 
 955         c
.d
.asBytes
[2] = oldblock2
[2]; 
 956         c
.d
.asBytes
[3] = oldblock2
[3]; 
 958         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1500) ) { 
 959                 PrintAndLog("Command execute timeout"); 
 966 int CmdHF14AMfuGenDiverseKeys(const char *Cmd
){ 
 968         uint8_t iv
[8] = { 0x00 }; 
 969         uint8_t block 
= 0x07; 
 972         //04 57 b6 e2 05 3f 80 UID 
 974         uint8_t uid
[] = { 0xF4,0xEA, 0x54, 0x8E }; 
 975         uint8_t mifarekeyA
[] = { 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5 }; 
 976         uint8_t mifarekeyB
[] = { 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5 }; 
 977         uint8_t dkeyA
[8] = { 0x00 }; 
 978         uint8_t dkeyB
[8] = { 0x00 }; 
 980         uint8_t masterkey
[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; 
 982         uint8_t mix
[8] = { 0x00 }; 
 983         uint8_t divkey
[8] = { 0x00 }; 
 985         memcpy(mix
, mifarekeyA
, 4); 
 987         mix
[4] = mifarekeyA
[4] ^ uid
[0]; 
 988         mix
[5] = mifarekeyA
[5] ^ uid
[1]; 
 989         mix
[6] = block 
^ uid
[2]; 
 992         des3_context ctx 
= { 0x00 }; 
 993         des3_set2key_enc(&ctx
, masterkey
); 
 995         des3_crypt_cbc(&ctx  
// des3_context 
 996                 , DES_ENCRYPT    
// int mode 
 997                 , sizeof(mix
)    // length 
1003         PrintAndLog("3DES version"); 
1004         PrintAndLog("Masterkey    :\t %s", sprint_hex(masterkey
,sizeof(masterkey
))); 
1005         PrintAndLog("UID          :\t %s", sprint_hex(uid
, sizeof(uid
))); 
1006         PrintAndLog("Sector       :\t %0d", block
); 
1007         PrintAndLog("Mifare key   :\t %s", sprint_hex(mifarekeyA
, sizeof(mifarekeyA
))); 
1008         PrintAndLog("Message      :\t %s", sprint_hex(mix
, sizeof(mix
))); 
1009         PrintAndLog("Diversified key: %s", sprint_hex(divkey
+1, 6)); 
1011         PrintAndLog("\n DES version"); 
1013         for (int i
=0; i 
< sizeof(mifarekeyA
); ++i
){ 
1014                 dkeyA
[i
] = (mifarekeyA
[i
] << 1) & 0xff; 
1015                 dkeyA
[6] |=  ((mifarekeyA
[i
] >> 7) & 1) << (i
+1); 
1018         for (int i
=0; i 
< sizeof(mifarekeyB
); ++i
){ 
1019                 dkeyB
[1] |=  ((mifarekeyB
[i
] >> 7) & 1) << (i
+1); 
1020                 dkeyB
[2+i
] = (mifarekeyB
[i
] << 1) & 0xff; 
1023         uint8_t zeros
[8] = {0x00}; 
1024         uint8_t newpwd
[8] = {0x00}; 
1025         uint8_t dmkey
[24] = {0x00}; 
1026         memcpy(dmkey
, dkeyA
, 8); 
1027         memcpy(dmkey
+8, dkeyB
, 8); 
1028         memcpy(dmkey
+16, dkeyA
, 8); 
1029         memset(iv
, 0x00, 8); 
1031         des3_set3key_enc(&ctx
, dmkey
); 
1033         des3_crypt_cbc(&ctx  
// des3_context 
1034                 , DES_ENCRYPT    
// int mode 
1035                 , sizeof(newpwd
) // length 
1041         PrintAndLog("Mifare dkeyA :\t %s", sprint_hex(dkeyA
, sizeof(dkeyA
))); 
1042         PrintAndLog("Mifare dkeyB :\t %s", sprint_hex(dkeyB
, sizeof(dkeyB
))); 
1043         PrintAndLog("Mifare ABA   :\t %s", sprint_hex(dmkey
, sizeof(dmkey
))); 
1044         PrintAndLog("Mifare Pwd   :\t %s", sprint_hex(newpwd
, sizeof(newpwd
))); 
1049 // static uint8_t * diversify_key(uint8_t * key){ 
1051  // for(int i=0; i<16; i++){ 
1052    // if(i<=6) key[i]^=cuid[i]; 
1053    // if(i>6) key[i]^=cuid[i%7]; 
1058 // static void GenerateUIDe( uint8_t *uid, uint8_t len){ 
1059         // for (int i=0; i<len; ++i){ 
1065 //------------------------------------ 
1067 //------------------------------------ 
1068 static command_t CommandTable
[] = 
1070         {"help",        CmdHelp
,                        1, "This help"}, 
1071         {"dbg",         CmdHF14AMfDbg
,          0, "Set default debug mode"}, 
1072         {"info",        CmdHF14AMfUInfo
,        0, "Tag information"}, 
1073         {"dump",        CmdHF14AMfUDump
,        0, "Dump Ultralight / Ultralight-C tag to binary file"}, 
1074         {"rdbl",        CmdHF14AMfURdBl
,        0, "Read block  - Ultralight"}, 
1075         {"wrbl",        CmdHF14AMfUWrBl
,        0, "Write block - Ultralight"},     
1076         {"crdbl",       CmdHF14AMfUCRdBl
,       0, "Read block        - Ultralight C"}, 
1077         {"cwrbl",       CmdHF14AMfUCWrBl
,       0, "Write block       - Ultralight C"}, 
1078         {"cauth",       CmdHF14AMfucAuth
,       0, "Authentication    - Ultralight C"}, 
1079         {"setpwd",      CmdHF14AMfucSetPwd
, 1, "Set 3des password - Ultralight-C"}, 
1080         {"setuid",      CmdHF14AMfucSetUid
, 1, "Set UID - MAGIC tags only"}, 
1081         {"gen",         CmdHF14AMfuGenDiverseKeys 
, 1, "Generate 3des mifare diversified keys"}, 
1082         {NULL
, NULL
, 0, NULL
} 
1085 int CmdHFMFUltra(const char *Cmd
){ 
1086         WaitForResponseTimeout(CMD_ACK
,NULL
,100); 
1087         CmdsParse(CommandTable
, Cmd
); 
1091 int CmdHelp(const char *Cmd
){ 
1092         CmdsHelp(CommandTable
);