+ PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
+ printvar("Used key",used_key,8);
+ diversifyKey(CSN,used_key, div_key);
+ PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
+ printvar("Div key", div_key, 8);
+ printvar("CC_NR:",CCNR,12);
+ doMAC(CCNR,12,div_key, MAC);
+ printvar("MAC", MAC, 4);
+
+ uint8_t iclass_data[32000] = {0};
+ uint32_t iclass_datalen = 0;
+ uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
+
+ UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
+ memcpy(d.d.asBytes, MAC, 4);
+ clearCommandBuffer();
+ SendCommand(&d);
+ PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
+ while (true) {
+ printf(".");
+ if (ukbhit()) {
+ getchar();
+ printf("\naborted via keyboard!\n");
+ break;
+ }
+ if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
+ {
+ uint32_t dataLength = resp.arg[0];
+ iclass_blocksFailed |= resp.arg[1];
+ if(dataLength > 0)
+ {
+ PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
+ memcpy(iclass_data, resp.d.asBytes,dataLength);
+ iclass_datalen += dataLength;
+ }else
+ {//Last transfer, datalength 0 means the dump is finished
+ PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
+ if(iclass_blocksFailed)
+ {
+ PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
+ }
+ if(iclass_datalen > 0)
+ {
+ char filename[100] = {0};
+ //create a preferred filename
+ snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
+ CSN[0],CSN[1],CSN[2],CSN[3],
+ CSN[4],CSN[5],CSN[6],CSN[7]);
+ saveFile(filename,"bin",iclass_data, iclass_datalen );
+ }
+ //Aaaand we're finished
+ return 0;
+ }
+ }
+ }
+
+
+ return 0;
+}
+
+int hf_iclass_eload_usage()
+{
+ PrintAndLog("Loads iclass tag-dump into emulator memory on device");
+ PrintAndLog("Usage: hf iclass eload f <filename>");
+ PrintAndLog("");
+ PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
+ return 0;
+
+}
+
+int iclassEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
+ UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};
+ memcpy(c.d.asBytes, data, blocksCount * 16);
+ SendCommand(&c);
+ return 0;
+}
+int CmdHFiClassELoad(const char *Cmd)
+{
+
+ char opt = param_getchar(Cmd, 0);
+ if (strlen(Cmd)<1 || opt == 'h')
+ return hf_iclass_eload_usage();
+
+ //File handling and reading
+ FILE *f;
+ char filename[FILE_PATH_SIZE];
+ if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0)
+ {
+ f = fopen(filename, "rb");
+ }else{
+ return hf_iclass_eload_usage();
+ }
+
+ if(!f) {
+ PrintAndLog("Failed to read from file '%s'", filename);
+ return 1;
+ }
+
+ fseek(f, 0, SEEK_END);
+ long fsize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ uint8_t *dump = malloc(fsize);
+ size_t bytes_read = fread(dump, 1, fsize, f);
+ fclose(f);
+
+ //Validate
+
+ if (bytes_read < fsize)
+ {
+ prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
+ free(dump);
+ return 1;
+ }
+ //Send to device
+ uint32_t bytes_sent = 0;
+ uint32_t bytes_remaining = bytes_read;
+
+ while(bytes_remaining > 0){
+ uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining);
+ UsbCommand c = {CMD_ICLASS_EML_MEMSET, {bytes_sent,bytes_in_packet,0}};
+ memcpy(c.d.asBytes, dump, bytes_in_packet);
+ SendCommand(&c);
+ bytes_remaining -= bytes_in_packet;
+ bytes_sent += bytes_in_packet;
+ }
+ free(dump);
+ PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent);
+ return 0;
+}
+
+int usage_hf_iclass_decrypt()
+{
+ PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
+ PrintAndLog("");
+ PrintAndLog("In order to use this function, the file 'iclass_decryptionkey.bin must reside");
+ PrintAndLog("in the working directory. The file should be 16 bytes binary data");
+ PrintAndLog("example: hf iclass decrypt tagdump_12312342343.bin");
+ PrintAndLog("");
+ PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 5. ");
+ PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
+ PrintAndLog("which is defined by the configuration block.");
+ return 1;
+}
+
+int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
+{
+ FILE *f = fopen(filename, "rb");
+ if(!f) {
+ PrintAndLog("Failed to read from file '%s'", filename);
+ return 1;
+ }
+ fseek(f, 0, SEEK_END);
+ long fsize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ size_t bytes_read = fread(buffer, 1, len, f);
+ fclose(f);
+ if(fsize != len)
+ {
+ PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
+ return 1;
+ }
+ if(bytes_read != len)
+ {
+ PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
+ return 1;
+ }
+ return 0;
+}