From: pwpiwi <pwpiwi@users.noreply.github.com>
Date: Sun, 27 Oct 2019 15:51:27 +0000 (+0100)
Subject: fix 'hf iclass reader' and 'hf iclass readblk'
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/ece38ef311b28eefb1d716937139aad9ee00985c?ds=sidebyside;hp=--cc

fix 'hf iclass reader' and 'hf iclass readblk'
* don't do READCHECK when not trying to authenticate
* standard LED handling
* remove unused FLAG_ICLASS_READER_ONLY_ONCE and FLAG_ICLASS_READER_ONE_TRY
* sanity check for negative times in TransmitTo15693Tag()
* increase reader timeout for 'hf 15' functions to be enough for slot 7 answers to ACTALL
* add 'hf iclass permute' inspired by RRG repository
* whitespace fixes
---

ece38ef311b28eefb1d716937139aad9ee00985c
diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index e3bd1fe0..56da5434 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -1327,8 +1327,11 @@ void UsbPacketReceived(uint8_t *packet, int len)
 		case CMD_ICLASS_READBLOCK:
 			iClass_ReadBlk(c->arg[0]);
 			break;
-		case CMD_ICLASS_AUTHENTICATION: //check
-			iClass_Authentication(c->d.asBytes);
+		case CMD_ICLASS_CHECK:
+			iClass_Check(c->d.asBytes);
+			break;
+		case CMD_ICLASS_READCHECK:
+			iClass_Readcheck(c->arg[0], c->arg[1]);
 			break;
 		case CMD_ICLASS_DUMP:
 			iClass_Dump(c->arg[0], c->arg[1]);
diff --git a/armsrc/iclass.c b/armsrc/iclass.c
index 392271bd..1a729f3f 100644
--- a/armsrc/iclass.c
+++ b/armsrc/iclass.c
@@ -63,9 +63,9 @@
 // 56,64us = 24 ssp_clk_cycles
 #define DELAY_ICLASS_VCD_TO_VICC_SIM     (140 - 24)
 // times in ssp_clk_cycles @ 3,3625MHz when acting as reader
-#define DELAY_ICLASS_VICC_TO_VCD_READER	 DELAY_ISO15693_VICC_TO_VCD_READER
+#define DELAY_ICLASS_VICC_TO_VCD_READER  DELAY_ISO15693_VICC_TO_VCD_READER
 // times in samples @ 212kHz when acting as reader
-#define ICLASS_READER_TIMEOUT_ACTALL     330 // 1558us, nominal 330us + 7slots*160us = 1450us         
+#define ICLASS_READER_TIMEOUT_ACTALL     330 // 1558us, nominal 330us + 7slots*160us = 1450us
 #define ICLASS_READER_TIMEOUT_OTHERS      80 // 380us, nominal 330us
 
 
@@ -695,7 +695,6 @@ void RAMFUNC SnoopIClass(void) {
 			if (OutOfNDecoding((smpl & 0xF0) >> 4)) {
 				rsamples = samples - Uart.samples;
 				time_stop = (GetCountSspClk()-time_0) << 4;
-				LED_C_ON();
 
 				//if (!LogTrace(Uart.output, Uart.byteCnt, rsamples, Uart.parityBits,true)) break;
 				//if (!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break;
@@ -708,7 +707,6 @@ void RAMFUNC SnoopIClass(void) {
 				/* And also reset the demod code, which might have been */
 				/* false-triggered by the commands from the reader. */
 				Demod.state = DEMOD_UNSYNCD;
-				LED_B_OFF();
 				Uart.byteCnt = 0;
 			} else {
 				time_start = (GetCountSspClk()-time_0) << 4;
@@ -722,7 +720,6 @@ void RAMFUNC SnoopIClass(void) {
 				time_stop = (GetCountSspClk()-time_0) << 4;
 
 				rsamples = samples - Demod.samples;
-				LED_B_ON();
 
 				uint8_t parity[MAX_PARITY_SIZE];
 				GetParity(Demod.output, Demod.len, parity);
@@ -732,7 +729,6 @@ void RAMFUNC SnoopIClass(void) {
 				memset(&Demod, 0, sizeof(Demod));
 				Demod.output = tagToReaderResponse;
 				Demod.state = DEMOD_UNSYNCD;
-				LED_C_OFF();
 			} else {
 				time_start = (GetCountSspClk()-time_0) << 4;
 			}
@@ -1341,7 +1337,7 @@ static void ReaderTransmitIClass(uint8_t *frame, int len, uint32_t *start_time)
 }
 
 
-static bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, size_t max_resp_size, 
+static bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, size_t max_resp_size,
 										  uint8_t expected_size, uint8_t retries, uint32_t start_time, uint32_t *eof_time) {
 	while (retries-- > 0) {
 		ReaderTransmitIClass(command, cmdsize, &start_time);
@@ -1353,39 +1349,31 @@ static bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint
 }
 
 /**
- * @brief Talks to an iclass tag, sends the commands to get CSN and CC.
- * @param card_data where the CSN and CC are stored for return
- * @return 0 = fail
- *         1 = Got CSN
- *         2 = Got CSN and CC
+ * @brief Selects an iclass tag
+ * @param card_data where the CSN is stored for return
+ * @return false = fail
+ *         true = success
  */
-static uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key, uint32_t *eof_time) {
+static bool selectIclassTag(uint8_t *card_data, uint32_t *eof_time) {
 	uint8_t act_all[]      = { 0x0a };
 	uint8_t identify[]     = { 0x0c };
 	uint8_t select[]       = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	uint8_t readcheck_cc[] = { 0x88, 0x02 };
-	if (use_credit_key)
-		readcheck_cc[0] = 0x18;
-	else
-		readcheck_cc[0] = 0x88;
 
 	uint8_t resp[ICLASS_BUFFER_SIZE];
 
-	uint8_t read_status = 0;
 	uint32_t start_time = GetCountSspClk();
 
 	// Send act_all
 	ReaderTransmitIClass(act_all, 1, &start_time);
 	// Card present?
-	if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return read_status;//Fail
-	
+	if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time) < 0) return false;//Fail
+
 	//Send Identify
 	start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 	ReaderTransmitIClass(identify, 1, &start_time);
-	// FpgaDisableTracing(); // DEBUGGING
 	//We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC
 	uint8_t len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time);
-	if (len != 10) return read_status;//Fail
+	if (len != 10) return false;//Fail
 
 	//Copy the Anti-collision CSN to our select-packet
 	memcpy(&select[1], resp, 8);
@@ -1394,54 +1382,33 @@ static uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key, u
 	ReaderTransmitIClass(select, sizeof(select), &start_time);
 	//We expect a 10-byte response here, 8 byte CSN and 2 byte CRC
 	len = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time);
-	if (len != 10) return read_status;//Fail
+	if (len != 10) return false;//Fail
 
-	//Success - level 1, we got CSN
+	//Success - we got CSN
 	//Save CSN in response data
 	memcpy(card_data, resp, 8);
 
-	//Flag that we got to at least stage 1, read CSN
-	read_status = 1;
-
-	// Card selected, now read e-purse (cc) (only 8 bytes no CRC)
-	start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
-	ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc), &start_time);
-	if (GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time) == 8) {
-		//Save CC (e-purse) in response data
-		memcpy(card_data+8, resp, 8);
-		read_status++;
-	}
-
-	return read_status;
-}
-
-static uint8_t handshakeIclassTag(uint8_t *card_data, uint32_t *eof_time) {
-	return handshakeIclassTag_ext(card_data, false, eof_time);
+	return true;
 }
 
 
-// Reader iClass Anticollission
+// Select an iClass tag and read all blocks which are always readable without authentication
 void ReaderIClass(uint8_t arg0) {
 
+	LED_A_ON();
+
 	uint8_t card_data[6 * 8] = {0};
 	memset(card_data, 0xFF, sizeof(card_data));
-	uint8_t last_csn[8] = {0,0,0,0,0,0,0,0};
 	uint8_t resp[ICLASS_BUFFER_SIZE];
-	memset(resp, 0xFF, sizeof(resp));
 	//Read conf block CRC(0x01) => 0xfa 0x22
-	uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22};
+	uint8_t readConf[] = {ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22};
+	//Read e-purse block CRC(0x02) => 0x61 0x10
+	uint8_t readEpurse[] = {ICLASS_CMD_READ_OR_IDENTIFY, 0x02, 0x61, 0x10};
 	//Read App Issuer Area block CRC(0x05) => 0xde  0x64
-	uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
+	uint8_t readAA[] = {ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
 
-	int read_status= 0;
 	uint8_t result_status = 0;
-	// flag to read until one tag is found successfully
-	bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
-	// flag to only try 5 times to find one tag then return
-	bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
-	// if neither abort_after_read nor try_once then continue reading until button pressed.
 
-	bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY;
 	// test flags for what blocks to be sure to read
 	uint8_t flagReadConfig = arg0 & FLAG_ICLASS_READER_CONF;
 	uint8_t flagReadCC = arg0 & FLAG_ICLASS_READER_CC;
@@ -1454,93 +1421,57 @@ void ReaderIClass(uint8_t arg0) {
 	StartCountSspClk();
 	uint32_t start_time = 0;
 	uint32_t eof_time = 0;
+
+	if (selectIclassTag(resp, &eof_time)) {
+		result_status = FLAG_ICLASS_READER_CSN;
+		memcpy(card_data, resp, 8);
+	}
 	
-	uint16_t tryCnt = 0;
-	bool userCancelled = BUTTON_PRESS() || usb_poll_validate_length();
-	while (!userCancelled) {
-		// if only looking for one card try 2 times if we missed it the first time
-		if (try_once && tryCnt > 2) {
-			break;
-		}
-		tryCnt++;
-		if (!get_tracing()) {
-			DbpString("Trace full");
-			break;
+	start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
+	
+	//Read block 1, config
+	if (flagReadConfig) {
+		if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, &eof_time)) {
+			result_status |= FLAG_ICLASS_READER_CONF;
+			memcpy(card_data+8, resp, 8);
+		} else {
+			Dbprintf("Failed to read config block");
 		}
-		WDT_HIT();
-
-		read_status = handshakeIclassTag_ext(card_data, use_credit_key, &eof_time);
-
-		if (read_status == 0) continue;
-		if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
-		if (read_status == 2) result_status = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC;
-
 		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
-		// handshakeIclass returns CSN|CC, but the actual block
-		// layout is CSN|CONFIG|CC, so here we reorder the data,
-		// moving CC forward 8 bytes
-		memcpy(card_data+16, card_data+8, 8);
-		//Read block 1, config
-		if (flagReadConfig) {
-			if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, sizeof(resp), 10, 10, start_time, &eof_time)) {
-				result_status |= FLAG_ICLASS_READER_CONF;
-				memcpy(card_data+8, resp, 8);
-			} else {
-				Dbprintf("Failed to dump config block");
-			}
-			start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
-		}
+	}
 
-		//Read block 5, AA
-		if (flagReadAA) {
-			if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, &eof_time)) {
-				result_status |= FLAG_ICLASS_READER_AA;
-				memcpy(card_data + (8*5), resp, 8);
-			} else {
-				//Dbprintf("Failed to dump AA block");
-			}
+	//Read block 2, e-purse
+	if (flagReadCC) {
+		if (sendCmdGetResponseWithRetries(readEpurse, sizeof(readEpurse), resp, sizeof(resp), 10, 10, start_time, &eof_time)) {
+			result_status |= FLAG_ICLASS_READER_CC;
+			memcpy(card_data + (8*2), resp, 8);
+		} else {
+			Dbprintf("Failed to read e-purse");
 		}
+		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
+	}
 
-		// 0 : CSN
-		// 1 : Configuration
-		// 2 : e-purse
-		// 3 : kd / debit / aa2 (write-only)
-		// 4 : kc / credit / aa1 (write-only)
-		// 5 : AIA, Application issuer area
-		//Then we can 'ship' back the 6 * 8 bytes of data,
-		// with 0xFF:s in block 3 and 4.
-
-		LED_B_ON();
-		//Send back to client, but don't bother if we already sent this -
-		//  only useful if looping in arm (not try_once && not abort_after_read)
-		if (memcmp(last_csn, card_data, 8) != 0) {
-			// If caller requires that we get Conf, CC, AA, continue until we got it
-			if ( (result_status ^ FLAG_ICLASS_READER_CSN ^ flagReadConfig ^ flagReadCC ^ flagReadAA) == 0) {
-				cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
-				if (abort_after_read) {
-					FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-					LED_A_OFF();
-					LED_B_OFF();
-					return;
-				}
-				//Save that we already sent this....
-				memcpy(last_csn, card_data, 8);
-			}
-
+	//Read block 5, AA
+	if (flagReadAA) {
+		if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, sizeof(resp), 10, 10, start_time, &eof_time)) {
+			result_status |= FLAG_ICLASS_READER_AA;
+			memcpy(card_data + (8*5), resp, 8);
+		} else {
+			Dbprintf("Failed to read AA block");
 		}
-		LED_B_OFF();
-		userCancelled = BUTTON_PRESS() || usb_poll_validate_length();
-	}
-	if (userCancelled) {
-		cmd_send(CMD_ACK, 0xFF, 0, 0, card_data, 0);
-	} else {
-		cmd_send(CMD_ACK, 0, 0, 0, card_data, 0);
 	}
+
+	cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
+
 	LED_A_OFF();
 }
 
+
 void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
 
+	LED_A_ON();
+
+	bool use_credit_key = false;
 	uint8_t card_data[USB_CMD_DATA_SIZE]={0};
 	uint16_t block_crc_LUT[255] = {0};
 
@@ -1551,6 +1482,9 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
 	}
 	//Dbprintf("Lookup table: %02x %02x %02x" ,block_crc_LUT[0],block_crc_LUT[1],block_crc_LUT[2]);
 
+	uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 };
+	if (use_credit_key)
+		readcheck_cc[0] = ICLASS_CMD_READCHECK_KC;
 	uint8_t check[]       = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	uint8_t read[]        = { 0x0c, 0x00, 0x00, 0x00 };
 
@@ -1575,7 +1509,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
 	StartCountSspClk();
 	uint32_t start_time = 0;
 	uint32_t eof_time = 0;
-	
+
 	while (!BUTTON_PRESS()) {
 
 		WDT_HIT();
@@ -1585,34 +1519,33 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
 			break;
 		}
 
-		uint8_t read_status = handshakeIclassTag(card_data, &eof_time);
-		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
+		if (!selectIclassTag(card_data, &eof_time)) continue;
 
-		if (read_status < 2) continue;
+		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
+		if (!sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, sizeof(resp), 8, 3, start_time, &eof_time)) continue;
 
-		//for now replay captured auth (as cc not updated)
+		// replay captured auth (cc must not have been updated)
 		memcpy(check+5, MAC, 4);
 
+		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 		if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, sizeof(resp), 4, 5, start_time, &eof_time)) {
-			start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 			Dbprintf("Error: Authentication Fail!");
 			continue;
 		}
 
-		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 		//first get configuration block (block 1)
 		crc = block_crc_LUT[1];
 		read[1] = 1;
 		read[2] = crc >> 8;
 		read[3] = crc & 0xff;
 
+		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 		if (!sendCmdGetResponseWithRetries(read, sizeof(read), resp, sizeof(resp), 10, 10, start_time, &eof_time)) {
 			start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 			Dbprintf("Dump config (block 1) failed");
 			continue;
 		}
 
-		start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 		mem = resp[5];
 		memory.k16 = (mem & 0x80);
 		memory.book = (mem & 0x20);
@@ -1633,8 +1566,8 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
 			read[2] = crc >> 8;
 			read[3] = crc & 0xff;
 
+			start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 			if (sendCmdGetResponseWithRetries(read, sizeof(read), resp, sizeof(resp), 10, 10, start_time, &eof_time)) {
-				start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 				Dbprintf("     %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
 						block, resp[0], resp[1], resp[2],
 						resp[3], resp[4], resp[5],
@@ -1683,19 +1616,33 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
 			 0);
 
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+	LED_D_OFF();
 	LED_A_OFF();
 }
 
-void iClass_Authentication(uint8_t *MAC) {
-	uint8_t check[] = { ICLASS_CMD_CHECK_KD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	uint8_t resp[ICLASS_BUFFER_SIZE];
+
+void iClass_Check(uint8_t *MAC) {
+	uint8_t check[9] = {ICLASS_CMD_CHECK_KD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	uint8_t resp[4];
 	memcpy(check+5, MAC, 4);
-	bool isOK;
 	uint32_t eof_time;
-	isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, sizeof(resp), 4, 6, 0, &eof_time);
-	cmd_send(CMD_ACK,isOK, 0, 0, 0, 0);
+	bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, sizeof(resp), 4, 6, 0, &eof_time);
+	cmd_send(CMD_ACK, isOK, 0, 0, resp, sizeof(resp));
+}
+
+
+void iClass_Readcheck(uint8_t block, bool use_credit_key) {
+	uint8_t readcheck[2] = {ICLASS_CMD_READCHECK_KD, block};
+	if (use_credit_key) {
+		readcheck[0] = ICLASS_CMD_READCHECK_KC;
+	}
+	uint8_t resp[8];
+	uint32_t eof_time;
+	bool isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 8, 6, 0, &eof_time);
+	cmd_send(CMD_ACK, isOK, 0, 0, resp, sizeof(resp));
 }
 
+
 static bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) {
 	uint8_t readcmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; //0x88, 0x00 // can i use 0C?
 	char bl = blockNo;
@@ -1705,23 +1652,32 @@ static bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) {
 	uint8_t resp[10];
 	bool isOK = false;
 	uint32_t eof_time;
-	
-	//readcmd[1] = blockNo;
+
 	isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, sizeof(resp), 10, 10, 0, &eof_time);
 	memcpy(readdata, resp, sizeof(resp));
 
 	return isOK;
 }
 
+
 void iClass_ReadBlk(uint8_t blockno) {
+
+	LED_A_ON();
+
 	uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
 	bool isOK = false;
 	isOK = iClass_ReadBlock(blockno, readblockdata);
 	cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8);
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+	LED_D_OFF();
+
+	LED_A_OFF();
 }
 
 void iClass_Dump(uint8_t blockno, uint8_t numblks) {
+
+	LED_A_ON();
+
 	uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0};
 	bool isOK = false;
 	uint8_t blkCnt = 0;
@@ -1751,12 +1707,19 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) {
 	}
 	//return pointer to dump memory in arg3
 	cmd_send(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0);
+
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-	LEDsoff();
+	LED_D_OFF();
 	BigBuf_free();
+
+	LED_A_OFF();
 }
 
+
 static bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
+
+	LED_A_ON();
+
 	uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	//uint8_t readblockdata[10];
 	//write[1] = blockNo;
@@ -1768,7 +1731,7 @@ static bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
 	uint8_t resp[10];
 	bool isOK = false;
 	uint32_t eof_time = 0;
-	
+
 	isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 10, 10, 0, &eof_time);
 	uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
 	if (isOK) { //if reader responded correctly
@@ -1780,10 +1743,17 @@ static bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
 			}
 		}
 	}
+
+	LED_A_OFF();
+
 	return isOK;
 }
 
+
 void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) {
+
+	LED_A_ON();
+
 	bool isOK = iClass_WriteBlock_ext(blockNo, data);
 	if (isOK){
 		Dbprintf("Write block [%02x] successful", blockNo);
@@ -1791,7 +1761,11 @@ void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) {
 		Dbprintf("Write block [%02x] failed", blockNo);
 	}
 	cmd_send(CMD_ACK, isOK, 0, 0, 0, 0);
+
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+	LED_D_OFF();
+
+	LED_A_OFF();
 }
 
 void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
@@ -1819,5 +1793,6 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
 
 	cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-	LEDsoff();
+	LED_D_OFF();
+	LED_A_OFF();
 }
diff --git a/armsrc/iclass.h b/armsrc/iclass.h
index 3cbe79fb..9666e888 100644
--- a/armsrc/iclass.h
+++ b/armsrc/iclass.h
@@ -15,6 +15,7 @@
 #define ICLASS_H__
 
 #include <stdint.h>
+#include <stdbool.h>
 #include "common.h" // for RAMFUNC
 
 extern void RAMFUNC SnoopIClass(void);
@@ -22,7 +23,8 @@ extern void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t
 extern void ReaderIClass(uint8_t arg0);
 extern void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC);
 extern void IClass_iso14443A_GetPublic(uint8_t arg0);
-extern void iClass_Authentication(uint8_t *MAC);
+extern void iClass_Readcheck(uint8_t block, bool use_credit_key);
+extern void iClass_Check(uint8_t *MAC);
 extern void iClass_WriteBlock(uint8_t blockNo, uint8_t *data);
 extern void iClass_ReadBlk(uint8_t blockNo);
 extern void iClass_Dump(uint8_t blockno, uint8_t numblks);
diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c
index fff8b370..3b39d576 100644
--- a/armsrc/iso15693.c
+++ b/armsrc/iso15693.c
@@ -132,7 +132,7 @@ void CodeIso15693AsReader(uint8_t *cmd, int n) {
 
 	// EOF
 	ToSend[++ToSendMax] = 0x20; //0010 + 0000 padding
-	
+
 	ToSendMax++;
 }
 
@@ -249,14 +249,18 @@ void CodeIso15693AsTag(uint8_t *cmd, size_t len) {
 void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) {
 
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD);
-	
+
+	if (*start_time < DELAY_ARM_TO_TAG) {
+		*start_time = DELAY_ARM_TO_TAG;
+	}
+
 	*start_time = (*start_time - DELAY_ARM_TO_TAG) & 0xfffffff0;
 
 	while (GetCountSspClk() > *start_time) { // we may miss the intended time
 		*start_time += 16; // next possible time
 	}
 
-	
+
 	while (GetCountSspClk() < *start_time)
 		/* wait */ ;
 
@@ -275,7 +279,7 @@ void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time) {
 		WDT_HIT();
 	}
 	LED_B_OFF();
-	
+
 	*start_time = *start_time + DELAY_ARM_TO_TAG;
 
 }
@@ -289,7 +293,7 @@ void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time,
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K);
 
 	uint32_t modulation_start_time = *start_time - DELAY_ARM_TO_READER + 3 * 8;  // no need to transfer the unmodulated start of SOF
-	
+
 	while (GetCountSspClk() > (modulation_start_time & 0xfffffff8) + 3) { // we will miss the intended time
 		if (slot_time) {
 			modulation_start_time += slot_time; // use next available slot
@@ -298,7 +302,7 @@ void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time,
 		}
 	}
 
-	while (GetCountSspClk() < (modulation_start_time & 0xfffffff8)) 
+	while (GetCountSspClk() < (modulation_start_time & 0xfffffff8))
 		/* wait */ ;
 
 	uint8_t shift_delay = modulation_start_time & 0x00000007;
@@ -414,7 +418,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 			// DecodeTag->posCount = 2;
 			DecodeTag->state = STATE_TAG_SOF_HIGH;
 			break;
-				
+
 		case STATE_TAG_SOF_HIGH:
 			// waiting for 10 times high. Take average over the last 8
 			if (amplitude > DecodeTag->threshold_sof) {
@@ -428,7 +432,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 				}
 			} else { // high phase was too short
 				DecodeTag->posCount = 1;
-				DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
+				DecodeTag->previous_amplitude = amplitude;
 				DecodeTag->state = STATE_TAG_SOF_LOW;
 			}
 			break;
@@ -444,18 +448,18 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 				DecodeTag->sum2 = 0;
 				DecodeTag->posCount = 2;
 				DecodeTag->state = STATE_TAG_RECEIVING_DATA;
-				// FpgaDisableTracing(); // DEBUGGING
-				// Dbprintf("amplitude = %d, threshold_sof = %d, threshold_half/4 = %d, previous_amplitude = %d", 
-					// amplitude, 
-					// DecodeTag->threshold_sof, 
-					// DecodeTag->threshold_half/4,
-					// DecodeTag->previous_amplitude); // DEBUGGING
+				FpgaDisableTracing(); // DEBUGGING
+				Dbprintf("amplitude = %d, threshold_sof = %d, threshold_half/4 = %d, previous_amplitude = %d",
+					amplitude,
+					DecodeTag->threshold_sof,
+					DecodeTag->threshold_half/4,
+					DecodeTag->previous_amplitude); // DEBUGGING
 				LED_C_ON();
 			} else {
 				DecodeTag->posCount++;
 				if (DecodeTag->posCount > 13) { // high phase too long
 					DecodeTag->posCount = 0;
-					DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
+					DecodeTag->previous_amplitude = amplitude;
 					DecodeTag->state = STATE_TAG_SOF_LOW;
 					LED_C_OFF();
 				}
@@ -478,7 +482,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 						DecodeTag->state = STATE_TAG_EOF;
 					} else {
 						DecodeTag->posCount = 0;
-						DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
+						DecodeTag->previous_amplitude = amplitude;
 						DecodeTag->state = STATE_TAG_SOF_LOW;
 						LED_C_OFF();
 					}
@@ -508,7 +512,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 					// logic 0
 					if (DecodeTag->lastBit == SOF_PART1) { // incomplete SOF
 						DecodeTag->posCount = 0;
-						DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
+						DecodeTag->previous_amplitude = amplitude;
 						DecodeTag->state = STATE_TAG_SOF_LOW;
 						LED_C_OFF();
 					} else {
@@ -522,7 +526,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 							if (DecodeTag->len > DecodeTag->max_len) {
 								// buffer overflow, give up
 								DecodeTag->posCount = 0;
-								DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
+								DecodeTag->previous_amplitude = amplitude;
 								DecodeTag->state = STATE_TAG_SOF_LOW;
 								LED_C_OFF();
 							}
@@ -561,7 +565,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 					DecodeTag->state = STATE_TAG_EOF_TAIL;
 				} else {
 					DecodeTag->posCount = 0;
-					DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
+					DecodeTag->previous_amplitude = amplitude;
 					DecodeTag->state = STATE_TAG_SOF_LOW;
 					LED_C_OFF();
 				}
@@ -585,7 +589,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 					return true;
 				} else {
 					DecodeTag->posCount = 0;
-					DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
+					DecodeTag->previous_amplitude = amplitude;
 					DecodeTag->state = STATE_TAG_SOF_LOW;
 					LED_C_OFF();
 				}
@@ -598,8 +602,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1
 }
 
 
-static void DecodeTagInit(DecodeTag_t *DecodeTag, uint8_t *data, uint16_t max_len)
-{
+static void DecodeTagInit(DecodeTag_t *DecodeTag, uint8_t *data, uint16_t max_len) {
 	DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
 	DecodeTag->posCount = 0;
 	DecodeTag->state = STATE_TAG_SOF_LOW;
@@ -608,8 +611,7 @@ static void DecodeTagInit(DecodeTag_t *DecodeTag, uint8_t *data, uint16_t max_le
 }
 
 
-static void DecodeTagReset(DecodeTag_t *DecodeTag)
-{
+static void DecodeTagReset(DecodeTag_t *DecodeTag) {
 	DecodeTag->posCount = 0;
 	DecodeTag->state = STATE_TAG_SOF_LOW;
 	DecodeTag->previous_amplitude = MAX_PREVIOUS_AMPLITUDE;
@@ -649,10 +651,10 @@ int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeo
 
 		samples++;
 		if (samples == 1) {
-		    // DMA has transferred the very first data
+			// DMA has transferred the very first data
 			dma_start_time = GetCountSspClk() & 0xfffffff0;
 		}
-		
+
 		uint16_t tagdata = *upTo++;
 
 		if(upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) {                // we have read all of the DMA buffer content.
@@ -680,7 +682,7 @@ int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeo
 		}
 
 		if (samples > timeout && DecodeTag.state < STATE_TAG_RECEIVING_DATA) {
-			ret = -1;	// timeout
+			ret = -1;   // timeout
 			break;
 		}
 
@@ -699,9 +701,9 @@ int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeo
 						- DecodeTag.len * 8 * 8 * 16 // time for byte transfers
 						- 32 * 16  // time for SOF transfer
 						- (DecodeTag.lastBit != SOF_PART2?32*16:0); // time for EOF transfer
-						
+
 	if (DEBUG) Dbprintf("timing: sof_time = %d, eof_time = %d", sof_time, *eof_time);
-	
+
 	LogTrace_ISO15693(DecodeTag.output, DecodeTag.len, sof_time*4, *eof_time*4, NULL, false);
 
 	return DecodeTag.len;
@@ -1089,20 +1091,19 @@ static void BuildIdentifyRequest(void)
 //-----------------------------------------------------------------------------
 void AcquireRawAdcSamplesIso15693(void)
 {
-	LEDsoff();
 	LED_A_ON();
 
 	uint8_t *dest = BigBuf_get_addr();
 
 	FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER);
+	LED_D_ON();
 	FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
 	SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
 
 	BuildIdentifyRequest();
 
 	// Give the tags time to energize
-	LED_D_ON();
 	SpinDelay(100);
 
 	// Now send the command
@@ -1129,6 +1130,7 @@ void AcquireRawAdcSamplesIso15693(void)
 void SnoopIso15693(void)
 {
 	LED_A_ON();
+	
 	FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
 	BigBuf_free();
 
@@ -1348,17 +1350,13 @@ static void BuildInventoryResponse(uint8_t *uid)
 //  return: length of received data, or -1 for timeout
 int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, uint32_t *eof_time) {
 
-	LED_A_ON();
-	LED_B_OFF();
-	LED_C_OFF();
-
 	if (init) {
 		Iso15693InitReader();
 		StartCountSspClk();
 	}
-	
+
 	int answerLen = 0;
-	
+
 	if (!speed) {
 		// low speed (1 out of 256)
 		CodeIso15693AsReader256(send, sendlen);
@@ -1367,18 +1365,13 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *recv,
 		CodeIso15693AsReader(send, sendlen);
 	}
 
-	if (start_time == 0) {
-		start_time = GetCountSspClk();
-	}
 	TransmitTo15693Tag(ToSend, ToSendMax, &start_time);
 
 	// Now wait for a response
 	if (recv != NULL) {
-		answerLen = GetIso15693AnswerFromTag(recv, max_recv_len, DELAY_ISO15693_VCD_TO_VICC_READER * 2, eof_time);
+		answerLen = GetIso15693AnswerFromTag(recv, max_recv_len, ISO15693_READER_TIMEOUT, eof_time);
 	}
 
-	LED_A_OFF();
-
 	return answerLen;
 }
 
@@ -1462,9 +1455,8 @@ void SetDebugIso15693(uint32_t debug) {
 // Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector.
 // all demodulation performed in arm rather than host. - greg
 //---------------------------------------------------------------------------------------
-void ReaderIso15693(uint32_t parameter)
-{
-	LEDsoff();
+void ReaderIso15693(uint32_t parameter) {
+
 	LED_A_ON();
 
 	set_tracing(true);
@@ -1564,9 +1556,8 @@ void ReaderIso15693(uint32_t parameter)
 // Simulate an ISO15693 TAG.
 // For Inventory command: print command and send Inventory Response with given UID
 // TODO: interpret other reader commands and send appropriate response
-void SimTagIso15693(uint32_t parameter, uint8_t *uid)
-{
-	LEDsoff();
+void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
+
 	LED_A_ON();
 
 	FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@@ -1597,7 +1588,8 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
 	}
 
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-	LEDsoff();
+	LED_D_OFF();
+	LED_A_OFF();
 }
 
 
@@ -1605,7 +1597,6 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
 // (some manufactures offer a way to read the AFI, though)
 void BruteforceIso15693Afi(uint32_t speed)
 {
-	LEDsoff();
 	LED_A_ON();
 
 	uint8_t data[6];
@@ -1648,17 +1639,19 @@ void BruteforceIso15693Afi(uint32_t speed)
 	Dbprintf("AFI Bruteforcing done.");
 
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-	LEDsoff();
+	LED_D_OFF();
+	LED_A_OFF();
+
 }
 
 // Allows to directly send commands to the tag via the client
 void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t data[]) {
 
+	LED_A_ON();
+
 	int recvlen = 0;
 	uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
 	uint32_t eof_time;
-	
-	LED_A_ON();
 
 	if (DEBUG) {
 		Dbprintf("SEND:");
@@ -1695,17 +1688,16 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
 //-----------------------------------------------------------------------------
 
 // Set the UID to the tag (based on Iceman work).
-void SetTag15693Uid(uint8_t *uid)
-{
-	uint8_t cmd[4][9] = {0x00};
+void SetTag15693Uid(uint8_t *uid) {
 
+	LED_A_ON();
+
+	uint8_t cmd[4][9] = {0x00};
 	uint16_t crc;
 
 	int recvlen = 0;
 	uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
 	uint32_t eof_time;
-	
-	LED_A_ON();
 
 	// Command 1 : 02213E00000000
 	cmd[0][0] = 0x02;
@@ -1767,8 +1759,6 @@ void SetTag15693Uid(uint8_t *uid)
 		cmd_send(CMD_ACK, recvlen>ISO15693_MAX_RESPONSE_LENGTH?ISO15693_MAX_RESPONSE_LENGTH:recvlen, 0, 0, recvbuf, ISO15693_MAX_RESPONSE_LENGTH);
 	}
 
-	LED_D_OFF();
-
 	LED_A_OFF();
 }
 
diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h
index 96a2b39b..5cbe5ecc 100644
--- a/armsrc/iso15693.h
+++ b/armsrc/iso15693.h
@@ -21,6 +21,8 @@
 //SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when acting as reader. All values should be multiples of 16
 #define DELAY_ISO15693_VCD_TO_VICC_READER 1056 // 1056/3,39MHz = 311.5us from end of command EOF to start of tag response
 #define DELAY_ISO15693_VICC_TO_VCD_READER 1024 // 1024/3.39MHz = 302.1us between end of tag response and next reader command
+// times in samples @ 212kHz when acting as reader
+#define ISO15693_READER_TIMEOUT            330 // 330/212kHz = 1558us, should be even enough for iClass tags responding to ACTALL
 
 void Iso15693InitReader();
 void CodeIso15693AsReader(uint8_t *cmd, int n);
diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c
index 81738686..195a282d 100644
--- a/client/cmdhficlass.c
+++ b/client/cmdhficlass.c
@@ -35,7 +35,6 @@
 #include "util_posix.h"
 #include "cmdhf14a.h" // DropField()
 
-static int CmdHelp(const char *Cmd);
 
 #define ICLASS_KEYS_MAX 8
 static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
@@ -49,12 +48,14 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
 		{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
 };
 
+
 typedef struct iclass_block {
-    uint8_t d[8];
+	uint8_t d[8];
 } iclass_block_t;
 
-int usage_hf_iclass_chk(void) {
-	PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");	
+
+static void usage_hf_iclass_chk(void) {
+	PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
 	PrintAndLog("Usage: hf iclass chk [h|e|r] <f  (*.dic)>");
 	PrintAndLog("Options:");
 	PrintAndLog("h             Show this help");
@@ -62,31 +63,25 @@ int usage_hf_iclass_chk(void) {
 	PrintAndLog("      e             target Elite / High security key scheme");
 	PrintAndLog("      r             interpret dictionary file as raw (diversified keys)");
 	PrintAndLog("Samples:");
-	PrintAndLog("		 hf iclass chk f default_iclass_keys.dic");	
-	PrintAndLog("		 hf iclass chk f default_iclass_keys.dic e");	
-	return 0;
+	PrintAndLog("        hf iclass chk f default_iclass_keys.dic");
+	PrintAndLog("        hf iclass chk f default_iclass_keys.dic e");
 }
 
-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) {
+static int CmdHFiClassList(const char *Cmd) {
 	PrintAndLog("Deprecated command, use 'hf list iclass' instead");
 	return 0;
 }
 
-int CmdHFiClassSnoop(const char *Cmd) {
+
+static int CmdHFiClassSnoop(const char *Cmd) {
 	UsbCommand c = {CMD_SNOOP_ICLASS};
 	SendCommand(&c);
 	return 0;
 }
 
-int usage_hf_iclass_sim(void) {
+
+static void usage_hf_iclass_sim(void) {
 	PrintAndLog("Usage:  hf iclass sim <option> [CSN]");
 	PrintAndLog("        options");
 	PrintAndLog("                0 <CSN> simulate the given CSN");
@@ -97,9 +92,9 @@ int usage_hf_iclass_sim(void) {
 	PrintAndLog("        example: hf iclass sim 2");
 	PrintAndLog("        example: hf iclass eload 'tagdump.bin'");
 	PrintAndLog("                 hf iclass sim 3");
-	return 0;
 }
 
+
 // the original malicious IDs from Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult,
 // and Milosch Meriac. Dismantling iClass and iClass Elite.
 #define NUM_CSNS 15
@@ -127,32 +122,34 @@ static uint8_t csns[8 * NUM_CSNS] = {
 
 // #define NUM_CSNS 9
 // static uint8_t csns[8 * NUM_CSNS] = {
-    // 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0,
-    // 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0
-    // //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0
+	// 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0,
+	// 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0
+	// //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0
 // };
 
 
-int CmdHFiClassSim(const char *Cmd) {
+static 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();
+		usage_hf_iclass_sim();
+		return 0;
 	}
 	simType = param_get8ex(Cmd, 0, 0, 10);
 
 	if (simType == ICLASS_SIM_MODE_CSN) {
 		if (param_gethex(Cmd, 1, CSN, 16)) {
 			PrintAndLog("A CSN should consist of 16 HEX symbols");
-			return usage_hf_iclass_sim();
+			usage_hf_iclass_sim();
+			return 0;
 		}
 		PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
 	}
@@ -186,8 +183,8 @@ int CmdHFiClassSim(const char *Cmd) {
 		void* dump = malloc(datalen);
 		for(int i = 0; i < NUM_CSNS; i++) {
 			memcpy(dump + i*24, csns+i*8, 8); //CSN
-            //copy CC from response
-            memcpy(dump + i*24 + 8, resp.d.asBytes + i*16, 8);
+			//copy CC from response
+			memcpy(dump + i*24 + 8, resp.d.asBytes + i*16, 8);
 			//Then comes NR_MAC (eight bytes from the response)
 			memcpy(dump + i*24 + 16, resp.d.asBytes + i*16 + 8, 8);
 		}
@@ -202,17 +199,18 @@ int CmdHFiClassSim(const char *Cmd) {
 
 	} else {
 		PrintAndLog("Undefined simtype %d", simType);
-		return usage_hf_iclass_sim();
+		usage_hf_iclass_sim();
+		return 0;
 	}
 
 	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_CC | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_AA |
-		    FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY } };
+			FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_AA} };
 	// loop in client not device - else on windows have a communication error
 	UsbCommand resp;
 	while(!ukbhit()){
@@ -232,7 +230,7 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) {
 				PrintAndLog("   CSN: %s",sprint_hex(data,8));
 				tagFound = true;
 			}
-			if( readStatus & FLAG_ICLASS_READER_CC) { 
+			if( readStatus & FLAG_ICLASS_READER_CC) {
 				PrintAndLog("    CC: %s",sprint_hex(data+16,8));
 			}
 			if( readStatus & FLAG_ICLASS_READER_CONF) {
@@ -244,7 +242,7 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) {
 				for (int i = 0; i<8; i++) {
 					if (data[8*5+i] != 0xFF) {
 						legacy = false;
-					} 
+					}
 				}
 				PrintAndLog("      : Possible iClass %s",(legacy) ? "(legacy tag)" : "(NOT legacy tag)");
 			}
@@ -258,11 +256,13 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) {
 	return 0;
 }
 
-int CmdHFiClassReader(const char *Cmd) {
+
+static int CmdHFiClassReader(const char *Cmd) {
 	return HFiClassReader(Cmd, true, true);
 }
 
-int CmdHFiClassReader_Replay(const char *Cmd) {
+
+static int CmdHFiClassReader_Replay(const char *Cmd) {
 	uint8_t readerType = 0;
 	uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
 
@@ -284,26 +284,22 @@ int CmdHFiClassReader_Replay(const char *Cmd) {
 	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 hf_iclass_eload_usage(void) {
+static void usage_hf_iclass_eload(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) {
+
+static int CmdHFiClassELoad(const char *Cmd) {
 
 	char opt = param_getchar(Cmd, 0);
-	if (strlen(Cmd)<1 || opt == 'h')
-		return hf_iclass_eload_usage();
+	if (strlen(Cmd)<1 || opt == 'h') {
+		usage_hf_iclass_eload();
+		return 0;
+	}
 
 	//File handling and reading
 	FILE *f;
@@ -311,7 +307,8 @@ int CmdHFiClassELoad(const char *Cmd) {
 	if (opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) {
 		f = fopen(filename, "rb");
 	} else {
-		return hf_iclass_eload_usage();
+		usage_hf_iclass_eload();
+		return 0;
 	}
 
 	if (!f) {
@@ -337,7 +334,7 @@ int CmdHFiClassELoad(const char *Cmd) {
 	printIclassDumpInfo(dump);
 	//Validate
 
-	if (bytes_read < fsize)	{
+	if (bytes_read < fsize) {
 		prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
 		free(dump);
 		return 1;
@@ -359,6 +356,7 @@ int CmdHFiClassELoad(const char *Cmd) {
 	return 0;
 }
 
+
 static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) {
 	FILE *f = fopen(filename, "rb");
 	if(!f) {
@@ -383,7 +381,8 @@ static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) {
 	return 0;
 }
 
-int usage_hf_iclass_decrypt(void) {
+
+static void 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");
@@ -394,10 +393,10 @@ int usage_hf_iclass_decrypt(void) {
 	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) {
+
+static int CmdHFiClassDecrypt(const char *Cmd) {
 	uint8_t key[16] = { 0 };
 	if(readKeyfile("iclass_decryptionkey.bin", 16, key))
 	{
@@ -406,8 +405,10 @@ int CmdHFiClassDecrypt(const char *Cmd) {
 	}
 	PrintAndLog("Decryption file found... ");
 	char opt = param_getchar(Cmd, 0);
-	if (strlen(Cmd)<1 || opt == 'h')
-		return usage_hf_iclass_decrypt();
+	if (strlen(Cmd)<1 || opt == 'h') {
+		usage_hf_iclass_decrypt();
+		return 0;
+	}
 
 	//Open the tagdump-file
 	FILE *f;
@@ -419,7 +420,8 @@ int CmdHFiClassDecrypt(const char *Cmd) {
 			return 1;
 		}
 	} else {
-		return usage_hf_iclass_decrypt();
+		usage_hf_iclass_decrypt();
+		return 0;
 	}
 
 	fseek(f, 0, SEEK_END);
@@ -457,7 +459,8 @@ int CmdHFiClassDecrypt(const char *Cmd) {
 	return 0;
 }
 
-int usage_hf_iclass_encrypt(void) {
+
+static void 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");
@@ -465,9 +468,9 @@ int usage_hf_iclass_encrypt(void) {
 	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))
@@ -481,7 +484,7 @@ static int iClassEncryptBlkData(uint8_t *blkData) {
 	uint8_t *encrypted = encryptedData;
 	mbedtls_des3_context ctx = { {0} };
 	mbedtls_des3_set2key_enc( &ctx, key);
-	
+
 	mbedtls_des3_crypt_ecb(&ctx, blkData,encrypted);
 	//printvar("decrypted block", decrypted, 8);
 	memcpy(blkData,encrypted,8);
@@ -489,25 +492,26 @@ static int iClassEncryptBlkData(uint8_t *blkData) {
 	return 1;
 }
 
-int CmdHFiClassEncryptBlk(const char *Cmd) {
+
+static int CmdHFiClassEncryptBlk(const char *Cmd) {
 	uint8_t blkData[8] = {0};
 	char opt = param_getchar(Cmd, 0);
-	if (strlen(Cmd)<1 || opt == 'h')
-		return usage_hf_iclass_encrypt();
-
+	if (strlen(Cmd)<1 || opt == 'h') {
+		usage_hf_iclass_encrypt();
+		return 0;
+	}
 	//get the bytes to encrypt
-	if (param_gethex(Cmd, 0, blkData, 16))
-	{
+	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]) {
+
+static 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);
@@ -515,18 +519,15 @@ void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_t MAC[4
 	//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) {
+
+static bool select_only(uint8_t *CSN, 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))
-	{
+	if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
 		PrintAndLog("Command execute timeout");
 		return false;
 	}
@@ -534,45 +535,81 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v
 	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));
-	}
-	if(isOK <= 1){
-		PrintAndLog("Failed to obtain CC! Aborting");
+	memcpy(CSN, data, 8);
+
+	if (isOK > 0) {
+		if (verbose) PrintAndLog("CSN: %s", sprint_hex(CSN, 8));
+	} else {
+		PrintAndLog("Failed to select card! Aborting");
 		return false;
 	}
-	return true;	
+	return true;
 }
 
+
+static void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
+	uint8_t keytable[128] = {0};
+	uint8_t key_index[8] = {0};
+	if (elite) {
+		uint8_t key_sel[8] = { 0 };
+		uint8_t key_sel_p[8] = { 0 };
+		hash2(KEY, keytable);
+		hash1(CSN, key_index);
+		for(uint8_t i = 0; i < 8 ; i++)
+			key_sel[i] = keytable[key_index[i]] & 0xFF;
+
+		//Permute from iclass format to standard format
+		permutekey_rev(key_sel, key_sel_p);
+		diversifyKey(CSN, key_sel_p, div_key);
+	} else {
+		diversifyKey(CSN, KEY, div_key);
+	}
+}
+
+
 static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
-	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 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};
 
-	if (!select_only(CSN, CCNR, use_credit_key, verbose))
+	if (!select_only(CSN, verbose))
 		return false;
 
 	//get div_key
-	if(rawkey)
+	if (rawkey)
 		memcpy(div_key, KEY, 8);
 	else
 		HFiClassCalcDivKey(CSN, KEY, div_key, elite);
-	 if (verbose) PrintAndLog("Authing with %s: %02x%02x%02x%02x%02x%02x%02x%02x", rawkey ? "raw key" : "diversified key", div_key[0],div_key[1],div_key[2],div_key[3],div_key[4],div_key[5],div_key[6],div_key[7]);
 
-	doMAC(CCNR, div_key, MAC);
+	if (verbose) PrintAndLog("Authenticating with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8));
+
 	UsbCommand resp;
-	UsbCommand d = {CMD_ICLASS_AUTHENTICATION, {0}};
+	UsbCommand d = {CMD_ICLASS_READCHECK, {2, use_credit_key, 0}};
+
+	clearCommandBuffer();
+	SendCommand(&d);
+
+	if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
+		if (verbose) PrintAndLog("Auth Command (READCHECK[2]) execute timeout");
+		return false;
+	}
+	bool isOK = resp.arg[0];
+	if (!isOK) {
+		if (verbose) PrintAndLog("Couldn't get Card Challenge");
+		return false;
+	}
+	memcpy(CCNR, resp.d.asBytes, 8);
+
+	doMAC(CCNR, div_key, MAC);
+
+	d.cmd = CMD_ICLASS_CHECK;
 	memcpy(d.d.asBytes, MAC, 4);
 	clearCommandBuffer();
 	SendCommand(&d);
-	if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
-	{
-		if (verbose) PrintAndLog("Auth Command execute timeout");
+	if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
+		if (verbose) PrintAndLog("Auth Command (CHECK) execute timeout");
 		return false;
 	}
-	uint8_t isOK = resp.arg[0] & 0xff;
+	isOK = resp.arg[0];
 	if (!isOK) {
 		if (verbose) PrintAndLog("Authentication error");
 		return false;
@@ -580,7 +617,8 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
 	return true;
 }
 
-int usage_hf_iclass_dump(void) {
+
+static void usage_hf_iclass_dump(void) {
 	PrintAndLog("Usage:  hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
 	PrintAndLog("Options:");
 	PrintAndLog("  f <filename> : specify a filename to save dump to");
@@ -591,14 +629,45 @@ int usage_hf_iclass_dump(void) {
 	PrintAndLog("                 See 'hf iclass sim 2'. This key should be on iclass-format");
 	PrintAndLog("  r            : If 'r' is specified, the key is interpreted as raw block 3/4");
 	PrintAndLog("  NOTE: * = required");
-  PrintAndLog("Samples:");
+	PrintAndLog("Samples:");
 	PrintAndLog("  hf iclass dump k 001122334455667B");
 	PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
 	PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA e");
-	return 0;
 }
 
-int CmdHFiClassReader_Dump(const char *Cmd) {
+
+static void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
+	uint8_t mem_config;
+	memcpy(&mem_config, iclass_dump + 13,1);
+	uint8_t maxmemcount;
+	uint8_t filemaxblock = filesize / 8;
+	if (mem_config & 0x80)
+		maxmemcount = 255;
+	else
+		maxmemcount = 31;
+	//PrintAndLog   ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
+
+	if (startblock == 0)
+		startblock = 6;
+	if ((endblock > maxmemcount) || (endblock == 0))
+		endblock = maxmemcount;
+
+	// remember endblock need to relate to zero-index arrays.
+	if (endblock > filemaxblock-1)
+		endblock = filemaxblock;
+
+	int i = startblock;
+	printf("------+--+-------------------------+\n");
+	while (i <= endblock) {
+		uint8_t *blk = iclass_dump + (i * 8);
+		printf("Block |%02X| %s|\n", i, sprint_hex(blk, 8) );
+		i++;
+	}
+	printf("------+--+-------------------------+\n");
+}
+
+
+static int CmdHFiClassReader_Dump(const char *Cmd) {
 
 	uint8_t MAC[4] = {0x00,0x00,0x00,0x00};
 	uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -629,7 +698,8 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 		{
 		case 'h':
 		case 'H':
-			return usage_hf_iclass_dump();
+			usage_hf_iclass_dump();
+			return 0;
 		case 'c':
 		case 'C':
 			have_credit_key = true;
@@ -657,7 +727,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 			break;
 		case 'f':
 		case 'F':
-			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); 
+			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
 			if (fileNameLen < 1) {
 				PrintAndLog("No filename found after f");
 				errors = true;
@@ -668,7 +738,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 		case 'K':
 			have_debit_key = true;
 			dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
-			if (dataLen == 16) { 
+			if (dataLen == 16) {
 				errors = param_gethex(tempStr, 0, KEY, dataLen);
 			} else if (dataLen == 1) {
 				keyNbr = param_get8(Cmd, cmdp+1);
@@ -694,16 +764,21 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 			errors = true;
 			break;
 		}
-		if(errors) return usage_hf_iclass_dump();
+		if (errors) {
+			usage_hf_iclass_dump();
+			return 0;
+		}
 	}
 
-	if (cmdp < 2) return usage_hf_iclass_dump();
+	if (cmdp < 2) {
+		usage_hf_iclass_dump();
+		return 0;
+	}
 	// if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
 	if (!have_debit_key && have_credit_key) use_credit_key = true;
 
 	//get config and first 3 blocks
-	UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
-					FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY}};
+	UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF}};
 	UsbCommand resp;
 	uint8_t tag_data[255*8];
 
@@ -739,7 +814,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 			return 0;
 		}
 	}
-	
+
 	// begin dump
 	UsbCommand w = {CMD_ICLASS_DUMP, {blockno, numblks-blockno+1}};
 	clearCommandBuffer();
@@ -796,7 +871,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 				PrintAndLog("Read Block Failed 2");
 				DropField();
 				return 0;
-			}		
+			}
 
 			startindex = resp.arg[2];
 			if (blocksRead*8 > sizeof(tag_data)-gotBytes) {
@@ -806,7 +881,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 			// get dumped data from bigbuf
 			GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false);
 
-			gotBytes += blocksRead*8;			
+			gotBytes += blocksRead*8;
 		} else { //field is still on - turn it off...
 			DropField();
 		}
@@ -819,11 +894,11 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 	printf("------+--+-------------------------+\n");
 	printf("CSN   |00| %s|\n",sprint_hex(tag_data, 8));
 	printIclassDumpContents(tag_data, 1, (gotBytes/8), gotBytes);
-	
+
 	if (filename[0] == 0){
 		snprintf(filename, FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
-		    tag_data[0],tag_data[1],tag_data[2],tag_data[3],
-		    tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
+			tag_data[0],tag_data[1],tag_data[2],tag_data[3],
+			tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
 	}
 
 	// save the dump to .bin file
@@ -832,6 +907,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) {
 	return 1;
 }
 
+
 static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
 	uint8_t MAC[4]={0x00,0x00,0x00,0x00};
 	uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -844,7 +920,7 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c
 	UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno}};
 	memcpy(w.d.asBytes, bldata, 8);
 	memcpy(w.d.asBytes + 8, MAC, 4);
-	
+
 	clearCommandBuffer();
 	SendCommand(&w);
 	if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
@@ -861,22 +937,23 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c
 	return 1;
 }
 
-int usage_hf_iclass_writeblock(void) {
+
+static void usage_hf_iclass_writeblock(void) {
 	PrintAndLog("Options:");
-  PrintAndLog("  b <Block> : The block number as 2 hex symbols");
-  PrintAndLog("  d <data>  : Set the Data to write as 16 hex symbols");
+	PrintAndLog("  b <Block> : The block number as 2 hex symbols");
+	PrintAndLog("  d <data>  : Set the Data to write as 16 hex symbols");
 	PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory");
-  PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n");
-  PrintAndLog("  e         : If 'e' is specified, elite computations applied to key");
-  PrintAndLog("  r         : If 'r' is specified, no computations applied to key");
-  PrintAndLog("Samples:");
+	PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n");
+	PrintAndLog("  e         : If 'e' is specified, elite computations applied to key");
+	PrintAndLog("  r         : If 'r' is specified, no computations applied to key");
+	PrintAndLog("Samples:");
 	PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
 	PrintAndLog("  hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
 	PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
-	return 0;
 }
 
-int CmdHFiClass_WriteBlock(const char *Cmd) {
+
+static int CmdHFiClass_WriteBlock(const char *Cmd) {
 	uint8_t blockno=0;
 	uint8_t bldata[8]={0,0,0,0,0,0,0,0};
 	uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -894,7 +971,8 @@ int CmdHFiClass_WriteBlock(const char *Cmd) {
 		{
 		case 'h':
 		case 'H':
-			return usage_hf_iclass_writeblock();
+			usage_hf_iclass_writeblock();
+			return 0;
 		case 'b':
 		case 'B':
 			if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
@@ -925,7 +1003,7 @@ int CmdHFiClass_WriteBlock(const char *Cmd) {
 		case 'k':
 		case 'K':
 			dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
-			if (dataLen == 16) { 
+			if (dataLen == 16) {
 				errors = param_gethex(tempStr, 0, KEY, dataLen);
 			} else if (dataLen == 1) {
 				keyNbr = param_get8(Cmd, cmdp+1);
@@ -951,16 +1029,23 @@ int CmdHFiClass_WriteBlock(const char *Cmd) {
 			errors = true;
 			break;
 		}
-		if(errors) return usage_hf_iclass_writeblock();
+		if(errors) {
+			usage_hf_iclass_writeblock();
+			return 0;
+		}
 	}
 
-	if (cmdp < 6) return usage_hf_iclass_writeblock();
+	if (cmdp < 6) {
+		usage_hf_iclass_writeblock();
+		return 0;
+	}
 	int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
 	DropField();
 	return ans;
 }
 
-int usage_hf_iclass_clone(void) {
+
+static void usage_hf_iclass_clone(void) {
 	PrintAndLog("Usage:  hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
 	PrintAndLog("Options:");
 	PrintAndLog("  f <filename>: specify a filename to clone from");
@@ -974,10 +1059,10 @@ int usage_hf_iclass_clone(void) {
 	PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
 	PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
 	PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
-	return -1;
 }
 
-int CmdHFiClassCloneTag(const char *Cmd) {
+
+static int CmdHFiClassCloneTag(const char *Cmd) {
 	char filename[FILE_PATH_SIZE] = {0};
 	char tempStr[50]={0};
 	uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -997,7 +1082,8 @@ int CmdHFiClassCloneTag(const char *Cmd) {
 		{
 		case 'h':
 		case 'H':
-			return usage_hf_iclass_clone();
+			usage_hf_iclass_clone();
+			return 0;
 		case 'b':
 		case 'B':
 			if (param_gethex(Cmd, cmdp+1, &startblock, 2)) {
@@ -1018,7 +1104,7 @@ int CmdHFiClassCloneTag(const char *Cmd) {
 			break;
 		case 'f':
 		case 'F':
-			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); 
+			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
 			if (fileNameLen < 1) {
 				PrintAndLog("No filename found after f");
 				errors = true;
@@ -1028,7 +1114,7 @@ int CmdHFiClassCloneTag(const char *Cmd) {
 		case 'k':
 		case 'K':
 			dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
-			if (dataLen == 16) { 
+			if (dataLen == 16) {
 				errors = param_gethex(tempStr, 0, KEY, dataLen);
 			} else if (dataLen == 1) {
 				keyNbr = param_get8(Cmd, cmdp+1);
@@ -1062,10 +1148,16 @@ int CmdHFiClassCloneTag(const char *Cmd) {
 			errors = true;
 			break;
 		}
-		if(errors) return usage_hf_iclass_clone();
+		if (errors) {
+			usage_hf_iclass_clone();
+			return 0;
+		}
 	}
 
-	if (cmdp < 8) return usage_hf_iclass_clone();
+	if (cmdp < 8) {
+		usage_hf_iclass_clone();
+		return 0;
+	}
 
 	FILE *f;
 
@@ -1108,21 +1200,21 @@ int CmdHFiClassCloneTag(const char *Cmd) {
 	uint8_t *ptr;
 	// calculate all mac for every the block we will write
 	for (i = startblock; i <= endblock; i++){
-	    Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
-	    // usb command d start pointer = d + (i - 6) * 12
-	    // memcpy(pointer,tag_data[i - 6],8) 8 bytes
-	    // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
-	    // next one
-	    ptr = w.d.asBytes + (i - startblock) * 12;
-	    memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
-	    memcpy(ptr + 8,MAC, 4);
+		Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
+		// usb command d start pointer = d + (i - 6) * 12
+		// memcpy(pointer,tag_data[i - 6],8) 8 bytes
+		// memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
+		// next one
+		ptr = w.d.asBytes + (i - startblock) * 12;
+		memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
+		memcpy(ptr + 8,MAC, 4);
 	}
 	uint8_t p[12];
 	for (i = 0; i <= endblock - startblock;i++){
-	    memcpy(p,w.d.asBytes + (i * 12),12);
-	    printf("Block |%02x|",i + startblock);
-	    printf(" %02x%02x%02x%02x%02x%02x%02x%02x |",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]);
-	    printf(" MAC |%02x%02x%02x%02x|\n",p[8],p[9],p[10],p[11]);
+		memcpy(p,w.d.asBytes + (i * 12),12);
+		printf("Block |%02x|",i + startblock);
+		printf(" %02x%02x%02x%02x%02x%02x%02x%02x |",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]);
+		printf(" MAC |%02x%02x%02x%02x|\n",p[8],p[9],p[10],p[11]);
 	}
 	UsbCommand resp;
 	SendCommand(&w);
@@ -1134,7 +1226,9 @@ int CmdHFiClassCloneTag(const char *Cmd) {
 	return 1;
 }
 
+
 static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
+
 	uint8_t MAC[4]={0x00,0x00,0x00,0x00};
 	uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 
@@ -1142,9 +1236,8 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
 		if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose))
 			return 0;
 	} else {
-		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};
-		if (!select_only(CSN, CCNR, (keyType==0x18), verbose))
+		uint8_t CSN[8];
+		if (!select_only(CSN, verbose))
 			return 0;
 	}
 
@@ -1152,8 +1245,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
 	UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}};
 	clearCommandBuffer();
 	SendCommand(&w);
-	if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
-	{
+	if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
 		PrintAndLog("Command execute timeout");
 		return 0;
 	}
@@ -1167,22 +1259,23 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
 	return 1;
 }
 
-int usage_hf_iclass_readblock(void) {
-	PrintAndLog("Usage:  hf iclass readblk b <Block> k <Key> c e|r\n");
+
+static void usage_hf_iclass_readblock(void) {
+	PrintAndLog("Usage:  hf iclass readblk b <Block> k <Key> [c] [e|r]\n");
 	PrintAndLog("Options:");
-  PrintAndLog("  b <Block> : The block number as 2 hex symbols");
+	PrintAndLog("  b <Block> : The block number as 2 hex symbols");
 	PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory");
-  PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n");
-  PrintAndLog("  e         : If 'e' is specified, elite computations applied to key");
-  PrintAndLog("  r         : If 'r' is specified, no computations applied to key");
-  PrintAndLog("Samples:");
+	PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n");
+	PrintAndLog("  e         : If 'e' is specified, elite computations applied to key");
+	PrintAndLog("  r         : If 'r' is specified, no computations applied to key");
+	PrintAndLog("Samples:");
 	PrintAndLog("  hf iclass readblk b 06 k 0011223344556677");
 	PrintAndLog("  hf iclass readblk b 1B k 0011223344556677 c");
 	PrintAndLog("  hf iclass readblk b 0A k 0");
-	return 0;
 }
 
-int CmdHFiClass_ReadBlock(const char *Cmd) {
+
+static int CmdHFiClass_ReadBlock(const char *Cmd) {
 	uint8_t blockno=0;
 	uint8_t keyType = 0x88; //debit key
 	uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -1194,71 +1287,78 @@ int CmdHFiClass_ReadBlock(const char *Cmd) {
 	bool errors = false;
 	bool auth = false;
 	uint8_t cmdp = 0;
-	while(param_getchar(Cmd, cmdp) != 0x00)
-	{
-		switch(param_getchar(Cmd, cmdp))
-		{
-		case 'h':
-		case 'H':
-			return usage_hf_iclass_readblock();
-		case 'b':
-		case 'B':
-			if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
-				PrintAndLog("Block No must include 2 HEX symbols\n");
-				errors = true;
-			}
-			cmdp += 2;
-			break;
-		case 'c':
-		case 'C':
-			keyType = 0x18;
-			cmdp++;
-			break;
-		case 'e':
-		case 'E':
-			elite = true;
-			cmdp++;
-			break;
-		case 'k':
-		case 'K':
-			auth = true;
-			dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
-			if (dataLen == 16) { 
-				errors = param_gethex(tempStr, 0, KEY, dataLen);
-			} else if (dataLen == 1) {
-				keyNbr = param_get8(Cmd, cmdp+1);
-				if (keyNbr < ICLASS_KEYS_MAX) {
-					memcpy(KEY, iClass_Key_Table[keyNbr], 8);
+	while (param_getchar(Cmd, cmdp) != 0x00) {
+		switch (param_getchar(Cmd, cmdp)) {
+			case 'h':
+			case 'H':
+				usage_hf_iclass_readblock();
+				return 0;
+			case 'b':
+			case 'B':
+				if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
+					PrintAndLog("Block No must include 2 HEX symbols\n");
+					errors = true;
+				}
+				cmdp += 2;
+				break;
+			case 'c':
+			case 'C':
+				keyType = 0x18;
+				cmdp++;
+				break;
+			case 'e':
+			case 'E':
+				elite = true;
+				cmdp++;
+				break;
+			case 'k':
+			case 'K':
+				auth = true;
+				dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
+				if (dataLen == 16) {
+					errors = param_gethex(tempStr, 0, KEY, dataLen);
+				} else if (dataLen == 1) {
+					keyNbr = param_get8(Cmd, cmdp+1);
+					if (keyNbr < ICLASS_KEYS_MAX) {
+						memcpy(KEY, iClass_Key_Table[keyNbr], 8);
+					} else {
+						PrintAndLog("\nERROR: KeyNbr is invalid\n");
+						errors = true;
+					}
 				} else {
-					PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
+					PrintAndLog("\nERROR: Key is incorrect length\n");
 					errors = true;
 				}
-			} else {
-				PrintAndLog("\nERROR: Credit Key is incorrect length\n");
+				cmdp += 2;
+				break;
+			case 'r':
+			case 'R':
+				rawkey = true;
+				cmdp++;
+				break;
+			default:
+				PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
 				errors = true;
-			}
-			cmdp += 2;
-			break;
-		case 'r':
-		case 'R':
-			rawkey = true;
-			cmdp++;
-			break;
-		default:
-			PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
-			errors = true;
-			break;
+				break;
+		}
+		if (errors) {
+			usage_hf_iclass_readblock();
+			return 0;
 		}
-		if(errors) return usage_hf_iclass_readblock();
 	}
 
-	if (cmdp < 2) return usage_hf_iclass_readblock();
+	if (cmdp < 2) {
+		usage_hf_iclass_readblock();
+		return 0;
+	}
 	if (!auth)
 		PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
+
 	return ReadBlock(KEY, blockno, keyType, elite, rawkey, true, auth);
 }
 
-int CmdHFiClass_loclass(const char *Cmd) {
+
+static int CmdHFiClass_loclass(const char *Cmd) {
 	char opt = param_getchar(Cmd, 0);
 
 	if (strlen(Cmd)<1 || opt == 'h') {
@@ -1297,49 +1397,22 @@ int CmdHFiClass_loclass(const char *Cmd) {
 	return 0;
 }
 
-void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
-	uint8_t mem_config;
-	memcpy(&mem_config, iclass_dump + 13,1);
-	uint8_t maxmemcount;
-	uint8_t filemaxblock = filesize / 8;
-	if (mem_config & 0x80)
-		maxmemcount = 255;
-	else
-		maxmemcount = 31;
-	//PrintAndLog	("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
 
-	if (startblock == 0)
-		startblock = 6;
-	if ((endblock > maxmemcount) || (endblock == 0))
-		endblock = maxmemcount;
-
-	// remember endblock need to relate to zero-index arrays.
-	if (endblock > filemaxblock-1)
-		endblock = filemaxblock;
-	
-	int i = startblock;
-	printf("------+--+-------------------------+\n");
-	while (i <= endblock) {
-		uint8_t *blk = iclass_dump + (i * 8);
-		printf("Block |%02X| %s|\n", i, sprint_hex(blk, 8) );	
-		i++;
-	}
-	printf("------+--+-------------------------+\n");
-}
-
-int usage_hf_iclass_readtagfile() {
+static void usage_hf_iclass_readtagfile() {
 	PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
-	return 1;
 }
 
-int CmdHFiClassReadTagFile(const char *Cmd) {
+
+static int CmdHFiClassReadTagFile(const char *Cmd) {
 	int startblock = 0;
 	int endblock = 0;
 	char tempnum[5];
 	FILE *f;
 	char filename[FILE_PATH_SIZE];
-	if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1)
-		return usage_hf_iclass_readtagfile();
+	if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1) {
+		usage_hf_iclass_readtagfile();
+		return 0;
+	}
 	if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1)
 		startblock = 0;
 	else
@@ -1397,24 +1470,7 @@ uint64_t hexarray_to_uint64(uint8_t *key) {
 	return uint_key;
 }
 */
-void HFiClassCalcDivKey(uint8_t	*CSN, uint8_t	*KEY, uint8_t *div_key, bool elite){
-	uint8_t keytable[128] = {0};
-	uint8_t key_index[8] = {0};
-	if (elite) {
-		uint8_t key_sel[8] = { 0 };
-		uint8_t key_sel_p[8] = { 0 };
-		hash2(KEY, keytable);
-		hash1(CSN, key_index);
-		for(uint8_t i = 0; i < 8 ; i++)
-			key_sel[i] = keytable[key_index[i]] & 0xFF;
 
-		//Permute from iclass format to standard format
-		permutekey_rev(key_sel, key_sel_p);
-		diversifyKey(CSN, key_sel_p, div_key);	
-	} else {
-		diversifyKey(CSN, KEY, div_key);
-	}		
-}
 
 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
 //calculate and return xor_div_key (ready for a key write command)
@@ -1426,18 +1482,19 @@ static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, u
 	HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite);
 	//get new div key
 	HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite);
-	
+
 	for (uint8_t i = 0; i < sizeof(old_div_key); i++){
 		xor_div_key[i] = old_div_key[i] ^ new_div_key[i];
 	}
 	if (verbose) {
 		printf("Old Div Key : %s\n",sprint_hex(old_div_key,8));
 		printf("New Div Key : %s\n",sprint_hex(new_div_key,8));
-		printf("Xor Div Key : %s\n",sprint_hex(xor_div_key,8));		
+		printf("Xor Div Key : %s\n",sprint_hex(xor_div_key,8));
 	}
 }
 
-int usage_hf_iclass_calc_newkey(void) {
+
+static void usage_hf_iclass_calc_newkey(void) {
 	PrintAndLog("HELP :  Manage iClass Keys in client memory:\n");
 	PrintAndLog("Usage:  hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
 	PrintAndLog("  Options:");
@@ -1451,16 +1508,14 @@ int usage_hf_iclass_calc_newkey(void) {
 	PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
 	PrintAndLog(" std to std read csn      : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
 	PrintAndLog("NOTE: * = required\n");
-
-	return 1;
 }
 
-int CmdHFiClassCalcNewKey(const char *Cmd) {
+
+static int CmdHFiClassCalcNewKey(const char *Cmd) {
 	uint8_t OLDKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 	uint8_t NEWKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 	uint8_t xor_div_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 keyNbr = 0;
 	uint8_t dataLen = 0;
 	char tempStr[50] = {0};
@@ -1475,7 +1530,8 @@ int CmdHFiClassCalcNewKey(const char *Cmd) {
 		{
 		case 'h':
 		case 'H':
-			return usage_hf_iclass_calc_newkey();
+			usage_hf_iclass_calc_newkey();
+			return 0;
 		case 'e':
 		case 'E':
 			dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr));
@@ -1487,7 +1543,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) {
 		case 'n':
 		case 'N':
 			dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
-			if (dataLen == 16) { 
+			if (dataLen == 16) {
 				errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
 			} else if (dataLen == 1) {
 				keyNbr = param_get8(Cmd, cmdp+1);
@@ -1506,7 +1562,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) {
 		case 'o':
 		case 'O':
 			dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
-			if (dataLen == 16) { 
+			if (dataLen == 16) {
 				errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
 			} else if (dataLen == 1) {
 				keyNbr = param_get8(Cmd, cmdp+1);
@@ -1525,8 +1581,10 @@ int CmdHFiClassCalcNewKey(const char *Cmd) {
 		case 's':
 		case 'S':
 			givenCSN = true;
-			if (param_gethex(Cmd, cmdp+1, CSN, 16))
-				return usage_hf_iclass_calc_newkey();
+			if (param_gethex(Cmd, cmdp+1, CSN, 16)) {
+				usage_hf_iclass_calc_newkey();
+				return 0;
+			}
 			cmdp += 2;
 			break;
 		default:
@@ -1534,19 +1592,26 @@ int CmdHFiClassCalcNewKey(const char *Cmd) {
 			errors = true;
 			break;
 		}
-		if(errors) return usage_hf_iclass_calc_newkey();
+		if (errors) {
+			usage_hf_iclass_calc_newkey();
+			return 0;
+		}
 	}
 
-	if (cmdp < 4) return usage_hf_iclass_calc_newkey();
+	if (cmdp < 4) {
+		usage_hf_iclass_calc_newkey();
+		return 0;
+	}
 
 	if (!givenCSN)
-		if (!select_only(CSN, CCNR, false, true))
+		if (!select_only(CSN, true))
 			return 0;
-	
+
 	HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true);
 	return 0;
 }
 
+
 static int loadKeys(char *filename) {
 	FILE *f;
 	f = fopen(filename,"rb");
@@ -1582,6 +1647,7 @@ static int loadKeys(char *filename) {
 	return 1;
 }
 
+
 static int saveKeys(char *filename) {
 	FILE *f;
 	f = fopen(filename,"wb");
@@ -1599,16 +1665,18 @@ static int saveKeys(char *filename) {
 	return 0;
 }
 
+
 static int printKeys(void) {
 	PrintAndLog("");
 	for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
 		PrintAndLog("%u: %s",i,sprint_hex(iClass_Key_Table[i],8));
 	}
-	PrintAndLog("");	
+	PrintAndLog("");
 	return 0;
 }
 
-int usage_hf_iclass_managekeys(void) {
+
+static void usage_hf_iclass_managekeys(void) {
 	PrintAndLog("HELP :  Manage iClass Keys in client memory:\n");
 	PrintAndLog("Usage:  hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
 	PrintAndLog("  Options:");
@@ -1623,10 +1691,10 @@ int usage_hf_iclass_managekeys(void) {
 	PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
 	PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
 	PrintAndLog(" print keys   : hf iclass managekeys p\n");
-	return 0;
 }
 
-int CmdHFiClassManageKeys(const char *Cmd) {
+
+static int CmdHFiClassManageKeys(const char *Cmd) {
 	uint8_t keyNbr = 0;
 	uint8_t dataLen = 0;
 	uint8_t KEY[8] = {0};
@@ -1643,10 +1711,11 @@ int CmdHFiClassManageKeys(const char *Cmd) {
 		{
 		case 'h':
 		case 'H':
-			return usage_hf_iclass_managekeys();
+			usage_hf_iclass_managekeys();
+			return 0;
 		case 'f':
 		case 'F':
-			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); 
+			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
 			if (fileNameLen < 1) {
 				PrintAndLog("No filename found after f");
 				errors = true;
@@ -1664,7 +1733,7 @@ int CmdHFiClassManageKeys(const char *Cmd) {
 			break;
 		case 'k':
 		case 'K':
-			operation += 3; //set key 
+			operation += 3; //set key
 			dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
 			if (dataLen == 16) { //ul-c or ev1/ntag key length
 				errors = param_gethex(tempStr, 0, KEY, dataLen);
@@ -1694,19 +1763,25 @@ int CmdHFiClassManageKeys(const char *Cmd) {
 			errors = true;
 			break;
 		}
-		if(errors) return usage_hf_iclass_managekeys();
+		if (errors) {
+			usage_hf_iclass_managekeys();
+			return 0;
+		}
 	}
 	if (operation == 0){
 		PrintAndLog("no operation specified (load, save, or print)\n");
-		return usage_hf_iclass_managekeys();
+		usage_hf_iclass_managekeys();
+		return 0;
 	}
 	if (operation > 6){
 		PrintAndLog("Too many operations specified\n");
-		return usage_hf_iclass_managekeys();
+		usage_hf_iclass_managekeys();
+		return 0;
 	}
 	if (operation > 4 && fileNameLen == 0){
 		PrintAndLog("You must enter a filename when loading or saving\n");
-		return usage_hf_iclass_managekeys();
+		usage_hf_iclass_managekeys();
+		return 0;
 	}
 
 	switch (operation){
@@ -1719,7 +1794,8 @@ int CmdHFiClassManageKeys(const char *Cmd) {
 	return 0;
 }
 
-int CmdHFiClassCheckKeys(const char *Cmd) {
+
+static int CmdHFiClassCheckKeys(const char *Cmd) {
 
 	uint8_t mac[4] = {0x00,0x00,0x00,0x00};
 	uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -1727,9 +1803,9 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
 
 	// elite key,  raw key, standard key
 	bool use_elite = false;
-	bool use_raw = false;	
+	bool use_raw = false;
 	bool found_debit = false;
-	bool found_credit = false;	
+	bool found_credit = false;
 	bool errors = false;
 	uint8_t cmdp = 0x00;
 	FILE * f;
@@ -1743,10 +1819,11 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
 		switch (param_getchar(Cmd, cmdp)) {
 		case 'h':
 		case 'H':
-			return usage_hf_iclass_chk();
+			usage_hf_iclass_chk();
+			return 0;
 		case 'f':
 		case 'F':
-			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); 
+			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
 			if (fileNameLen < 1) {
 				PrintAndLog("No filename found after f");
 				errors = true;
@@ -1769,8 +1846,11 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
 			break;
 		}
 	}
-	if (errors) return usage_hf_iclass_chk();	
-			
+	if (errors) {
+		usage_hf_iclass_chk();
+		return 0;
+	}
+
 	if ( !(f = fopen( filename , "r")) ) {
 		PrintAndLog("File: %s: not found or locked.", filename);
 		return 1;
@@ -1779,16 +1859,16 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
 	while( fgets(buf, sizeof(buf), f) ){
 		if (strlen(buf) < 16 || buf[15] == '\n')
 			continue;
-	
+
 		while (fgetc(f) != '\n' && !feof(f)) ;  //goto next line
-		
-		if( buf[0]=='#' ) continue;	//The line start with # is comment, skip
+
+		if( buf[0]=='#' ) continue; //The line start with # is comment, skip
 
 		if (!isxdigit(buf[0])){
 			PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf);
 			continue;
 		}
-		
+
 		buf[16] = 0;
 
 		p = realloc(keyBlock, 8 * (keyitems += 64));
@@ -1809,19 +1889,19 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
 	}
 	fclose(f);
 	PrintAndLog("Loaded %2d keys from %s", keycnt, filename);
-	
+
 	// time
 	uint64_t t1 = msclock();
-				
+
 	for (uint32_t c = 0; c < keycnt; c += 1) {
-			printf("."); fflush(stdout);			
+			printf("."); fflush(stdout);
 			if (ukbhit()) {
 				int gc = getchar(); (void)gc;
 				printf("\naborted via keyboard!\n");
 				break;
 			}
-			
-			memcpy(key, keyBlock + 8 * c , 8); 
+
+			memcpy(key, keyBlock + 8 * c , 8);
 
 			// debit key. try twice
 			for (int foo = 0; foo < 2 && !found_debit; foo++) {
@@ -1833,18 +1913,18 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
 			PrintAndLog("   Found AA1 debit key\t\t[%s]", sprint_hex(key, 8));
 				found_debit = true;
 			}
-			
+
 			// credit key. try twice
 			for (int foo = 0; foo < 2 && !found_credit; foo++) {
 				if (!select_and_auth(key, mac, div_key, true, use_elite, use_raw, false))
 					continue;
-				
+
 				// key found
 				PrintAndLog("\n--------------------------------------------------------");
 				PrintAndLog("   Found AA2 credit key\t\t[%s]", sprint_hex(key, 8));
 				found_credit = true;
 			}
-			
+
 			// both keys found.
 			if ( found_debit && found_credit )
 				break;
@@ -1853,45 +1933,108 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
 	t1 = msclock() - t1;
 
 	PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1/1000.0);
-	
+
 	DropField();
 	free(keyBlock);
 	PrintAndLog("");
 	return 0;
 }
 
-static command_t CommandTable[] = 
-{
-	{"help",        CmdHelp,                    	1,	"This help"},
-	{"calcnewkey",  CmdHFiClassCalcNewKey,      	1,	"[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
-	{"chk",         CmdHFiClassCheckKeys,        	0,	"            Check keys"},	
-	{"clone",       CmdHFiClassCloneTag,        	0,	"[options..] Authenticate and Clone from iClass bin file"},
-	{"decrypt",     CmdHFiClassDecrypt,         	1,	"[f <fname>] Decrypt tagdump" },
-	{"dump",        CmdHFiClassReader_Dump,     	0,	"[options..] Authenticate and Dump iClass tag's AA1"},
-	{"eload",       CmdHFiClassELoad,           	0,	"[f <fname>] (experimental) Load data into iClass emulator memory"},
-	{"encryptblk",  CmdHFiClassEncryptBlk,      	1,	"<BlockData> Encrypt given block data"},
-	{"list",        CmdHFiClassList,            	0,	"            (Deprecated) List iClass history"},
-	{"loclass",     CmdHFiClass_loclass,        	1,	"[options..] Use loclass to perform bruteforce of reader attack dump"},
-	{"managekeys",  CmdHFiClassManageKeys,      	1,	"[options..] Manage the keys to use with iClass"},
-	{"readblk",     CmdHFiClass_ReadBlock,      	0,	"[options..] Authenticate and Read iClass block"},
-	{"reader",      CmdHFiClassReader,          	0,	"            Look for iClass tags until a key or the pm3 button is pressed"},
-	{"readtagfile", CmdHFiClassReadTagFile,     	1,	"[options..] Display Content from tagfile"},
-	{"replay",      CmdHFiClassReader_Replay,   	0,	"<mac>       Read an iClass tag via Reply Attack"},
-	{"sim",         CmdHFiClassSim,             	0,	"[options..] Simulate iClass tag"},
-	{"snoop",       CmdHFiClassSnoop,           	0,	"            Eavesdrop iClass communication"},
-	{"writeblk",    CmdHFiClass_WriteBlock,     	0,	"[options..] Authenticate and Write iClass block"},
+
+static void usage_hf_iclass_permutekey(void) {
+	PrintAndLogEx(NORMAL, "Convert keys from standard NIST to iClass format (and vice versa)");
+	PrintAndLogEx(NORMAL, "");
+	PrintAndLogEx(NORMAL, "Usage:  hf iclass permute [h] [r] <key>");
+	PrintAndLogEx(NORMAL, "Options:");
+	PrintAndLogEx(NORMAL, "           h          This help");
+	PrintAndLogEx(NORMAL, "           r          reverse convert key from iClass to NIST format");
+	PrintAndLogEx(NORMAL, "");
+	PrintAndLogEx(NORMAL, "Examples:");
+	PrintAndLogEx(NORMAL, "      hf iclass permute r 0123456789abcdef");
+}
+
+
+static int CmdHFiClassPermuteKey(const char *Cmd) {
+
+	uint8_t key[8] = {0};
+	uint8_t data[16] = {0};
+	bool isReverse = false;
+	int len = sizeof(data);
+	char cmdp = tolower(param_getchar(Cmd, 0));
+	if (strlen(Cmd) == 0 || cmdp == 'h') {
+		usage_hf_iclass_permutekey();
+		return 0;
+	}
+
+	if (cmdp == 'r') {
+		isReverse = true;
+		param_gethex_ex(Cmd, 1, data, &len);
+	} else if (cmdp == 'f') {
+		param_gethex_ex(Cmd, 1, data, &len);
+	} else {
+		param_gethex_ex(Cmd, 0, data, &len);
+	}
+
+
+	if (len % 2) {
+		usage_hf_iclass_permutekey();
+		return 0;
+	}
+
+	len >>= 1;
+
+	memcpy(key, data, 8);
+
+	if (isReverse) {
+		// generate_rev(data, len);
+		uint8_t key_std_format[8] = {0};
+		permutekey_rev(key, key_std_format);
+		PrintAndLogEx(SUCCESS, "key in standard NIST format:     %s \n", sprint_hex(key_std_format, 8));
+		// if (mbedtls_des_key_check_key_parity(key_std_format
+	} else {
+		// generate(data, len);
+		uint8_t key_iclass_format[8] = {0};
+		permutekey(key, key_iclass_format);
+		PrintAndLogEx(SUCCESS, "key in iClass (permuted) format: %s \n", sprint_hex(key_iclass_format, 8));
+	}
+	return 0;
+}
+
+
+static int CmdHelp(const char *Cmd);
+
+static command_t CommandTable[] = {
+	{"help",        CmdHelp,                        1,  "This help"},
+	{"calcnewkey",  CmdHFiClassCalcNewKey,          1,  "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
+	{"chk",         CmdHFiClassCheckKeys,           0,  "            Check keys"},
+	{"clone",       CmdHFiClassCloneTag,            0,  "[options..] Authenticate and Clone from iClass bin file"},
+	{"decrypt",     CmdHFiClassDecrypt,             1,  "[f <fname>] Decrypt tagdump" },
+	{"dump",        CmdHFiClassReader_Dump,         0,  "[options..] Authenticate and Dump iClass tag's AA1"},
+	{"eload",       CmdHFiClassELoad,               0,  "[f <fname>] (experimental) Load data into iClass emulator memory"},
+	{"encryptblk",  CmdHFiClassEncryptBlk,          1,  "<BlockData> Encrypt given block data"},
+	{"list",        CmdHFiClassList,                0,  "            (Deprecated) List iClass history"},
+	{"loclass",     CmdHFiClass_loclass,            1,  "[options..] Use loclass to perform bruteforce of reader attack dump"},
+	{"managekeys",  CmdHFiClassManageKeys,          1,  "[options..] Manage the keys to use with iClass"},
+	{"permutekey",  CmdHFiClassPermuteKey,          1,  "            iClass key permutation"},
+	{"readblk",     CmdHFiClass_ReadBlock,          0,  "[options..] Authenticate and Read iClass block"},
+	{"reader",      CmdHFiClassReader,              0,  "            Look for iClass tags until a key or the pm3 button is pressed"},
+	{"readtagfile", CmdHFiClassReadTagFile,         1,  "[options..] Display Content from tagfile"},
+	{"replay",      CmdHFiClassReader_Replay,       0,  "<mac>       Read an iClass tag via Reply Attack"},
+	{"sim",         CmdHFiClassSim,                 0,  "[options..] Simulate iClass tag"},
+	{"snoop",       CmdHFiClassSnoop,               0,  "            Eavesdrop iClass communication"},
+	{"writeblk",    CmdHFiClass_WriteBlock,         0,  "[options..] Authenticate and Write iClass block"},
 	{NULL, NULL, 0, NULL}
 };
 
-int CmdHFiClass(const char *Cmd)
-{
-	clearCommandBuffer();	
+
+int CmdHFiClass(const char *Cmd) {
+	clearCommandBuffer();
 	CmdsParse(CommandTable, Cmd);
 	return 0;
 }
 
-int CmdHelp(const char *Cmd)
-{
+
+int CmdHelp(const char *Cmd) {
 	CmdsHelp(CommandTable);
 	return 0;
 }
diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h
index 456bb1c3..09103b33 100644
--- a/client/cmdhficlass.h
+++ b/client/cmdhficlass.h
@@ -13,28 +13,6 @@
 #define CMDHFICLASS_H__
 
 int CmdHFiClass(const char *Cmd);
-
-int CmdHFiClassCalcNewKey(const char *Cmd);
-int CmdHFiClassCloneTag(const char *Cmd);
-int CmdHFiClassDecrypt(const char *Cmd);
-int CmdHFiClassEncryptBlk(const char *Cmd);
-int CmdHFiClassELoad(const char *Cmd);
-int CmdHFiClassList(const char *Cmd);
 int HFiClassReader(const char *Cmd, bool loop, bool verbose);
-int CmdHFiClassReader(const char *Cmd);
-int CmdHFiClassReader_Dump(const char *Cmd);
-int CmdHFiClassReader_Replay(const char *Cmd);
-int CmdHFiClassReadKeyFile(const char *filename);
-int CmdHFiClassReadTagFile(const char *Cmd);
-int CmdHFiClass_ReadBlock(const char *Cmd);
-int CmdHFiClass_TestMac(const char *Cmd);
-int CmdHFiClassManageKeys(const char *Cmd);
-int CmdHFiClass_loclass(const char *Cmd);
-int CmdHFiClassSnoop(const char *Cmd);
-int CmdHFiClassSim(const char *Cmd);
-int CmdHFiClassWriteKeyFile(const char *Cmd);
-int CmdHFiClass_WriteBlock(const char *Cmd);
-int CmdHFiClassCheckKeys(const char *Cmd);
-void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize);
-void HFiClassCalcDivKey(uint8_t	*CSN, uint8_t	*KEY, uint8_t *div_key, bool elite);
+
 #endif
diff --git a/client/loclass/elite_crack.h b/client/loclass/elite_crack.h
index 46791fb5..c44f5105 100644
--- a/client/loclass/elite_crack.h
+++ b/client/loclass/elite_crack.h
@@ -85,7 +85,7 @@ typedef struct {
 	uint8_t cc_nr[12];
 	uint8_t mac[4];
 
-}dumpdata;
+} dumpdata;
 
 /**
  * @brief Performs brute force attack against a dump-data item, containing csn, cc_nr and mac.
diff --git a/include/usb_cmd.h b/include/usb_cmd.h
index 0802d2f1..75b7c210 100644
--- a/include/usb_cmd.h
+++ b/include/usb_cmd.h
@@ -165,7 +165,8 @@ typedef struct{
 #define CMD_ICLASS_READBLOCK                                              0x0396
 #define CMD_ICLASS_WRITEBLOCK                                             0x0397
 #define CMD_ICLASS_EML_MEMSET                                             0x0398
-#define CMD_ICLASS_AUTHENTICATION                                         0x0399
+#define CMD_ICLASS_CHECK                                                  0x0399
+#define CMD_ICLASS_READCHECK                                              0x039A                                         
 
 // For measurements of the antenna tuning
 #define CMD_MEASURE_ANTENNA_TUNING                                        0x0400
@@ -236,13 +237,11 @@ typedef struct{
 
 
 // iCLASS reader flags
-#define FLAG_ICLASS_READER_ONLY_ONCE    0x01
 #define FLAG_ICLASS_READER_CC           0x02
 #define FLAG_ICLASS_READER_CSN          0x04
 #define FLAG_ICLASS_READER_CONF         0x08
 #define FLAG_ICLASS_READER_AA           0x10
-#define FLAG_ICLASS_READER_ONE_TRY      0x20
-#define FLAG_ICLASS_READER_CEDITKEY     0x40
+#define FLAG_ICLASS_READER_CREDITKEY    0x40
 
 // iCLASS simulation modes
 #define ICLASS_SIM_MODE_CSN                   0