1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch 
   3 // Copyright (C) 2011 Gerhard de Koning Gans 
   4 // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende 
   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 iClass commands 
  11 //----------------------------------------------------------------------------- 
  17 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type 
  19 #include "proxmark3.h" 
  21 #include "cmdparser.h" 
  22 #include "cmdhficlass.h" 
  23 #include "../include/common.h" 
  26 #include "loclass/des.h" 
  27 #include "loclass/cipherutils.h" 
  28 #include "loclass/cipher.h" 
  29 #include "loclass/ikeys.h" 
  30 #include "loclass/elite_crack.h" 
  31 #include "loclass/fileutils.h" 
  33 static int CmdHelp(const char *Cmd
); 
  35 int xorbits_8(uint8_t val
) 
  37         uint8_t res 
= val 
^ (val 
>> 1); //1st pass 
  38         res 
= res 
^ (res 
>> 1);                 // 2nd pass 
  39         res 
= res 
^ (res 
>> 2);                 // 3rd pass 
  40         res 
= res 
^ (res 
>> 4);                         // 4th pass 
  44 int CmdHFiClassList(const char *Cmd
) 
  46         bool ShowWaitCycles 
= false; 
  47         char param 
= param_getchar(Cmd
, 0); 
  50                 PrintAndLog("List data in trace buffer."); 
  51                 PrintAndLog("Usage:  hf iclass list"); 
  52                 PrintAndLog("h - help"); 
  53                 PrintAndLog("sample: hf iclass list"); 
  57 // for the time being. Need better Bigbuf handling.      
  58 #define TRACE_SIZE 3000  
  60         uint8_t trace
[TRACE_SIZE
]; 
  61         GetFromBigBuf(trace
, TRACE_SIZE
, 0); 
  62         WaitForResponse(CMD_ACK
,NULL
); 
  64         PrintAndLog("Recorded Activity"); 
  66         PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); 
  67         PrintAndLog("All times are in carrier periods (1/13.56Mhz)"); 
  69         PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC "); 
  70         PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------"); 
  72         uint16_t tracepos 
= 0; 
  78         uint32_t first_timestamp
; 
  79         uint32_t EndOfTransmissionTimestamp
; 
  83                 if(tracepos 
>= TRACE_SIZE
) { 
  87                 timestamp 
= *((uint32_t *)(trace 
+ tracepos
)); 
  89                         first_timestamp 
= timestamp
; 
  92     // Break and stick with current result if buffer was not completely full 
  93                 if (timestamp 
== 0x44444444) break;  
  96                 duration 
= *((uint16_t *)(trace 
+ tracepos
)); 
  98                 data_len 
= *((uint16_t *)(trace 
+ tracepos
)); 
 101                 if (data_len 
& 0x8000) { 
 108                 parity_len 
= (data_len
-1)/8 + 1; 
 110                 if (tracepos 
+ data_len 
+ parity_len 
>= TRACE_SIZE
) { 
 114                 uint8_t *frame 
= trace 
+ tracepos
; 
 115                 tracepos 
+= data_len
; 
 116                 uint8_t *parityBytes 
= trace 
+ tracepos
; 
 117                 tracepos 
+= parity_len
; 
 120                 for (int j 
= 0; j 
< data_len
; j
++) { 
 121       int oddparity 
= 0x01; 
 125         oddparity 
^= (((frame
[j
] & 0xFF) >> k
) & 0x01); 
 128                         uint8_t parityBits 
= parityBytes
[j
>>3]; 
 129                         if (isResponse 
&& (oddparity 
!= ((parityBits 
>> (7-(j
&0x0007))) & 0x01))) { 
 130                                 sprintf(line
[j
/16]+((j%16
)*4), "%02x! ", frame
[j
]); 
 132                                 sprintf(line
[j
/16]+((j%16
)*4), "%02x  ", frame
[j
]); 
 140                         if(!isResponse 
&& data_len 
== 4 ) { 
 141                 // Rough guess that this is a command from the reader 
 142                 // For iClass the command byte is not part of the CRC 
 143                                 ComputeCrc14443(CRC_ICLASS
, &frame
[1], data_len
-3, &b1
, &b2
); 
 144                                 if (b1 
!= frame
[data_len
-2] || b2 
!= frame
[data_len
-1]) { 
 149                 // For other data.. CRC might not be applicable (UPDATE commands etc.) 
 150                                 ComputeCrc14443(CRC_ICLASS
, frame
, data_len
-2, &b1
, &b2
); 
 151                                 if (b1 
!= frame
[data_len
-2] || b2 
!= frame
[data_len
-1]) { 
 157                 EndOfTransmissionTimestamp 
= timestamp 
+ duration
; 
 159                 int num_lines 
= (data_len 
- 1)/16 + 1; 
 160                 for (int j 
= 0; j 
< num_lines
; j
++) { 
 162                                 PrintAndLog(" %9d | %9d | %s | %-64s| %s", 
 163                                         (timestamp 
- first_timestamp
), 
 164                                         (EndOfTransmissionTimestamp 
- first_timestamp
), 
 165                                         (isResponse 
? "Tag" : "Rdr"), 
 167                                         (j 
== num_lines
-1)?crc
:""); 
 169                                 PrintAndLog("           |           |     | %-64s| %s", 
 171                                         (j 
== num_lines
-1)?crc
:""); 
 175                 bool next_isResponse 
= *((uint16_t *)(trace 
+ tracepos 
+ 6)) & 0x8000; 
 177                 if (ShowWaitCycles 
&& !isResponse 
&& next_isResponse
) { 
 178                         uint32_t next_timestamp 
= *((uint32_t *)(trace 
+ tracepos
)); 
 179                         if (next_timestamp 
!= 0x44444444) { 
 180                                 PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", 
 181                                         (EndOfTransmissionTimestamp 
- first_timestamp
), 
 182                                         (next_timestamp 
- first_timestamp
), 
 184                                         (next_timestamp 
- EndOfTransmissionTimestamp
)); 
 193 int CmdHFiClassSnoop(const char *Cmd
) 
 195   UsbCommand c 
= {CMD_SNOOP_ICLASS
}; 
 200 int CmdHFiClassSim(const char *Cmd
) 
 203   uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 
 206         PrintAndLog("Usage:  hf iclass sim [0 <CSN>] | x"); 
 207         PrintAndLog("        options"); 
 208         PrintAndLog("                0 <CSN> simulate the given CSN"); 
 209         PrintAndLog("                1       simulate default CSN"); 
 210         PrintAndLog("                2       iterate CSNs, gather MACs"); 
 211         PrintAndLog("        sample: hf iclass sim 0 031FEC8AF7FF12E0"); 
 212         PrintAndLog("        sample: hf iclass sim 2"); 
 216   simType 
= param_get8(Cmd
, 0); 
 220           if (param_gethex(Cmd
, 1, CSN
, 16)) { 
 221                   PrintAndLog("A CSN should consist of 16 HEX symbols"); 
 224           PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8)); 
 229           PrintAndLog("Undefined simptype %d", simType
); 
 232   uint8_t numberOfCSNs
=0; 
 236                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}}; 
 237                 UsbCommand resp 
= {0}; 
 239                 /*uint8_t csns[8 * NUM_CSNS] = { 
 240                          0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 , 
 241                          0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 , 
 242                          0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 , 
 243                          0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 , 
 244                          0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 , 
 245                          0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 , 
 246                          0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 , 
 247                          0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 }; 
 250         uint8_t csns
[8*NUM_CSNS
] = { 
 251          0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 
 252          0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, 
 253          0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, 
 254          0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, 
 255          0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, 
 256          0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, 
 257          0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, 
 258          0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, 
 259          0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, 
 260          0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, 
 261          0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, 
 262          0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, 
 263          0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, 
 264          0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, 
 265          0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 }; 
 267          memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
); 
 270                 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) { 
 271                         PrintAndLog("Command timed out"); 
 275                 uint8_t num_mac_responses  
= resp
.arg
[1]; 
 276                 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
, NUM_CSNS
); 
 278                 size_t datalen 
= NUM_CSNS
*24; 
 280                  * Now, time to dump to file. We'll use this format: 
 281                  * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>.... 
 282                  * So, it should wind up as 
 285                  * The returndata from the pm3 is on the following format 
 286                  * <4 byte NR><4 byte MAC> 
 287                  * CC are all zeroes, CSN is the same as was sent in 
 289                 void* dump 
= malloc(datalen
); 
 290                 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field 
 292                 for(i 
= 0 ; i 
< NUM_CSNS 
; i
++) 
 294                         memcpy(dump
+i
*24, csns
+i
*8,8); //CSN 
 295                         //8 zero bytes here... 
 296                         //Then comes NR_MAC (eight bytes from the response) 
 297                         memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8); 
 300                 /** Now, save to dumpfile **/ 
 301                 saveFile("iclass_mac_attack", "bin", dump
,datalen
); 
 305                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}}; 
 306                 memcpy(c
.d
.asBytes
, CSN
, 8); 
 313 int CmdHFiClassReader(const char *Cmd
) 
 315   UsbCommand c 
= {CMD_READER_ICLASS
, {0}}; 
 319       if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
 320             uint8_t isOK    
= resp
.arg
[0] & 0xff; 
 321             uint8_t * data  
= resp
.d
.asBytes
; 
 323             PrintAndLog("isOk:%02x", isOK
); 
 327                 PrintAndLog("CSN: %s",sprint_hex(data
,8)); 
 331                 PrintAndLog("CC: %s",sprint_hex(data
+8,8)); 
 333                 PrintAndLog("No CC obtained"); 
 336             PrintAndLog("Command execute timeout"); 
 343 int CmdHFiClassReader_Replay(const char *Cmd
) 
 345   uint8_t readerType 
= 0; 
 346   uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00}; 
 349     PrintAndLog("Usage:  hf iclass replay <MAC>"); 
 350     PrintAndLog("        sample: hf iclass replay 00112233"); 
 354   if (param_gethex(Cmd
, 0, MAC
, 8)) { 
 355     PrintAndLog("MAC must include 8 HEX symbols"); 
 359   UsbCommand c 
= {CMD_READER_ICLASS_REPLAY
, {readerType
}}; 
 360   memcpy(c
.d
.asBytes
, MAC
, 4); 
 366 int CmdHFiClassReader_Dump(const char *Cmd
) 
 368   uint8_t readerType 
= 0; 
 369   uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
 370   uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 371   uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 372   uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 373   //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 374   uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 375   uint8_t keytable
[128] = {0}; 
 381     PrintAndLog("Usage:  hf iclass dump <Key> [e]"); 
 382     PrintAndLog("        Key    - A 16 byte master key"); 
 383     PrintAndLog("        e      - If 'e' is specified, the key is interpreted as the 16 byte"); 
 384     PrintAndLog("                 Custom Key (KCus), which can be obtained via reader-attack"); 
 385     PrintAndLog("                 See 'hf iclass sim 2'. This key should be on iclass-format"); 
 386     PrintAndLog("        sample: hf iclass dump 0011223344556677"); 
 392   if (param_gethex(Cmd
, 0, KEY
, 16))  
 394     PrintAndLog("KEY must include 16 HEX symbols"); 
 398   if (param_getchar(Cmd
, 1) == 'e') 
 400     PrintAndLog("Elite switch on"); 
 404     hash2(KEY
, keytable
); 
 405     printarr_human_readable("keytable", keytable
, 128); 
 410   uint8_t key_sel
[8] = {0}; 
 411   uint8_t key_sel_p
[8] = { 0 }; 
 413   //HACK -- Below is for testing without access to a tag 
 414   uint8_t fake_dummy_test 
= false; 
 417     uint8_t xdata
[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230 
 418                         0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here 
 419     memcpy(resp
.d
.asBytes
,xdata
, 16); 
 426   UsbCommand c 
= {CMD_READER_ICLASS
, {0}}; 
 427   c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
; 
 433   if (fake_dummy_test 
|| WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
 434         uint8_t isOK    
= resp
.arg
[0] & 0xff; 
 435         uint8_t * data  
= resp
.d
.asBytes
; 
 438         memcpy(CCNR
,data
+8,8); 
 440         PrintAndLog("isOk:%02x", isOK
); 
 444             PrintAndLog("CSN: %s",sprint_hex(CSN
,8)); 
 450                 //Get the key index (hash1) 
 451                 uint8_t key_index
[8] = {0}; 
 453                 hash1(CSN
, key_index
); 
 454                 printvar("hash1", key_index
,8); 
 455                 for(i 
= 0; i 
< 8 ; i
++) 
 456                     key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF; 
 457                 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:"); 
 458                 printvar("k_sel", key_sel
,8); 
 459                 //Permute from iclass format to standard format 
 460                 permutekey_rev(key_sel
,key_sel_p
); 
 461                 used_key 
= key_sel_p
; 
 463                 //Perhaps this should also be permuted to std format? 
 464                 // Something like the code below? I have no std system 
 465                 // to test this with /Martin 
 467                 //uint8_t key_sel_p[8] = { 0 }; 
 468                 //permutekey_rev(KEY,key_sel_p); 
 469                 //used_key = key_sel_p; 
 475             PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); 
 476             printvar("Used key",used_key
,8); 
 477             diversifyKey(CSN
,used_key
, div_key
); 
 478             PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); 
 479             printvar("Div key", div_key
, 8); 
 480             printvar("CC_NR:",CCNR
,12); 
 481             doMAC(CCNR
,12,div_key
, MAC
); 
 482             printvar("MAC", MAC
, 4); 
 484             UsbCommand d 
= {CMD_READER_ICLASS_REPLAY
, {readerType
}}; 
 485             memcpy(d
.d
.asBytes
, MAC
, 4); 
 486             if(!fake_dummy_test
) SendCommand(&d
); 
 489             PrintAndLog("Failed to obtain CC! Aborting"); 
 492         PrintAndLog("Command execute timeout"); 
 498 int CmdHFiClass_iso14443A_write(const char *Cmd
) 
 500   uint8_t readerType 
= 0; 
 501   uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
 502   uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 503   uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 504   uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 505   uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 508   uint8_t bldata
[8]={0}; 
 512     PrintAndLog("Usage:  hf iclass write <Key> <Block> <Data>"); 
 513     PrintAndLog("        sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA"); 
 517   if (param_gethex(Cmd
, 0, KEY
, 16))  
 519     PrintAndLog("KEY must include 16 HEX symbols"); 
 523   blockNo 
= param_get8(Cmd
, 1); 
 526         PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!"); 
 529   if (param_gethex(Cmd
, 2, bldata
, 8))  
 531         PrintAndLog("Block data must include 8 HEX symbols"); 
 535   UsbCommand c 
= {CMD_ICLASS_ISO14443A_WRITE
, {0}}; 
 539   if (WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
 540     uint8_t isOK    
= resp
.arg
[0] & 0xff; 
 541     uint8_t * data  
= resp
.d
.asBytes
; 
 544     memcpy(CCNR
,data
+8,8); 
 545     PrintAndLog("DEBUG: %s",sprint_hex(CSN
,8)); 
 546     PrintAndLog("DEBUG: %s",sprint_hex(CCNR
,8)); 
 547         PrintAndLog("isOk:%02x", isOK
); 
 549         PrintAndLog("Command execute timeout"); 
 552   diversifyKey(CSN
,KEY
, div_key
); 
 554   PrintAndLog("Div Key: %s",sprint_hex(div_key
,8)); 
 555   doMAC(CCNR
, 12,div_key
, MAC
); 
 557   UsbCommand c2 
= {CMD_ICLASS_ISO14443A_WRITE
, {readerType
,blockNo
}}; 
 558   memcpy(c2
.d
.asBytes
, bldata
, 8); 
 559   memcpy(c2
.d
.asBytes
+8, MAC
, 4); 
 562   if (WaitForResponseTimeout(CMD_ACK
,&resp
,1500)) { 
 563     uint8_t isOK    
= resp
.arg
[0] & 0xff; 
 564     uint8_t * data  
= resp
.d
.asBytes
; 
 567       PrintAndLog("isOk:%02x data:%s", isOK
, sprint_hex(data
, 4)); 
 569       PrintAndLog("isOk:%02x", isOK
); 
 571       PrintAndLog("Command execute timeout"); 
 577 static command_t CommandTable
[] =  
 579   {"help",    CmdHelp
,        1, "This help"}, 
 580   {"list",    CmdHFiClassList
,   0, "List iClass history"}, 
 581   {"snoop",   CmdHFiClassSnoop
,  0, "Eavesdrop iClass communication"}, 
 582   {"sim",     CmdHFiClassSim
,    0, "Simulate iClass tag"}, 
 583   {"reader",CmdHFiClassReader
,  0,      "Read an iClass tag"}, 
 584   {"replay",CmdHFiClassReader_Replay
,   0,      "Read an iClass tag via Reply Attack"}, 
 585   {"dump",      CmdHFiClassReader_Dump
, 0,              "Authenticate and Dump iClass tag"}, 
 586   {"write",     CmdHFiClass_iso14443A_write
,    0,      "Authenticate and Write iClass block"}, 
 587   {"replay",  CmdHFiClassReader_Replay
, 0, "Read an iClass tag via Reply Attack"}, 
 588   {"dump",        CmdHFiClassReader_Dump
, 0, "Authenticate and Dump iClass tag"}, 
 589   {"write",     CmdHFiClass_iso14443A_write
,    0,      "Authenticate and Write iClass block"}, 
 590   {NULL
, NULL
, 0, NULL
} 
 593 int CmdHFiClass(const char *Cmd
) 
 595   CmdsParse(CommandTable
, Cmd
); 
 599 int CmdHelp(const char *Cmd
) 
 601   CmdsHelp(CommandTable
);