1 //----------------------------------------------------------------------------- 
   2 // Gerhard de Koning Gans - May 2008 
   3 // Hagen Fritsch - June 2010 
   4 // Gerhard de Koning Gans - May 2011 
   5 // Gerhard de Koning Gans - June 2012 - Added iClass card and reader emulation 
   8 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   9 // at your option, any later version. See the LICENSE.txt file for the text of 
  11 //----------------------------------------------------------------------------- 
  12 // Routines to support iClass. 
  13 //----------------------------------------------------------------------------- 
  14 // Contribution made during a security research at Radboud University Nijmegen 
  16 // Please feel free to contribute and extend iClass support!! 
  17 //----------------------------------------------------------------------------- 
  21 #include "proxmark3.h" 
  28 #include "iso14443a.h" 
  30 // Needed for CRC in emulation mode; 
  31 // same construction as in ISO 14443; 
  32 // different initial value (CRC_ICLASS) 
  33 #include "iso14443crc.h" 
  34 #include "iso15693tools.h" 
  35 #include "protocols.h" 
  36 #include "optimized_cipher.h" 
  37 #include "fpgaloader.h" 
  39 // iCLASS has a slightly different timing compared to ISO15693. According to the picopass data sheet the tag response is expected 330us after 
  40 // the reader command. This is measured from end of reader EOF to first modulation of the tag's SOF which starts with a 56,64us unmodulated period. 
  41 // 330us = 140 ssp_clk cycles @ 423,75kHz when simulating. 
  42 // 56,64us = 24 ssp_clk_cycles 
  43 #define DELAY_ICLASS_VCD_TO_VICC_SIM     (140 - 24) 
  44 // times in ssp_clk_cycles @ 3,3625MHz when acting as reader 
  45 #define DELAY_ICLASS_VICC_TO_VCD_READER  DELAY_ISO15693_VICC_TO_VCD_READER 
  46 // times in samples @ 212kHz when acting as reader 
  47 #define ICLASS_READER_TIMEOUT_ACTALL     330 // 1558us, nominal 330us + 7slots*160us = 1450us 
  48 #define ICLASS_READER_TIMEOUT_UPDATE    3390 // 16000us, nominal 4-15ms 
  49 #define ICLASS_READER_TIMEOUT_OTHERS      80 // 380us, nominal 330us 
  51 #define ICLASS_BUFFER_SIZE 34                // we expect max 34 bytes as tag answer (response to READ4) 
  54 //============================================================================= 
  55 // A `sniffer' for iClass communication 
  56 // Both sides of communication! 
  57 //============================================================================= 
  58 void SnoopIClass(uint8_t jam_search_len
, uint8_t *jam_search_string
) { 
  59         SnoopIso15693(jam_search_len
, jam_search_string
); 
  63 void rotateCSN(uint8_t* originalCSN
, uint8_t* rotatedCSN
) { 
  65         for (i 
= 0; i 
< 8; i
++) { 
  66                 rotatedCSN
[i
] = (originalCSN
[i
] >> 3) | (originalCSN
[(i
+1)%8
] << 5); 
  72 static void CodeIClassTagSOF() { 
  74         ToSend
[++ToSendMax
] = 0x1D; 
  79 static void AppendCrc(uint8_t *data
, int len
) { 
  80         ComputeCrc14443(CRC_ICLASS
, data
, len
, data
+len
, data
+len
+1); 
  85  * @brief Does the actual simulation 
  87 int doIClassSimulation(int simulationMode
, uint8_t *reader_mac_buf
) { 
  89         // free eventually allocated BigBuf memory 
  90         BigBuf_free_keep_EM(); 
  92         uint16_t page_size 
= 32 * 8; 
  93         uint8_t current_page 
= 0; 
  95         // maintain cipher states for both credit and debit key for each page 
  96         State cipher_state_KC
[8]; 
  97         State cipher_state_KD
[8]; 
  98         State 
*cipher_state 
= &cipher_state_KD
[0]; 
 100         uint8_t *emulator 
= BigBuf_get_EM_addr(); 
 101         uint8_t *csn 
= emulator
; 
 103         // CSN followed by two CRC bytes 
 104         uint8_t anticoll_data
[10]; 
 105         uint8_t csn_data
[10]; 
 106         memcpy(csn_data
, csn
, sizeof(csn_data
)); 
 107         Dbprintf("Simulating CSN %02x%02x%02x%02x%02x%02x%02x%02x", csn
[0], csn
[1], csn
[2], csn
[3], csn
[4], csn
[5], csn
[6], csn
[7]); 
 109         // Construct anticollision-CSN 
 110         rotateCSN(csn_data
, anticoll_data
); 
 112         // Compute CRC on both CSNs 
 113         AppendCrc(anticoll_data
, 8); 
 114         AppendCrc(csn_data
, 8); 
 116         uint8_t diversified_key_d
[8] = { 0x00 }; 
 117         uint8_t diversified_key_c
[8] = { 0x00 }; 
 118         uint8_t *diversified_key 
= diversified_key_d
; 
 120         // configuration block 
 121         uint8_t conf_block
[10] = {0x12, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0xFF, 0x3C, 0x00, 0x00}; 
 124         uint8_t card_challenge_data
[8] = { 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 
 126         if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { 
 127                 // initialize from page 0 
 128                 memcpy(conf_block
, emulator 
+ 8 * 1, 8); 
 129                 memcpy(card_challenge_data
, emulator 
+ 8 * 2, 8); // e-purse 
 130                 memcpy(diversified_key_d
, emulator 
+ 8 * 3, 8);   // Kd 
 131                 memcpy(diversified_key_c
, emulator 
+ 8 * 4, 8);   // Kc 
 134         AppendCrc(conf_block
, 8); 
 136         // save card challenge for sim2,4 attack 
 137         if (reader_mac_buf 
!= NULL
) { 
 138                 memcpy(reader_mac_buf
, card_challenge_data
, 8); 
 141         if (conf_block
[5] & 0x80) { 
 146         // When the page is in personalization mode this bit is equal to 1. 
 147         // Once the application issuer has personalized and coded its dedicated areas, this bit must be set to 0: 
 148         // the page is then "in application mode". 
 149         bool personalization_mode 
= conf_block
[7] & 0x80; 
 151         // chip memory may be divided in 8 pages 
 152         uint8_t max_page 
= conf_block
[4] & 0x10 ? 0 : 7; 
 154         // Precalculate the cipher states, feeding it the CC 
 155         cipher_state_KD
[0] = opt_doTagMAC_1(card_challenge_data
, diversified_key_d
); 
 156         cipher_state_KC
[0] = opt_doTagMAC_1(card_challenge_data
, diversified_key_c
); 
 157         if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { 
 158                 for (int i 
= 1; i 
< max_page
; i
++) { 
 159                         uint8_t *epurse 
= emulator 
+ i
*page_size 
+ 8*2; 
 160                         uint8_t *Kd 
= emulator 
+ i
*page_size 
+ 8*3; 
 161                         uint8_t *Kc 
= emulator 
+ i
*page_size 
+ 8*4; 
 162                         cipher_state_KD
[i
] = opt_doTagMAC_1(epurse
, Kd
); 
 163                         cipher_state_KC
[i
] = opt_doTagMAC_1(epurse
, Kc
); 
 172         // Reader 81 anticoll. CSN 
 175         uint8_t *modulated_response
; 
 176         int modulated_response_size 
= 0; 
 177         uint8_t *trace_data 
= NULL
; 
 178         int trace_data_size 
= 0; 
 180         // Respond SOF -- takes 1 bytes 
 181         uint8_t *resp_sof 
= BigBuf_malloc(1); 
 184         // Anticollision CSN (rotated CSN) 
 185         // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) 
 186         uint8_t *resp_anticoll 
= BigBuf_malloc(22); 
 187         int resp_anticoll_len
; 
 190         // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) 
 191         uint8_t *resp_csn 
= BigBuf_malloc(22); 
 194         // configuration (block 1) picopass 2ks 
 195         uint8_t *resp_conf 
= BigBuf_malloc(22); 
 199         // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit) 
 200         uint8_t *resp_cc 
= BigBuf_malloc(18); 
 203         // Kd, Kc (blocks 3 and 4). Cannot be read. Always respond with 0xff bytes only 
 204         uint8_t *resp_ff 
= BigBuf_malloc(22); 
 206         uint8_t ff_data
[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}; 
 207         AppendCrc(ff_data
, 8); 
 209         // Application Issuer Area (block 5) 
 210         uint8_t *resp_aia 
= BigBuf_malloc(22); 
 212         uint8_t aia_data
[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}; 
 213         AppendCrc(aia_data
, 8); 
 215         uint8_t *receivedCmd 
= BigBuf_malloc(MAX_FRAME_SIZE
); 
 218         // Prepare card messages 
 220         // First card answer: SOF only 
 222         memcpy(resp_sof
, ToSend
, ToSendMax
); 
 223         resp_sof_Len 
= ToSendMax
; 
 226         CodeIso15693AsTag(anticoll_data
, sizeof(anticoll_data
)); 
 227         memcpy(resp_anticoll
, ToSend
, ToSendMax
); 
 228         resp_anticoll_len 
= ToSendMax
; 
 231         CodeIso15693AsTag(csn_data
, sizeof(csn_data
)); 
 232         memcpy(resp_csn
, ToSend
, ToSendMax
); 
 233         resp_csn_len 
= ToSendMax
; 
 235         // Configuration (block 1) 
 236         CodeIso15693AsTag(conf_block
, sizeof(conf_block
)); 
 237         memcpy(resp_conf
, ToSend
, ToSendMax
); 
 238         resp_conf_len 
= ToSendMax
; 
 241         CodeIso15693AsTag(card_challenge_data
, sizeof(card_challenge_data
)); 
 242         memcpy(resp_cc
, ToSend
, ToSendMax
); 
 243         resp_cc_len 
= ToSendMax
; 
 245         // Kd, Kc (blocks 3 and 4) 
 246         CodeIso15693AsTag(ff_data
, sizeof(ff_data
)); 
 247         memcpy(resp_ff
, ToSend
, ToSendMax
); 
 248         resp_ff_len 
= ToSendMax
; 
 250         // Application Issuer Area (block 5) 
 251         CodeIso15693AsTag(aia_data
, sizeof(aia_data
)); 
 252         memcpy(resp_aia
, ToSend
, ToSendMax
); 
 253         resp_aia_len 
= ToSendMax
; 
 255         //This is used for responding to READ-block commands or other data which is dynamically generated 
 256         uint8_t *data_generic_trace 
= BigBuf_malloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer 
 257         uint8_t *data_response 
= BigBuf_malloc( (32 + 2) * 2 + 2); 
 259         bool buttonPressed 
= false; 
 260         enum { IDLE
, ACTIVATED
, SELECTED
, HALTED 
} chip_state 
= IDLE
; 
 265                 uint32_t reader_eof_time 
= 0; 
 266                 len 
= GetIso15693CommandFromReader(receivedCmd
, MAX_FRAME_SIZE
, &reader_eof_time
); 
 268                         buttonPressed 
= true; 
 272                 // Now look at the reader command and provide appropriate responses 
 273                 // default is no response: 
 274                 modulated_response 
= NULL
; 
 275                 modulated_response_size 
= 0; 
 279                 if (receivedCmd
[0] == ICLASS_CMD_ACTALL 
&& len 
== 1) { 
 280                         // Reader in anticollision phase 
 281                         if (chip_state 
!= HALTED
) { 
 282                                 modulated_response 
= resp_sof
; 
 283                                 modulated_response_size 
= resp_sof_Len
; 
 284                                 chip_state 
= ACTIVATED
; 
 287                 } else if (receivedCmd
[0] == ICLASS_CMD_READ_OR_IDENTIFY 
&& len 
== 1) { // identify 
 288                         // Reader asks for anticollision CSN 
 289                         if (chip_state 
== SELECTED 
|| chip_state 
== ACTIVATED
) { 
 290                                 modulated_response 
= resp_anticoll
; 
 291                                 modulated_response_size 
= resp_anticoll_len
; 
 292                                 trace_data 
= anticoll_data
; 
 293                                 trace_data_size 
= sizeof(anticoll_data
); 
 296                 } else if (receivedCmd
[0] == ICLASS_CMD_SELECT 
&& len 
== 9) { 
 297                         // Reader selects anticollision CSN. 
 298                         // Tag sends the corresponding real CSN 
 299                         if (chip_state 
== ACTIVATED 
|| chip_state 
== SELECTED
) { 
 300                                 if (!memcmp(receivedCmd
+1, anticoll_data
, 8)) { 
 301                                         modulated_response 
= resp_csn
; 
 302                                         modulated_response_size 
= resp_csn_len
; 
 303                                         trace_data 
= csn_data
; 
 304                                         trace_data_size 
= sizeof(csn_data
); 
 305                                         chip_state 
= SELECTED
; 
 309                         } else if (chip_state 
== HALTED
) { 
 311                                 if (!memcmp(receivedCmd
+1, csn_data
, 8)) { 
 312                                         modulated_response 
= resp_csn
; 
 313                                         modulated_response_size 
= resp_csn_len
; 
 314                                         trace_data 
= csn_data
; 
 315                                         trace_data_size 
= sizeof(csn_data
); 
 316                                         chip_state 
= SELECTED
; 
 320                 } else if (receivedCmd
[0] == ICLASS_CMD_READ_OR_IDENTIFY 
&& len 
== 4) { // read block 
 321                         uint16_t blockNo 
= receivedCmd
[1]; 
 322                         if (chip_state 
== SELECTED
) { 
 323                                 if (simulationMode 
== ICLASS_SIM_MODE_EXIT_AFTER_MAC
) { 
 324                                         // provide defaults for blocks 0 ... 5 
 326                                                 case 0: // csn (block 00) 
 327                                                         modulated_response 
= resp_csn
; 
 328                                                         modulated_response_size 
= resp_csn_len
; 
 329                                                         trace_data 
= csn_data
; 
 330                                                         trace_data_size 
= sizeof(csn_data
); 
 332                                                 case 1: // configuration (block 01) 
 333                                                         modulated_response 
= resp_conf
; 
 334                                                         modulated_response_size 
= resp_conf_len
; 
 335                                                         trace_data 
= conf_block
; 
 336                                                         trace_data_size 
= sizeof(conf_block
); 
 338                                                 case 2: // e-purse (block 02) 
 339                                                         modulated_response 
= resp_cc
; 
 340                                                         modulated_response_size 
= resp_cc_len
; 
 341                                                         trace_data 
= card_challenge_data
; 
 342                                                         trace_data_size 
= sizeof(card_challenge_data
); 
 343                                                         // set epurse of sim2,4 attack 
 344                                                         if (reader_mac_buf 
!= NULL
) { 
 345                                                                 memcpy(reader_mac_buf
, card_challenge_data
, 8); 
 349                                                 case 4: // Kd, Kc, always respond with 0xff bytes 
 350                                                         modulated_response 
= resp_ff
; 
 351                                                         modulated_response_size 
= resp_ff_len
; 
 352                                                         trace_data 
= ff_data
; 
 353                                                         trace_data_size 
= sizeof(ff_data
); 
 355                                                 case 5: // Application Issuer Area (block 05) 
 356                                                         modulated_response 
= resp_aia
; 
 357                                                         modulated_response_size 
= resp_aia_len
; 
 358                                                         trace_data 
= aia_data
; 
 359                                                         trace_data_size 
= sizeof(aia_data
); 
 361                                                 // default: don't respond 
 363                                 } else if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { 
 364                                         if (blockNo 
== 3 || blockNo 
== 4) { // Kd, Kc, always respond with 0xff bytes 
 365                                                 modulated_response 
= resp_ff
; 
 366                                                 modulated_response_size 
= resp_ff_len
; 
 367                                                 trace_data 
= ff_data
; 
 368                                                 trace_data_size 
= sizeof(ff_data
); 
 369                                         } else { // use data from emulator memory 
 370                                                 memcpy(data_generic_trace
, emulator 
+ current_page
*page_size 
+ 8*blockNo
, 8); 
 371                                                 AppendCrc(data_generic_trace
, 8); 
 372                                                 trace_data 
= data_generic_trace
; 
 373                                                 trace_data_size 
= 10; 
 374                                                 CodeIso15693AsTag(trace_data
, trace_data_size
); 
 375                                                 memcpy(data_response
, ToSend
, ToSendMax
); 
 376                                                 modulated_response 
= data_response
; 
 377                                                 modulated_response_size 
= ToSendMax
; 
 382                 } else if ((receivedCmd
[0] == ICLASS_CMD_READCHECK_KD
 
 383                                         || receivedCmd
[0] == ICLASS_CMD_READCHECK_KC
) && receivedCmd
[1] == 0x02 && len 
== 2) { 
 384                         // Read e-purse (88 02 || 18 02) 
 385                         if (chip_state 
== SELECTED
) { 
 386                                 if(receivedCmd
[0] == ICLASS_CMD_READCHECK_KD
){ 
 387                                         cipher_state 
= &cipher_state_KD
[current_page
]; 
 388                                         diversified_key 
= diversified_key_d
; 
 390                                         cipher_state 
= &cipher_state_KC
[current_page
]; 
 391                                         diversified_key 
= diversified_key_c
; 
 393                                 modulated_response 
= resp_cc
; 
 394                                 modulated_response_size 
= resp_cc_len
; 
 395                                 trace_data 
= card_challenge_data
; 
 396                                 trace_data_size 
= sizeof(card_challenge_data
); 
 399                 } else if ((receivedCmd
[0] == ICLASS_CMD_CHECK_KC
 
 400                                         || receivedCmd
[0] == ICLASS_CMD_CHECK_KD
) && len 
== 9) { 
 401                         // Reader random and reader MAC!!! 
 402                         if (chip_state 
== SELECTED
) { 
 403                                 if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { 
 404                                         //NR, from reader, is in receivedCmd+1 
 405                                         opt_doTagMAC_2(*cipher_state
, receivedCmd
+1, data_generic_trace
, diversified_key
); 
 406                                         trace_data 
= data_generic_trace
; 
 408                                         CodeIso15693AsTag(trace_data
, trace_data_size
); 
 409                                         memcpy(data_response
, ToSend
, ToSendMax
); 
 410                                         modulated_response 
= data_response
; 
 411                                         modulated_response_size 
= ToSendMax
; 
 413                                 } else { // Not fullsim, we don't respond 
 414                                         // We do not know what to answer, so lets keep quiet 
 415                                         if (simulationMode 
== ICLASS_SIM_MODE_EXIT_AFTER_MAC
) { 
 416                                                 if (reader_mac_buf 
!= NULL
) { 
 417                                                         // save NR and MAC for sim 2,4 
 418                                                         memcpy(reader_mac_buf 
+ 8, receivedCmd 
+ 1, 8); 
 425                 } else if (receivedCmd
[0] == ICLASS_CMD_HALT 
&& len 
== 1) { 
 426                         if (chip_state 
== SELECTED
) { 
 427                                 // Reader ends the session 
 428                                 modulated_response 
= resp_sof
; 
 429                                 modulated_response_size 
= resp_sof_Len
; 
 433                 } else if (simulationMode 
== ICLASS_SIM_MODE_FULL 
&& receivedCmd
[0] == ICLASS_CMD_READ4 
&& len 
== 4) {  // 0x06 
 435                         if (chip_state 
== SELECTED
) { 
 436                                 uint8_t blockNo 
= receivedCmd
[1]; 
 437                                 memcpy(data_generic_trace
, emulator 
+ current_page
*page_size 
+ blockNo
*8, 8 * 4); 
 438                                 AppendCrc(data_generic_trace
, 8 * 4); 
 439                                 trace_data 
= data_generic_trace
; 
 440                                 trace_data_size 
= 8 * 4 + 2; 
 441                                 CodeIso15693AsTag(trace_data
, trace_data_size
); 
 442                                 memcpy(data_response
, ToSend
, ToSendMax
); 
 443                                 modulated_response 
= data_response
; 
 444                                 modulated_response_size 
= ToSendMax
; 
 447                 } else if (receivedCmd
[0] == ICLASS_CMD_UPDATE 
&& (len 
== 12 || len 
== 14)) { 
 448                         // We're expected to respond with the data+crc, exactly what's already in the receivedCmd 
 449                         // receivedCmd is now UPDATE 1b | ADDRESS 1b | DATA 8b | Signature 4b or CRC 2b 
 450                         if (chip_state 
== SELECTED
) { 
 451                                 uint8_t blockNo 
= receivedCmd
[1]; 
 452                                 if (blockNo 
== 2) { // update e-purse 
 453                                         memcpy(card_challenge_data
, receivedCmd
+2, 8); 
 454                                         CodeIso15693AsTag(card_challenge_data
, sizeof(card_challenge_data
)); 
 455                                         memcpy(resp_cc
, ToSend
, ToSendMax
); 
 456                                         resp_cc_len 
= ToSendMax
; 
 457                                         cipher_state_KD
[current_page
] = opt_doTagMAC_1(card_challenge_data
, diversified_key_d
); 
 458                                         cipher_state_KC
[current_page
] = opt_doTagMAC_1(card_challenge_data
, diversified_key_c
); 
 459                                         if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { 
 460                                                 memcpy(emulator 
+ current_page
*page_size 
+ 8*2, card_challenge_data
, 8); 
 462                                 } else if (blockNo 
== 3) { // update Kd 
 463                                         for (int i 
= 0; i 
< 8; i
++) { 
 464                                                 if (personalization_mode
) { 
 465                                                         diversified_key_d
[i
] = receivedCmd
[2 + i
]; 
 467                                                         diversified_key_d
[i
] ^= receivedCmd
[2 + i
]; 
 470                                         cipher_state_KD
[current_page
] = opt_doTagMAC_1(card_challenge_data
, diversified_key_d
); 
 471                                         if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { 
 472                                                 memcpy(emulator 
+ current_page
*page_size 
+ 8*3, diversified_key_d
, 8); 
 474                                 } else if (blockNo 
== 4) { // update Kc 
 475                                         for (int i 
= 0; i 
< 8; i
++) { 
 476                                                 if (personalization_mode
) { 
 477                                                         diversified_key_c
[i
] = receivedCmd
[2 + i
]; 
 479                                                         diversified_key_c
[i
] ^= receivedCmd
[2 + i
]; 
 482                                         cipher_state_KC
[current_page
] = opt_doTagMAC_1(card_challenge_data
, diversified_key_c
); 
 483                                         if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { 
 484                                                 memcpy(emulator 
+ current_page
*page_size 
+ 8*4, diversified_key_c
, 8); 
 486                                 } else if (simulationMode 
== ICLASS_SIM_MODE_FULL
) { // update any other data block 
 487                                                 memcpy(emulator 
+ current_page
*page_size 
+ 8*blockNo
, receivedCmd
+2, 8); 
 489                                 memcpy(data_generic_trace
, receivedCmd 
+ 2, 8); 
 490                                 AppendCrc(data_generic_trace
, 8); 
 491                                 trace_data 
= data_generic_trace
; 
 492                                 trace_data_size 
= 10; 
 493                                 CodeIso15693AsTag(trace_data
, trace_data_size
); 
 494                                 memcpy(data_response
, ToSend
, ToSendMax
); 
 495                                 modulated_response 
= data_response
; 
 496                                 modulated_response_size 
= ToSendMax
; 
 499                 } else if (receivedCmd
[0] == ICLASS_CMD_PAGESEL 
&& len 
== 4) { 
 501                         // Chips with a single page will not answer to this command 
 502                         // Otherwise, we should answer 8bytes (conf block 1) + 2bytes CRC 
 503                         if (chip_state 
== SELECTED
) { 
 504                                 if (simulationMode 
== ICLASS_SIM_MODE_FULL 
&& max_page 
> 0) { 
 505                                         current_page 
= receivedCmd
[1]; 
 506                                         memcpy(data_generic_trace
, emulator 
+ current_page
*page_size 
+ 8*1, 8); 
 507                                         memcpy(diversified_key_d
, emulator 
+ current_page
*page_size 
+ 8*3, 8); 
 508                                         memcpy(diversified_key_c
, emulator 
+ current_page
*page_size 
+ 8*4, 8); 
 509                                         cipher_state 
= &cipher_state_KD
[current_page
]; 
 510                                         personalization_mode 
= data_generic_trace
[7] & 0x80; 
 511                                         AppendCrc(data_generic_trace
, 8); 
 512                                         trace_data 
= data_generic_trace
; 
 513                                         trace_data_size 
= 10; 
 514                                         CodeIso15693AsTag(trace_data
, trace_data_size
); 
 515                                         memcpy(data_response
, ToSend
, ToSendMax
); 
 516                                         modulated_response 
= data_response
; 
 517                                         modulated_response_size 
= ToSendMax
; 
 521                 } else if (receivedCmd
[0] == 0x26 && len 
== 5) { 
 522                         // standard ISO15693 INVENTORY command. Ignore. 
 525                         // don't know how to handle this command 
 526                         char debug_message
[250]; // should be enough 
 527                         sprintf(debug_message
, "Unhandled command (len = %d) received from reader:", len
); 
 528                         for (int i 
= 0; i 
< len 
&& strlen(debug_message
) < sizeof(debug_message
) - 3 - 1; i
++) { 
 529                                 sprintf(debug_message 
+ strlen(debug_message
), " %02x", receivedCmd
[i
]); 
 531                         Dbprintf("%s", debug_message
); 
 536                 A legit tag has about 273,4us delay between reader EOT and tag SOF. 
 538                 if (modulated_response_size 
> 0) { 
 539                         uint32_t response_time 
= reader_eof_time 
+ DELAY_ICLASS_VCD_TO_VICC_SIM
; 
 540                         TransmitTo15693Reader(modulated_response
, modulated_response_size
, &response_time
, 0, false); 
 541                         LogTrace_ISO15693(trace_data
, trace_data_size
, response_time
*32, response_time
*32 + modulated_response_size
/2, NULL
, false); 
 548                 DbpString("Button pressed"); 
 550         return buttonPressed
; 
 554  * @brief SimulateIClass simulates an iClass card. 
 555  * @param arg0 type of simulation 
 556  *          - 0 uses the first 8 bytes in usb data as CSN 
 557  *          - 2 "dismantling iclass"-attack. This mode iterates through all CSN's specified 
 558  *          in the usb data. This mode collects MAC from the reader, in order to do an offline 
 559  *          attack on the keys. For more info, see "dismantling iclass" and proxclone.com. 
 560  *          - Other : Uses the default CSN (031fec8af7ff12e0) 
 561  * @param arg1 - number of CSN's contained in datain (applicable for mode 2 only) 
 565 void SimulateIClass(uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, uint8_t *datain
) { 
 569         uint32_t simType 
= arg0
; 
 570         uint32_t numberOfCSNS 
= arg1
; 
 572         // setup hardware for simulation: 
 573         FpgaDownloadAndGo(FPGA_BITSTREAM_HF
); 
 574         SetAdcMuxFor(GPIO_MUXSEL_HIPKD
); 
 575         FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR 
| FPGA_HF_SIMULATOR_NO_MODULATION
); 
 577         FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR
); 
 580         // Enable and clear the trace 
 583         //Use the emulator memory for SIM 
 584         uint8_t *emulator 
= BigBuf_get_EM_addr(); 
 586         if (simType 
== ICLASS_SIM_MODE_CSN
) { 
 587                 // Use the CSN from commandline 
 588                 memcpy(emulator
, datain
, 8); 
 589                 doIClassSimulation(ICLASS_SIM_MODE_CSN
, NULL
); 
 590         } else if (simType 
== ICLASS_SIM_MODE_CSN_DEFAULT
) { 
 592                 uint8_t csn_crc
[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 }; 
 593                 // Use the CSN from commandline 
 594                 memcpy(emulator
, csn_crc
, 8); 
 595                 doIClassSimulation(ICLASS_SIM_MODE_CSN
, NULL
); 
 596         } else if (simType 
== ICLASS_SIM_MODE_READER_ATTACK
) { 
 597                 uint8_t mac_responses
[USB_CMD_DATA_SIZE
] = { 0 }; 
 598                 Dbprintf("Going into attack mode, %d CSNS sent", numberOfCSNS
); 
 599                 // In this mode, a number of csns are within datain. We'll simulate each one, one at a time 
 600                 // in order to collect MAC's from the reader. This can later be used in an offline-attack 
 601                 // in order to obtain the keys, as in the "dismantling iclass"-paper. 
 603                 for (i 
= 0; i 
< numberOfCSNS 
&& i
*16+16 <= USB_CMD_DATA_SIZE
; i
++) { 
 604                         // The usb data is 512 bytes, fitting 32 responses (8 byte CC + 4 Byte NR + 4 Byte MAC = 16 Byte response). 
 605                         memcpy(emulator
, datain
+(i
*8), 8); 
 606                         if (doIClassSimulation(ICLASS_SIM_MODE_EXIT_AFTER_MAC
, mac_responses
+i
*16)) { 
 610                         Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x", 
 611                                         datain
[i
*8+0], datain
[i
*8+1], datain
[i
*8+2], datain
[i
*8+3], 
 612                                         datain
[i
*8+4], datain
[i
*8+5], datain
[i
*8+6], datain
[i
*8+7]); 
 613                         Dbprintf("NR,MAC: %02x %02x %02x %02x %02x %02x %02x %02x", 
 614                                         mac_responses
[i
*16+ 8], mac_responses
[i
*16+ 9], mac_responses
[i
*16+10], mac_responses
[i
*16+11], 
 615                                         mac_responses
[i
*16+12], mac_responses
[i
*16+13], mac_responses
[i
*16+14], mac_responses
[i
*16+15]); 
 616                         SpinDelay(100); // give the reader some time to prepare for next CSN 
 618                 cmd_send(CMD_ACK
, CMD_SIMULATE_TAG_ICLASS
, i
, 0, mac_responses
, i
*16); 
 619         } else if (simType 
== ICLASS_SIM_MODE_FULL
) { 
 620                 //This is 'full sim' mode, where we use the emulator storage for data. 
 621                 doIClassSimulation(ICLASS_SIM_MODE_FULL
, NULL
); 
 623                 // We may want a mode here where we hardcode the csns to use (from proxclone). 
 624                 // That will speed things up a little, but not required just yet. 
 625                 Dbprintf("The mode is not implemented, reserved for future use"); 
 636 static void ReaderTransmitIClass(uint8_t *frame
, int len
, uint32_t *start_time
) { 
 638         CodeIso15693AsReader(frame
, len
); 
 640         TransmitTo15693Tag(ToSend
, ToSendMax
, start_time
); 
 642         uint32_t end_time 
= *start_time 
+ 32*(8*ToSendMax
-4); // substract the 4 padding bits after EOF 
 643         LogTrace_ISO15693(frame
, len
, *start_time
*4, end_time
*4, NULL
, true); 
 647 static bool sendCmdGetResponseWithRetries(uint8_t* command
, size_t cmdsize
, uint8_t* resp
, size_t max_resp_size
, 
 648                                                                                   uint8_t expected_size
, uint8_t tries
, uint32_t start_time
, uint32_t timeout
, uint32_t *eof_time
) { 
 649         while (tries
-- > 0) { 
 650                 ReaderTransmitIClass(command
, cmdsize
, &start_time
); 
 651                 if (expected_size 
== GetIso15693AnswerFromTag(resp
, max_resp_size
, timeout
, eof_time
)) { 
 660  * @brief Selects an iclass tag 
 661  * @param card_data where the CSN is stored for return 
 662  * @return false = fail 
 665 static bool selectIclassTag(uint8_t *card_data
, uint32_t *eof_time
) { 
 666         uint8_t act_all
[]      = { 0x0a }; 
 667         uint8_t identify
[]     = { 0x0c }; 
 668         uint8_t select
[]       = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 
 670         uint8_t resp
[ICLASS_BUFFER_SIZE
]; 
 672         uint32_t start_time 
= GetCountSspClk(); 
 675         ReaderTransmitIClass(act_all
, 1, &start_time
); 
 677         if (GetIso15693AnswerFromTag(resp
, sizeof(resp
), ICLASS_READER_TIMEOUT_ACTALL
, eof_time
) < 0) return false;//Fail 
 680         start_time 
= *eof_time 
+ DELAY_ICLASS_VICC_TO_VCD_READER
; 
 681         ReaderTransmitIClass(identify
, 1, &start_time
); 
 682         //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC 
 683         uint8_t len 
= GetIso15693AnswerFromTag(resp
, sizeof(resp
), ICLASS_READER_TIMEOUT_OTHERS
, eof_time
); 
 684         if (len 
!= 10) return false;//Fail 
 686         //Copy the Anti-collision CSN to our select-packet 
 687         memcpy(&select
[1], resp
, 8); 
 689         start_time 
= *eof_time 
+ DELAY_ICLASS_VICC_TO_VCD_READER
; 
 690         ReaderTransmitIClass(select
, sizeof(select
), &start_time
); 
 691         //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC 
 692         len 
= GetIso15693AnswerFromTag(resp
, sizeof(resp
), ICLASS_READER_TIMEOUT_OTHERS
, eof_time
); 
 693         if (len 
!= 10) return false;//Fail 
 695         //Success - we got CSN 
 696         //Save CSN in response data 
 697         memcpy(card_data
, resp
, 8); 
 703 // Select an iClass tag and read all blocks which are always readable without authentication 
 704 void ReaderIClass(uint8_t flags
) { 
 708         uint8_t card_data
[6 * 8] = {0}; 
 709         memset(card_data
, 0xFF, sizeof(card_data
)); 
 710         uint8_t resp
[ICLASS_BUFFER_SIZE
]; 
 711         //Read conf block CRC(0x01) => 0xfa 0x22 
 712         uint8_t readConf
[] = {ICLASS_CMD_READ_OR_IDENTIFY
, 0x01, 0xfa, 0x22}; 
 713         //Read e-purse block CRC(0x02) => 0x61 0x10 
 714         uint8_t readEpurse
[] = {ICLASS_CMD_READ_OR_IDENTIFY
, 0x02, 0x61, 0x10}; 
 715         //Read App Issuer Area block CRC(0x05) => 0xde  0x64 
 716         uint8_t readAA
[] = {ICLASS_CMD_READ_OR_IDENTIFY
, 0x05, 0xde, 0x64}; 
 718         uint8_t result_status 
= 0; 
 720         if (flags 
& FLAG_ICLASS_READER_INIT
) { 
 721                 Iso15693InitReader(); 
 724         if (flags 
& FLAG_ICLASS_READER_CLEARTRACE
) { 
 730         uint32_t start_time 
= 0; 
 731         uint32_t eof_time 
= 0; 
 733         if (selectIclassTag(resp
, &eof_time
)) { 
 734                 result_status 
= FLAG_ICLASS_READER_CSN
; 
 735                 memcpy(card_data
, resp
, 8); 
 738         start_time 
= eof_time 
+ DELAY_ICLASS_VICC_TO_VCD_READER
; 
 740         //Read block 1, config 
 741         if (flags 
& FLAG_ICLASS_READER_CONF
) { 
 742                 if (sendCmdGetResponseWithRetries(readConf
, sizeof(readConf
), resp
, sizeof(resp
), 10, 10, start_time
, ICLASS_READER_TIMEOUT_OTHERS
, &eof_time
)) { 
 743                         result_status 
|= FLAG_ICLASS_READER_CONF
; 
 744                         memcpy(card_data
+8, resp
, 8); 
 746                         Dbprintf("Failed to read config block"); 
 748                 start_time 
= eof_time 
+ DELAY_ICLASS_VICC_TO_VCD_READER
; 
 751         //Read block 2, e-purse 
 752         if (flags 
& FLAG_ICLASS_READER_CC
) { 
 753                 if (sendCmdGetResponseWithRetries(readEpurse
, sizeof(readEpurse
), resp
, sizeof(resp
), 10, 10, start_time
, ICLASS_READER_TIMEOUT_OTHERS
, &eof_time
)) { 
 754                         result_status 
|= FLAG_ICLASS_READER_CC
; 
 755                         memcpy(card_data 
+ (8*2), resp
, 8); 
 757                         Dbprintf("Failed to read e-purse"); 
 759                 start_time 
= eof_time 
+ DELAY_ICLASS_VICC_TO_VCD_READER
; 
 763         if (flags 
& FLAG_ICLASS_READER_AA
) { 
 764                 if (sendCmdGetResponseWithRetries(readAA
, sizeof(readAA
), resp
, sizeof(resp
), 10, 10, start_time
, ICLASS_READER_TIMEOUT_OTHERS
, &eof_time
)) { 
 765                         result_status 
|= FLAG_ICLASS_READER_AA
; 
 766                         memcpy(card_data 
+ (8*5), resp
, 8); 
 768                         Dbprintf("Failed to read AA block"); 
 772         cmd_send(CMD_ACK
, result_status
, 0, 0, card_data
, sizeof(card_data
)); 
 778 void iClass_Check(uint8_t *NRMAC
) { 
 779         uint8_t check
[9] = {ICLASS_CMD_CHECK_KD
, 0x00}; 
 781         memcpy(check
+1, NRMAC
, 8); 
 783         bool isOK 
= sendCmdGetResponseWithRetries(check
, sizeof(check
), resp
, sizeof(resp
), 4, 3, 0, ICLASS_READER_TIMEOUT_OTHERS
, &eof_time
); 
 784         cmd_send(CMD_ACK
, isOK
, 0, 0, resp
, sizeof(resp
)); 
 788 void iClass_Readcheck(uint8_t block
, bool use_credit_key
) { 
 789         uint8_t readcheck
[2] = {ICLASS_CMD_READCHECK_KD
, block
}; 
 790         if (use_credit_key
) { 
 791                 readcheck
[0] = ICLASS_CMD_READCHECK_KC
; 
 795         bool isOK 
= sendCmdGetResponseWithRetries(readcheck
, sizeof(readcheck
), resp
, sizeof(resp
), 8, 3, 0, ICLASS_READER_TIMEOUT_OTHERS
, &eof_time
); 
 796         cmd_send(CMD_ACK
, isOK
, 0, 0, resp
, sizeof(resp
)); 
 800 static bool iClass_ReadBlock(uint8_t blockNo
, uint8_t *readdata
) { 
 801         uint8_t readcmd
[] = {ICLASS_CMD_READ_OR_IDENTIFY
, blockNo
, 0x00, 0x00}; //0x88, 0x00 // can i use 0C? 
 802         uint8_t bl 
= blockNo
; 
 803         uint16_t rdCrc 
= iclass_crc16(&bl
, 1); 
 804         readcmd
[2] = rdCrc 
>> 8; 
 805         readcmd
[3] = rdCrc 
& 0xff; 
 809         bool isOK 
= sendCmdGetResponseWithRetries(readcmd
, sizeof(readcmd
), resp
, sizeof(resp
), 10, 10, 0, ICLASS_READER_TIMEOUT_OTHERS
, &eof_time
); 
 810         memcpy(readdata
, resp
, sizeof(resp
)); 
 816 void iClass_ReadBlk(uint8_t blockno
) { 
 820         uint8_t readblockdata
[10]; 
 821         bool isOK 
= iClass_ReadBlock(blockno
, readblockdata
); 
 822         cmd_send(CMD_ACK
, isOK
, 0, 0, readblockdata
, 8); 
 823         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 830 void iClass_Dump(uint8_t startblock
, uint8_t numblks
) { 
 834         uint8_t readblockdata
[USB_CMD_DATA_SIZE
+2] = {0}; 
 838         if (numblks 
> USB_CMD_DATA_SIZE 
/ 8) { 
 839                 numblks 
= USB_CMD_DATA_SIZE 
/ 8; 
 842         for (blkCnt 
= 0; blkCnt 
< numblks
; blkCnt
++) { 
 843                 isOK 
= iClass_ReadBlock(startblock
+blkCnt
, readblockdata
+8*blkCnt
); 
 845                         Dbprintf("Block %02X failed to read", startblock
+blkCnt
); 
 850         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 853         cmd_send(CMD_ACK
, isOK
, blkCnt
, 0, readblockdata
, blkCnt
*8); 
 859 static bool iClass_WriteBlock_ext(uint8_t blockNo
, uint8_t *data
) { 
 861         uint8_t write
[16] = {ICLASS_CMD_UPDATE
, blockNo
}; 
 862         memcpy(write
+2, data
, 12); // data + mac 
 863         AppendCrc(write
+1, 13); 
 866         uint32_t eof_time 
= 0; 
 868         isOK 
= sendCmdGetResponseWithRetries(write
, sizeof(write
), resp
, sizeof(resp
), 10, 3, 0, ICLASS_READER_TIMEOUT_UPDATE
, &eof_time
); 
 873         uint8_t all_ff
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
 875                 if (memcmp(data
+4, resp
, 4) || memcmp(data
, resp
+4, 4)) { // check response. e-purse update swaps first and second half 
 878         } else if (blockNo 
== 3 || blockNo 
== 4) { 
 879                 if (memcmp(all_ff
, resp
, 8)) { // check response. Key updates always return 0xffffffffffffffff 
 883                 if (memcmp(data
, resp
, 8)) { // check response. All other updates return unchanged data 
 892 void iClass_WriteBlock(uint8_t blockNo
, uint8_t *data
) { 
 896         bool isOK 
= iClass_WriteBlock_ext(blockNo
, data
); 
 898                 Dbprintf("Write block [%02x] successful", blockNo
); 
 900                 Dbprintf("Write block [%02x] failed", blockNo
); 
 902         cmd_send(CMD_ACK
, isOK
, 0, 0, 0, 0); 
 904         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 911 void iClass_Clone(uint8_t startblock
, uint8_t endblock
, uint8_t *data
) { 
 916         int total_blocks 
= (endblock 
- startblock
) + 1; 
 918         for (uint8_t block 
= startblock
; block 
<= endblock
; block
++) { 
 920                 if (iClass_WriteBlock_ext(block
, data 
+ (block
-startblock
)*12)) { 
 921                         Dbprintf("Write block [%02x] successful", block
); 
 924                         Dbprintf("Write block [%02x] failed", block
); 
 928         if (written 
== total_blocks
) 
 929                 Dbprintf("Clone complete"); 
 931                 Dbprintf("Clone incomplete"); 
 933         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 936         cmd_send(CMD_ACK
, 1, 0, 0, 0, 0);