- }
-
- if (param_gethex(Cmd, 0, MAC, 8)) {
- PrintAndLog("MAC must include 8 HEX symbols");
- return 1;
- }
-
- UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
- memcpy(c.d.asBytes, MAC, 4);
- SendCommand(&c);
-
- return 0;
-}
-
-int CmdHFiClassReader_Dump(const char *Cmd)
-{
- uint8_t readerType = 0;
- uint8_t MAC[4]={0x00,0x00,0x00,0x00};
- uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- uint8_t keytable[128] = {0};
- int elite = 0;
- uint8_t *used_key;
- int i;
- if (strlen(Cmd)<1)
- {
- PrintAndLog("Usage: hf iclass dump <Key> [e]");
- PrintAndLog(" Key - A 16 byte master key");
- PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
- PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
- PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
- PrintAndLog(" sample: hf iclass dump 0011223344556677");
-
-
- return 0;
- }
-
- if (param_gethex(Cmd, 0, KEY, 16))
- {
- PrintAndLog("KEY must include 16 HEX symbols");
- return 1;
- }
-
- if (param_getchar(Cmd, 1) == 'e')
- {
- PrintAndLog("Elite switch on");
- elite = 1;
-
- //calc h2
- hash2(KEY, keytable);
- printarr_human_readable("keytable", keytable, 128);
-
- }
-
- UsbCommand resp;
- uint8_t key_sel[8] = {0};
- uint8_t key_sel_p[8] = { 0 };
-
- UsbCommand c = {CMD_READER_ICLASS, {0}};
- c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC;
- SendCommand(&c);
-
-
-
- if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
- {
- PrintAndLog("Command execute timeout");
- return 0;
- }
-
- uint8_t isOK = resp.arg[0] & 0xff;
- uint8_t * data = resp.d.asBytes;
-
- memcpy(CSN,data,8);
- memcpy(CCNR,data+8,8);
-
- PrintAndLog("isOk:%02x", isOK);
-
- if(isOK > 0)
- {
- PrintAndLog("CSN: %s",sprint_hex(CSN,8));
- }
+}
+
+int CmdHFiClassReader(const char *Cmd) {
+ return HFiClassReader(Cmd, true, true);
+}
+
+int CmdHFiClassReader_Replay(const char *Cmd) {
+ uint8_t readerType = 0;
+ uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
+
+ if (strlen(Cmd)<1) {
+ PrintAndLog("Usage: hf iclass replay <MAC>");
+ PrintAndLog(" sample: hf iclass replay 00112233");
+ return 0;
+ }
+
+ if (param_gethex(Cmd, 0, MAC, 8)) {
+ PrintAndLog("MAC must include 8 HEX symbols");
+ return 1;
+ }
+
+ UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
+ memcpy(c.d.asBytes, MAC, 4);
+ clearCommandBuffer();
+ SendCommand(&c);
+ 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);
+ clearCommandBuffer();
+ SendCommand(&c);
+ return 0;
+}
+
+int hf_iclass_eload_usage(void) {
+ 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 CmdHFiClassELoad(const char *Cmd) {
+
+ char opt = param_getchar(Cmd, 0);
+ if (strlen(Cmd)<1 || opt == 'h' || 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);
+
+ if (fsize < 0) {
+ prnlog("Error, when getting filesize");
+ fclose(f);
+ return 1;
+ }
+
+ uint8_t *dump = malloc(fsize);
+
+ size_t bytes_read = fread(dump, 1, fsize, f);
+ fclose(f);
+
+ printIclassDumpInfo(dump);
+ //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);
+ clearCommandBuffer();
+ 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;
+}
+
+static 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;
+}
+
+int usage_hf_iclass_decrypt(void) {
+ PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
+ PrintAndLog("");
+ PrintAndLog("OBS! 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("");
+ PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
+ PrintAndLog("");
+ PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
+ 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 CmdHFiClassDecrypt(const char *Cmd) {
+ uint8_t key[16] = { 0 };
+ if(readKeyfile("iclass_decryptionkey.bin", 16, key)) {
+ usage_hf_iclass_decrypt();
+ return 1;
+ }
+ PrintAndLog("Decryption file found... ");
+ char opt = param_getchar(Cmd, 0);
+ if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_decrypt();
+
+ //Open the tagdump-file
+ FILE *f;
+ char filename[FILE_PATH_SIZE];
+ if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0) {
+ if ( (f = fopen(filename, "rb")) == NULL) {
+ PrintAndLog("Could not find file %s", filename);
+ return 1;
+ }
+ } else {
+ return usage_hf_iclass_decrypt();
+ }
+
+ fseek(f, 0, SEEK_END);
+ long fsize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ uint8_t enc_dump[8] = {0};
+ uint8_t *decrypted = malloc(fsize);
+ des3_context ctx = { DES_DECRYPT ,{ 0 } };
+ des3_set2key_dec( &ctx, key);
+ size_t bytes_read = fread(enc_dump, 1, 8, f);
+
+ //Use the first block (CSN) for filename
+ char outfilename[FILE_PATH_SIZE] = { 0 };
+ snprintf(outfilename,FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
+ enc_dump[0],enc_dump[1],enc_dump[2],enc_dump[3],
+ enc_dump[4],enc_dump[5],enc_dump[6],enc_dump[7]);
+
+ size_t blocknum =0;
+ while(bytes_read == 8)
+ {
+ if(blocknum < 7) {
+ memcpy(decrypted+(blocknum*8), enc_dump, 8);
+ } else {
+ des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
+ }
+ printvar("decrypted block", decrypted +(blocknum*8), 8);
+ bytes_read = fread(enc_dump, 1, 8, f);
+ blocknum++;
+ }
+ fclose(f);
+ saveFile(outfilename,"bin", decrypted, blocknum*8);
+ free(decrypted);
+ return 0;
+}
+
+int usage_hf_iclass_encrypt(void) {
+ PrintAndLog("Usage: hf iclass encrypt <BlockData>");
+ PrintAndLog("");
+ PrintAndLog("OBS! 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("");
+ PrintAndLog("example: hf iclass encrypt 0102030405060708");
+ PrintAndLog("");
+ return 0;
+}
+
+static int iClassEncryptBlkData(uint8_t *blkData) {
+ uint8_t key[16] = { 0 };
+ if(readKeyfile("iclass_decryptionkey.bin", 16, key)) {
+ usage_hf_iclass_encrypt();
+ return 1;
+ }
+ PrintAndLog("Decryption file found... ");
+
+ uint8_t encryptedData[16];
+ uint8_t *encrypted = encryptedData;
+ des3_context ctx = { DES_DECRYPT ,{ 0 } };
+ des3_set2key_enc( &ctx, key);
+
+ des3_crypt_ecb(&ctx, blkData,encrypted);
+ //printvar("decrypted block", decrypted, 8);
+ memcpy(blkData,encrypted,8);
+
+ return 1;
+}
+
+int CmdHFiClassEncryptBlk(const char *Cmd) {
+ uint8_t blkData[8] = {0};
+ char opt = param_getchar(Cmd, 0);
+ if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_encrypt();
+
+ //get the bytes to encrypt
+ if (param_gethex(Cmd, 0, blkData, 16)) {
+ PrintAndLog("BlockData must include 16 HEX symbols");
+ return 0;
+ }
+ if (!iClassEncryptBlkData(blkData)) return 0;
+
+ printvar("encrypted block", blkData, 8);
+ return 1;
+}
+
+void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_t MAC[4]) {
+ uint8_t WB[9];
+ WB[0] = blockno;
+ memcpy(WB + 1,data,8);
+ doMAC_N(WB,sizeof(WB),div_key,MAC);
+ //printf("Cal wb mac block [%02x][%02x%02x%02x%02x%02x%02x%02x%02x] : MAC [%02x%02x%02x%02x]",WB[0],WB[1],WB[2],WB[3],WB[4],WB[5],WB[6],WB[7],WB[8],MAC[0],MAC[1],MAC[2],MAC[3]);
+}
+
+static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) {
+ UsbCommand resp;
+
+ UsbCommand c = {CMD_READER_ICLASS, {0}};
+ c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_ONE_TRY;
+ if (use_credit_key)
+ c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
+
+ clearCommandBuffer();
+ SendCommand(&c);
+ if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
+ PrintAndLog("Command execute timeout");
+ return false;
+ }
+
+ uint8_t isOK = resp.arg[0] & 0xff;
+ uint8_t *data = resp.d.asBytes;
+
+ memcpy(CSN,data,8);
+
+ if (CCNR!=NULL)
+ memcpy(CCNR,data+16,8);
+
+ if(isOK > 0) {
+ if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8));
+ }
+