X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/5b9fb6f454174c97b80b01811a669737496273ce..8ce95353de94f1e7d083775eb0f6b199c4122069:/client/cmdhflegic.c

diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c
index 60c2e858..62c43f04 100644
--- a/client/cmdhflegic.c
+++ b/client/cmdhflegic.c
@@ -149,7 +149,16 @@ int usage_legic_esave(void){
 	PrintAndLog("      hf legic esave 2 myfile");
 	return 0;
 }
-
+int usage_legic_wipe(void){
+	PrintAndLog("Fills a legic tag memory with zeros. From byte7 and to the end.");
+	PrintAndLog(" Usage:  hf legic wipe [h]");
+	PrintAndLog("Options:");
+	PrintAndLog("      h             : this help");
+	PrintAndLog("");
+	PrintAndLog("Samples:");	
+	PrintAndLog("      hf legic wipe");
+	return 0;
+}
 /*
  *  Output BigBuf and deobfuscate LEGIC RF tag data.
  *  This is based on information given in the talk held
@@ -506,8 +515,8 @@ int CmdLegicRdmem(const char *Cmd) {
 		return 1;
 	}
 	
-	PrintAndLog("\n ##  | Data");
-	PrintAndLog("-----+-----");
+	PrintAndLog("\n ##  |  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F");
+	PrintAndLog("-----+------------------------------------------------------------------------------------------------");
 	print_hex_break( data, readlen, 32);
 	free(data);
 	return 0;
@@ -551,11 +560,19 @@ int CmdLegicRfWrite(const char *Cmd) {
 				errors = true;
 				break;
 			}
+			
+			// limit number of bytes to write. This is not a 'restore' command.
+			if ( (len>>1) > 100 ){
+				PrintAndLog("Max bound on 100bytes to write a one time.");
+				PrintAndLog("Use the 'hf legic restore' command if you want to write the whole tag at once");
+				errors = true;
+			}
 
 			// it's possible for user to accidentally enter "b" parameter
 			// more than once - we have to clean previous malloc
 			if (data)
 				free(data);
+			
 			data = malloc(len >> 1);
 			if ( data == NULL ) {
 				PrintAndLog("Can't allocate memory. exiting");
@@ -604,27 +621,41 @@ int CmdLegicRfWrite(const char *Cmd) {
 	legic_print_type(card.cardsize, 0);
 	
 	// OUT-OF-BOUNDS checks
-	// UID 4 bytes can't be written to.
-	if ( offset < 4 ) {
-		PrintAndLog("Out-of-bounds, UID 4bytes can't be written to. Offset = %d", offset);
+	// UID 4+1 bytes can't be written to.
+	if ( offset < 5 ) {
+		PrintAndLog("Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset);
 		return -2;
 	}
 	
-	if ( len + offset + 4 >= card.cardsize ) {
-		PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset + 4);
+	if ( len + offset >= card.cardsize ) {
+		PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset);
 		return -2;
 	}
 
+	if (offset == 5 || offset == 6) {
+		PrintAndLog("############# DANGER ################");
+		PrintAndLog("# changing the DCF is irreversible  #");
+		PrintAndLog("#####################################");
+		char *answer = NULL;
+		answer = readline("do you really want to continue? y(es) n(o) : ");
+		bool overwrite = (answer[0] == 'y' || answer[0] == 'Y');
+		if (!overwrite){
+			PrintAndLog("command cancelled");
+			return 0;
+		}
+	}
+	
 	legic_chk_iv(&IV);
 	
 	PrintAndLog("Writing to tag");
-    UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
-	memcpy(c.d.asBytes, data, len);
-	
-	clearCommandBuffer();
-    SendCommand(&c);
+
+	UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
+	memcpy(c.d.asBytes, data, len);	
 	UsbCommand resp;
-	if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+	clearCommandBuffer();
+	SendCommand(&c);
+	
+	if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
 		PrintAndLog("command execution time out");
 		return 1;
 	}
@@ -633,20 +664,10 @@ int CmdLegicRfWrite(const char *Cmd) {
 		PrintAndLog("failed writing tag");
 		return 1;
 	}
-	
+
     return 0;
 }
 
-/*
-	PrintAndLog("############# DANGER !! #############");
-	PrintAndLog("# changing the DCF is irreversible  #");
-	PrintAndLog("#####################################");
-	PrintAndLog("do youe really want to continue? y(es) n(o)");		
-	// if (scanf(" %c", &answer) > 0 && (answer == 'y' || answer == 'Y')) {
-		// return 0;
-	// }
-*/
-
 int CmdLegicCalcCrc(const char *Cmd){
 
 	uint8_t *data = NULL;
@@ -903,7 +924,8 @@ int CmdLegicDump(const char *Cmd){
 	else
 		sprintf(fnameptr + fileNlen,".bin");
 
-	if ((f = fopen(filename,"wb")) == NULL) { 
+	f = fopen(filename,"wb");
+	if (!f) { 
 		PrintAndLog("Could not create file name %s", filename);
 		if (data)
 			free(data);
@@ -922,7 +944,7 @@ int CmdLegicRestore(const char *Cmd){
 	char filename[FILE_PATH_SIZE] = {0x00};
 	char *fnameptr = filename;
 	size_t fileNlen = 0;
-	bool errors = false;
+	bool errors = true;
 	uint16_t numofbytes;	
 	uint8_t cmdp = 0;
 	
@@ -938,17 +960,20 @@ int CmdLegicRestore(const char *Cmd){
 			case 'I':
 				fileNlen = param_getstr(Cmd, cmdp+1, filename);
 				if (!fileNlen) 
-					errors = true; 
+					errors = true;
+				else 
+					errors = false;
+				
 				if (fileNlen > FILE_PATH_SIZE-5) 
 					fileNlen = FILE_PATH_SIZE-5;
-				cmdp += 2;
+				cmdp += 2;				
 				break;
 			default:
 				PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
 				errors = true;
 				break;
 		}
-		if(errors) break;
+		if (errors) break;
 	}
 
 	//Validations
@@ -966,7 +991,7 @@ int CmdLegicRestore(const char *Cmd){
 	uint8_t *data = malloc(numofbytes);
 	if (!data) {
 		PrintAndLog("Fail, cannot allocate memory");
-		return 3;		
+		return 2;		
 	}
 	memset(data, 0, numofbytes);
 	
@@ -975,34 +1000,66 @@ int CmdLegicRestore(const char *Cmd){
 	// set up file
 	fnameptr += fileNlen;
 	sprintf(fnameptr, ".bin");
-	
-	PrintAndLog("Reading binary file...");
 
-	if ((f = fopen(filename,"rb")) == NULL) {
+	f = fopen(filename,"rb");
+	if (!f) {
 		PrintAndLog("File %s not found or locked", filename);
-		return 2;
+		return 3;
 	}	
 	
-	// verify size of dumpfile is the same as card.
+	// verify size of dumpfile is the same as card.	
+	fseek(f, 0, SEEK_END); // seek to end of file
+	size_t filesize = ftell(f); // get current file pointer
+	fseek(f, 0, SEEK_SET); // seek back to beginning of file
+	
+	if ( filesize != numofbytes) {
+		PrintAndLog("Fail, filesize and cardsize is not equal. [%u != %u]", filesize, numofbytes);
+		free(data);
+		fclose(f);
+		return 4;
+	}
 
 	// load file
 	size_t bytes_read = fread(data, 1, numofbytes, f);
+	fclose(f);
+	
 	if ( bytes_read == 0){
 		PrintAndLog("File reading error");
 		free(data);
-		fclose(f);
 		return 2;
 	}
-	fclose(f);
-
-	PrintAndLog("Restoring %s to card", filename);
-
-	//loop writing :)
+	
+	PrintAndLog("Restoring to card");
 
-	//endloop
+	// transfer to device
+	size_t len = 0;
+	UsbCommand c = {CMD_WRITER_LEGIC_RF, {0, 0, 0x55}};
+	UsbCommand resp;
+	for(size_t i = 7; i < numofbytes; i += USB_CMD_DATA_SIZE) {
+		
+		len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);		
+		c.arg[0] = i; // offset
+		c.arg[1] = len; // number of bytes
+		memcpy(c.d.asBytes, data+i, len); 
+		clearCommandBuffer();
+		SendCommand(&c);
+	
+		if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+			PrintAndLog("command execution time out");
+			free(data);	
+			return 1;
+		}
+		uint8_t isOK = resp.arg[0] & 0xFF;
+		if ( !isOK ) {
+			PrintAndLog("failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
+			free(data);	
+			return 1;
+		}
+		PrintAndLog("Wrote chunk [offset %d | len %d | total %d", i, len, i+len);
+	}	
 	
 	free(data);	
-	PrintAndLog("\nLoaded %d bytes from file: %s  to emulator memory", numofbytes, filename);
+	PrintAndLog("\nWrote %d bytes to card from file %s", numofbytes, filename);
 	return 0;
 }
 
@@ -1041,7 +1098,8 @@ int CmdLegicELoad(const char *Cmd) {
 	sprintf(fnameptr, ".bin");
 	
 	// open file
-	if ((f = fopen(filename,"rb")) == NULL) { 
+	f = fopen(filename,"rb");
+	if (!f) { 
 		PrintAndLog("File %s not found or locked", filename);
 		free(data);
 		return 1;
@@ -1053,9 +1111,11 @@ int CmdLegicELoad(const char *Cmd) {
 		PrintAndLog("File reading error");
 		free(data);
 		fclose(f);
+		f = NULL;		
 		return 2;
 	}
 	fclose(f);
+	f = NULL;
 	
 	// transfer to device
 	legic_seteml(data, 0, numofbytes);
@@ -1115,7 +1175,8 @@ int CmdLegicESave(const char *Cmd) {
 		sprintf(fnameptr + fileNlen,".bin");
 	
 	// open file
-	if ((f = fopen(filename,"wb")) == NULL) { 
+	f = fopen(filename,"wb");
+	if (!f) { 
 		PrintAndLog("Could not create file name %s", filename);
 		free(data);
 		return 1;
@@ -1127,6 +1188,61 @@ int CmdLegicESave(const char *Cmd) {
 	return 0;
 }
 
+int CmdLegicWipe(const char *Cmd){
+
+	char cmdp = param_getchar(Cmd, 0);
+	
+	if ( cmdp == 'h' || cmdp == 'H') return usage_legic_wipe();
+	
+	// tagtype
+	legic_card_select_t card;
+	if (legic_get_type(&card)) {
+		PrintAndLog("Failed to identify tagtype");
+		return 1;
+	}
+	
+	// set up buffer
+	uint8_t *data = malloc(card.cardsize);
+	if (!data) {
+		PrintAndLog("Fail, cannot allocate memory");
+		return 2;		
+	}
+	memset(data, 0, card.cardsize);
+	
+	legic_print_type(card.cardsize, 0);
+
+	printf("Erasing");
+	
+	// transfer to device
+	size_t len = 0;
+	UsbCommand c = {CMD_WRITER_LEGIC_RF, {0, 0, 0x55}};
+	UsbCommand resp;
+	for(size_t i = 7; i < card.cardsize; i += USB_CMD_DATA_SIZE) {
+		
+		printf(".");
+		len = MIN((card.cardsize - i), USB_CMD_DATA_SIZE);		
+		c.arg[0] = i; // offset
+		c.arg[1] = len; // number of bytes
+		memcpy(c.d.asBytes, data+i, len); 
+		clearCommandBuffer();
+		SendCommand(&c);
+	
+		if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+			PrintAndLog("command execution time out");
+			free(data);	
+			return 3;
+		}
+		uint8_t isOK = resp.arg[0] & 0xFF;
+		if ( !isOK ) {
+			PrintAndLog("failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
+			free(data);	
+			return 4;
+		}
+	}
+	printf("ok\n");
+	return 0;
+}
+
 int CmdLegicList(const char *Cmd) {
 	CmdHFList("legic");
 	return 0;
@@ -1145,6 +1261,7 @@ static command_t CommandTable[] =  {
 	{"eload",	CmdLegicELoad,		1, "Load binary dump to emulator memory"},
 	{"esave",	CmdLegicESave,		1, "Save emulator memory to binary file"},
 	{"list",	CmdLegicList,		1, "[Deprecated] List LEGIC history"},
+	{"wipe",	CmdLegicWipe,		1, "Wipe a LEGIC Prime tag"},
 	{NULL, NULL, 0, NULL}
 };