X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/8556b852ed769280d1b63054ab1bd08fa19b746a..05151b6fe876c8c5630f9c5160f79353c91ac49b:/armsrc/iso14443a.c

diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c
index 74e269da..6c219f30 100644
--- a/armsrc/iso14443a.c
+++ b/armsrc/iso14443a.c
@@ -787,7 +787,6 @@ done:
 static void CodeIso14443aAsTagPar(const uint8_t *cmd, int len, uint32_t dwParity)
 {
 	int i;
-//	int oddparity;
 
 	ToSendReset();
 
@@ -809,9 +808,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, int len, uint32_t dwParity
 		uint8_t b = cmd[i];
 
 		// Data bits
-//		oddparity = 0x01;
 		for(j = 0; j < 8; j++) {
-//			oddparity ^= (b & 1);
 			if(b & 1) {
 				ToSend[++ToSendMax] = SEC_D;
 			} else {
@@ -820,38 +817,19 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, int len, uint32_t dwParity
 			b >>= 1;
 		}
 
-	// Get the parity bit
+		// Get the parity bit
 		if ((dwParity >> i) & 0x01) {
 			ToSend[++ToSendMax] = SEC_D;
 		} else {
 			ToSend[++ToSendMax] = SEC_E;
 		}
-		
-			// Parity bit
-//			if(oddparity) {
-//				ToSend[++ToSendMax] = SEC_D;
-//			} else {
-//				ToSend[++ToSendMax] = SEC_E;
-//			}
-
-//		if (oddparity != ((dwParity >> i) & 0x01))
-//		  Dbprintf("par error. i=%d", i);
 	}
 
 	// Send stopbit
 	ToSend[++ToSendMax] = SEC_F;
 
-	// Flush the buffer in FPGA!!
-	for(i = 0; i < 5; i++) {
-//		ToSend[++ToSendMax] = SEC_F;
-	}
-
 	// Convert from last byte pos to length
 	ToSendMax++;
-
-    // Add a few more for slop
-//    ToSend[ToSendMax++] = 0x00;
-//	ToSend[ToSendMax++] = 0x00;
 }
 
 static void CodeIso14443aAsTag(const uint8_t *cmd, int len){
@@ -2008,7 +1986,7 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	int vHf = 0;	// in mV
 	int nextCycleTimeout = 0;
 	int res;
-	uint32_t timer = 0;
+//	uint32_t timer = 0;
 	uint32_t selTimer = 0;
 	uint32_t authTimer = 0;
 	uint32_t par = 0;
@@ -2016,13 +1994,17 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	uint8_t cardWRBL = 0;
 	uint8_t cardAUTHSC = 0;
 	uint8_t cardAUTHKEY = 0xff;  // no authentication
+	uint32_t cardRn = 0;
+	uint32_t cardRr = 0;
 	uint32_t cuid = 0;
+	uint32_t rn_enc = 0;
+	uint32_t ans = 0;
+	uint32_t cardINTREG = 0;
+	uint8_t cardINTBLOCK = 0;
 	struct Crypto1State mpcs = {0, 0};
 	struct Crypto1State *pcs;
 	pcs = &mpcs;
 	
-	uint64_t key64 = 0xffffffffffffULL;
-	
 	uint8_t* receivedCmd = eml_get_bigbufptr_recbuf();
 	uint8_t *response = eml_get_bigbufptr_sendbuf();
 	
@@ -2034,12 +2016,16 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	static uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
 	static uint8_t rSAK1[] = {0x04, 0xda, 0x17};
 
-	static uint8_t rAUTH_NT[] = {0x1a, 0xac, 0xff, 0x4f};
+	static uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
+//	static uint8_t rAUTH_NT[] = {0x1a, 0xac, 0xff, 0x4f};
 	static uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
-	
+
 	// clear trace
 	traceLen = 0;
 	tracing = true;
+
+  // Authenticate response - nonce
+	uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
 	
 	// get UID from emul memory
 	emlGetMemBt(receivedCmd, 7, 1);
@@ -2061,30 +2047,6 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 
 // --------------------------------------	test area
 
-   // Authenticate response - nonce
-    uint8_t *resp1 = (((uint8_t *)BigBuf) + EML_RESPONSES);
-    int resp1Len;
-//    uint8_t *resp2 = (((uint8_t *)BigBuf) + EML_RESPONSES + 200);
-//    int resp2Len;
-	CodeIso14443aAsTag(rAUTH_NT, sizeof(rAUTH_NT));
-    memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
-		
-	timer = GetTickCount();
-	uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
-	uint32_t rn_enc = 0x98d76b77; // !!!!!!!!!!!!!!!!!
-	uint32_t ans = 0;
-	cuid = bytes_to_num(rUIDBCC1, 4);
-/*	
-	crypto1_create(pcs, key64);
-  crypto1_word(pcs, cuid ^ nonce, 0);
-  crypto1_word(pcs, rn_enc , 1);
-  crypto1_word(pcs, 0, 0);
-  ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
-	num_to_bytes(ans, 4, rAUTH_AT);
-	CodeIso14443aAsTag(rAUTH_AT, sizeof(rAUTH_AT));
-  memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;
-	Dbprintf("crypto auth time: %d", GetTickCount() - timer);
-*/
 // --------------------------------------	END test area
 	// start mkseconds counter
 	StartCountUS();
@@ -2096,7 +2058,7 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
   FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
 	SpinDelay(200);
 
-	Dbprintf("--> start. 7buid=%d", _7BUID);
+	if (MF_DBGLEVEL >= 1)	Dbprintf("Started. 7buid=%d", _7BUID);
 	// calibrate mkseconds counter
 	GetDeltaCountUS();
 	while (true) {
@@ -2112,7 +2074,7 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 		if (cardSTATE == MFEMUL_NOFIELD) {
 			vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
 			if (vHf > MF_MINFIELDV) {
-				cardSTATE = MFEMUL_IDLE;
+				cardSTATE_TO_IDLE();
 				LED_A_ON();
 			}
 		} 
@@ -2160,6 +2122,7 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 				// select all
 				if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
 					EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
+					break;
 				}
 
 				// select card
@@ -2173,17 +2136,20 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 					cuid = bytes_to_num(rUIDBCC1, 4);
 					if (!_7BUID) {
 						cardSTATE = MFEMUL_WORK;
+						LED_B_ON();
+						if (MF_DBGLEVEL >= 4)	Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
+						break;
 					} else {
 						cardSTATE = MFEMUL_SELECT2;
 						break;
 					}
-					LED_B_ON();
-					Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
 				}
 				
 				break;
 			}
 			case MFEMUL_SELECT2:{
+				if (!len) break;
+			
 				if (len == 2 && (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x20)) {
 					EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
 					break;
@@ -2197,65 +2163,92 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 					cuid = bytes_to_num(rUIDBCC2, 4);
 					cardSTATE = MFEMUL_WORK;
 					LED_B_ON();
-					Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
+					if (MF_DBGLEVEL >= 4)	Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
 					break;
 				}
-				// TODO: goto work state - i guess there is a command
-				break;
+				
+				// i guess there is a command). go into the work state.
+				if (len != 4) break;
+				cardSTATE = MFEMUL_WORK;
+				goto lbWORK;
 			}
 			case MFEMUL_AUTH1:{
 				if (len == 8) {
-// ---------------------------------
-	rn_enc = bytes_to_num(receivedCmd, 4);
-	crypto1_create(pcs, key64);
-  crypto1_word(pcs, cuid ^ nonce, 0);
-  crypto1_word(pcs, rn_enc , 1);
-  crypto1_word(pcs, 0, 0);
-  ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
-	num_to_bytes(ans, 4, rAUTH_AT);
-// ---------------------------------
-				EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+					// --- crypto
+					rn_enc = bytes_to_num(receivedCmd, 4);
+					cardRn = rn_enc ^ crypto1_word(pcs, rn_enc , 1);
+					cardRr = bytes_to_num(&receivedCmd[4], 4) ^ crypto1_word(pcs, 0, 0);
+					// test if auth OK
+					if (cardRr != prng_successor(nonce, 64)){
+						if (MF_DBGLEVEL >= 4)	Dbprintf("AUTH FAILED. cardRr=%08x, succ=%08x", cardRr, prng_successor(nonce, 64));
+						cardSTATE_TO_IDLE();
+						break;
+					}
+					ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
+					num_to_bytes(ans, 4, rAUTH_AT);
+					// --- crypto
+					EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
 					cardSTATE = MFEMUL_AUTH2;
 				} else {
-					cardSTATE = MFEMUL_IDLE;
-					LED_B_OFF();
-					LED_C_OFF();
+					cardSTATE_TO_IDLE();
 				}
 				if (cardSTATE != MFEMUL_AUTH2) break;
 			}
 			case MFEMUL_AUTH2:{
-				// test auth info here...
-
 				LED_C_ON();
 				cardSTATE = MFEMUL_WORK;
-Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - authTimer);
+				if (MF_DBGLEVEL >= 4)	Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - authTimer);
 				break;
 			}
 			case MFEMUL_WORK:{
-				// auth
-				if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
-authTimer = GetTickCount();
-//					EmSendCmd(rAUTH_NT, sizeof(rAUTH_NT));
-//SpinDelayUs(190);
-					EmSendCmd14443aRaw(resp1, resp1Len, 0);
-LogTrace(NULL, 0, GetDeltaCountUS(), 0, TRUE);
-//					crypto1_create(pcs, key64);
-//					if (cardAUTHKEY == 0xff) { // first auth
-//					crypto1_word(pcs, cuid ^ bytes_to_num(rAUTH_NT, 4), 0); // uid ^ nonce
-//					} else { // nested auth
-//					}
-
-					cardAUTHSC = receivedCmd[1] / 4;  // received block num
-					cardAUTHKEY = receivedCmd[0] - 0x60;
-					cardSTATE = MFEMUL_AUTH1;
-					nextCycleTimeout = 10;
-					break;
-				}
-				
-				if (len == 0) break;
+lbWORK:	if (len == 0) break;
 				
-				// decrypt seqence
-				if (cardAUTHKEY != 0xff) mf_crypto1_decrypt(pcs, receivedCmd, len);
+				if (cardAUTHKEY == 0xff) {
+					// first authentication
+					if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
+						authTimer = GetTickCount();
+
+						cardAUTHSC = receivedCmd[1] / 4;  // received block num
+						cardAUTHKEY = receivedCmd[0] - 0x60;
+
+						// --- crypto
+						crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
+						ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); 
+						num_to_bytes(nonce, 4, rAUTH_AT);
+						EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+						// --- crypto
+						
+//   last working revision 
+//						EmSendCmd14443aRaw(resp1, resp1Len, 0);
+//						LogTrace(NULL, 0, GetDeltaCountUS(), 0, true);
+
+						cardSTATE = MFEMUL_AUTH1;
+						nextCycleTimeout = 10;
+						break;
+					}
+				} else {
+					// decrypt seqence
+					mf_crypto1_decrypt(pcs, receivedCmd, len);
+					
+					// nested authentication
+					if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
+						authTimer = GetTickCount();
+
+						cardAUTHSC = receivedCmd[1] / 4;  // received block num
+						cardAUTHKEY = receivedCmd[0] - 0x60;
+
+						// --- crypto
+						crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
+						ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); 
+						num_to_bytes(ans, 4, rAUTH_AT);
+						EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+						// --- crypto
+
+						cardSTATE = MFEMUL_AUTH1;
+						nextCycleTimeout = 10;
+						break;
+					}
+				}
 				
 				// rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued
 				// BUT... ACK --> NACK
@@ -2272,7 +2265,7 @@ LogTrace(NULL, 0, GetDeltaCountUS(), 0, TRUE);
 				
 				// read block
 				if (len == 4 && receivedCmd[0] == 0x30) {
-					if (receivedCmd[1] >= 16 * 4) {
+					if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
 						EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
 						break;
 					}
@@ -2285,7 +2278,7 @@ LogTrace(NULL, 0, GetDeltaCountUS(), 0, TRUE);
 				
 				// write block
 				if (len == 4 && receivedCmd[0] == 0xA0) {
-					if (receivedCmd[1] >= 16 * 4) {
+					if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
 						EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
 						break;
 					}
@@ -2296,21 +2289,61 @@ LogTrace(NULL, 0, GetDeltaCountUS(), 0, TRUE);
 					break;
 				}
 			
+				// works with cardINTREG
+				
+				// increment, decrement, restore
+				if (len == 4 && (receivedCmd[0] == 0xC0 || receivedCmd[0] == 0xC1 || receivedCmd[0] == 0xC2)) {
+					if (receivedCmd[1] >= 16 * 4 || 
+							receivedCmd[1] / 4 != cardAUTHSC || 
+							emlCheckValBl(receivedCmd[1])) {
+						EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+						break;
+					}
+					EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
+					if (receivedCmd[0] == 0xC1)
+						cardSTATE = MFEMUL_INTREG_INC;
+					if (receivedCmd[0] == 0xC0)
+						cardSTATE = MFEMUL_INTREG_DEC;
+					if (receivedCmd[0] == 0xC2)
+						cardSTATE = MFEMUL_INTREG_REST;
+					cardWRBL = receivedCmd[1];
+					
+					break;
+				}
+				
+
+				// transfer
+				if (len == 4 && receivedCmd[0] == 0xB0) {
+					if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
+						EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+						break;
+					}
+					
+					if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1]))
+						EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+					else
+						EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
+						
+					break;
+				}
+
 				// halt
 				if (len == 4 && (receivedCmd[0] == 0x50 && receivedCmd[1] == 0x00)) {
-					cardSTATE = MFEMUL_HALTED;
 					LED_B_OFF();
 					LED_C_OFF();
-					Dbprintf("--> HALTED. Selected time: %d ms",  GetTickCount() - selTimer);
+					cardSTATE = MFEMUL_HALTED;
+					if (MF_DBGLEVEL >= 4)	Dbprintf("--> HALTED. Selected time: %d ms",  GetTickCount() - selTimer);
 					break;
 				}
-				break;
-
+				
 				// command not allowed
 				if (len == 4) {
 					EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
 					break;
 				}
+
+				// case break
+				break;
 			}
 			case MFEMUL_WRITEBL2:{
 				if (len == 18){
@@ -2319,8 +2352,46 @@ LogTrace(NULL, 0, GetDeltaCountUS(), 0, TRUE);
 					EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
 					cardSTATE = MFEMUL_WORK;
 					break;
+				} else {
+					cardSTATE_TO_IDLE();
+					break;
 				}
-Dbprintf("err write block: %d len:%d", cardWRBL, len);
+				break;
+			}
+			
+			case MFEMUL_INTREG_INC:{
+				mf_crypto1_decrypt(pcs, receivedCmd, len);
+				memcpy(&ans, receivedCmd, 4);
+				if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
+					EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+					cardSTATE_TO_IDLE();
+					break;
+				}
+				cardINTREG = cardINTREG + ans;
+				cardSTATE = MFEMUL_WORK;
+				break;
+			}
+			case MFEMUL_INTREG_DEC:{
+				mf_crypto1_decrypt(pcs, receivedCmd, len);
+				memcpy(&ans, receivedCmd, 4);
+				if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
+					EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+					cardSTATE_TO_IDLE();
+					break;
+				}
+				cardINTREG = cardINTREG - ans;
+				cardSTATE = MFEMUL_WORK;
+				break;
+			}
+			case MFEMUL_INTREG_REST:{
+				mf_crypto1_decrypt(pcs, receivedCmd, len);
+				memcpy(&ans, receivedCmd, 4);
+				if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
+					EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+					cardSTATE_TO_IDLE();
+					break;
+				}
+				cardSTATE = MFEMUL_WORK;
 				break;
 			}
 		
@@ -2335,5 +2406,5 @@ Dbprintf("err write block: %d len:%d", cardWRBL, len);
 	memset(rAUTH_NT, 0x44, 4);
 	LogTrace(rAUTH_NT, 4, 0, 0, TRUE);
 
-	DbpString("Emulator stopped.");
+	if (MF_DBGLEVEL >= 1)	Dbprintf("Emulator stopped. Tracing: %d  trace length: %d ",	tracing, traceLen);
 }