+#define ICLASS_KEYS_MAX 8
+static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
+};
+
+typedef struct iclass_block {
+ uint8_t d[8];
+} iclass_block_t;
+
+int xorbits_8(uint8_t val) {
+ uint8_t res = val ^ (val >> 1); //1st pass
+ res = res ^ (res >> 1); // 2nd pass
+ res = res ^ (res >> 2); // 3rd pass
+ res = res ^ (res >> 4); // 4th pass
+ return res & 1;
+}
+
+int CmdHFiClassList(const char *Cmd) {
+ //PrintAndLog("Deprecated command, use 'hf list iclass' instead");
+ CmdHFList("iclass");
+ return 0;
+}
+
+int CmdHFiClassSnoop(const char *Cmd) {
+ UsbCommand c = {CMD_SNOOP_ICLASS};
+ SendCommand(&c);
+ return 0;
+}
+
+int usage_hf_iclass_sim(void) {
+ PrintAndLog("Usage: hf iclass sim <option> [CSN]");
+ PrintAndLog(" options");
+ PrintAndLog(" 0 <CSN> simulate the given CSN");
+ PrintAndLog(" 1 simulate default CSN");
+ PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
+ PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
+ PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
+ PrintAndLog(" example: hf iclass sim 2");
+ PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
+ PrintAndLog(" hf iclass sim 3");
+ return 0;
+}
+
+#define NUM_CSNS 15
+int CmdHFiClassSim(const char *Cmd) {
+ uint8_t simType = 0;
+ uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ if (strlen(Cmd)<1) return usage_hf_iclass_sim();
+
+ simType = param_get8ex(Cmd, 0, 0, 10);
+
+ if(simType == 0)
+ {
+ if (param_gethex(Cmd, 1, CSN, 16)) {
+ PrintAndLog("A CSN should consist of 16 HEX symbols");
+ return usage_hf_iclass_sim();
+ }
+
+ PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
+ }
+
+ if(simType > 3)
+ {
+ PrintAndLog("Undefined simptype %d", simType);
+ return usage_hf_iclass_sim();
+ }
+
+ uint8_t numberOfCSNs=0;
+ if(simType == 2)
+ {
+ UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
+ UsbCommand resp = {0};
+
+ uint8_t csns[8*NUM_CSNS] = {
+ 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
+
+ memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
+ clearCommandBuffer();
+ SendCommand(&c);
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
+ PrintAndLog("Command timed out");
+ return 0;
+ }
+
+ uint8_t num_mac_responses = resp.arg[1];
+ PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
+
+ size_t datalen = NUM_CSNS*24;
+ /*
+ * Now, time to dump to file. We'll use this format:
+ * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
+ * So, it should wind up as
+ * 8 * 24 bytes.
+ *
+ * The returndata from the pm3 is on the following format
+ * <4 byte NR><4 byte MAC>
+ * CC are all zeroes, CSN is the same as was sent in
+ **/
+ void* dump = malloc(datalen);
+ memset(dump,0,datalen);//<-- Need zeroes for the CC-field
+ uint8_t i = 0;
+ for(i = 0 ; i < NUM_CSNS ; i++) {
+ memcpy(dump+i*24, csns+i*8, 8); //CSN
+ //8 zero bytes here...
+ //Then comes NR_MAC (eight bytes from the response)
+ memcpy(dump+i*24+16, resp.d.asBytes+i*8, 8);
+ }
+ /** Now, save to dumpfile **/
+ saveFile("iclass_mac_attack", "bin", dump, datalen);
+ free(dump);
+ } else {
+ UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
+ memcpy(c.d.asBytes, CSN, 8);
+ clearCommandBuffer();
+ SendCommand(&c);
+ }
+ return 0;
+}
+
+int HFiClassReader(const char *Cmd, bool loop, bool verbose) {
+ bool tagFound = false;
+ UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
+ FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_AA}};
+ // loop in client not device - else on windows have a communication error
+ c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
+ UsbCommand resp;
+ while(!ukbhit()){
+ clearCommandBuffer();
+ SendCommand(&c);
+ if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
+ uint8_t readStatus = resp.arg[0] & 0xff;
+ uint8_t *data = resp.d.asBytes;
+
+ if (verbose) PrintAndLog("Readstatus:%02x", readStatus);
+ if( readStatus == 0){
+ //Aborted
+ if (verbose) PrintAndLog("Quitting...");
+ return 0;
+ }
+ if( readStatus & FLAG_ICLASS_READER_CSN){
+ PrintAndLog("CSN: %s",sprint_hex(data,8));
+ tagFound = true;
+ }
+ if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s", sprint_hex(data+16, 8));
+ if( readStatus & FLAG_ICLASS_READER_CONF) printIclassDumpInfo(data);
+ if (tagFound && !loop) return 1;
+ } else {
+ if (verbose) PrintAndLog("Command execute timeout");
+ }
+ if (!loop) break;
+ }
+ return 0;