X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/a182a680b0f1f434b6fab67e1eba4a3db3b8a141..04da5cd92bdf5cbdcec127961e2499121003655e:/client/cmdhflegic.c

diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c
index 3a520f6a..0262f81c 100644
--- a/client/cmdhflegic.c
+++ b/client/cmdhflegic.c
@@ -38,9 +38,20 @@ int usage_legic_load(void){
 	return 0;
 }
 
+int usage_legic_read(void){	
+	PrintAndLog("Read data from a legic tag.");
+	PrintAndLog("Usage:  hf legic read <offset> <num of bytes>");
+	PrintAndLog("Options :");
+	PrintAndLog("  <offset>        : offset in data array to start download from");
+	PrintAndLog("  <num of bytes>  : number of bytes to download");
+	PrintAndLog("");
+	PrintAndLog(" sample: hf legic read");
+	return 0;
+}
+
 /*
  *  Output BigBuf and deobfuscate LEGIC RF tag data.
- *   This is based on information given in the talk held
+ *  This is based on information given in the talk held
  *  by Henryk Ploetz and Karsten Nohl at 26c3
  */
 int CmdLegicDecode(const char *Cmd) {
@@ -53,19 +64,22 @@ int CmdLegicDecode(const char *Cmd) {
 	int crc = 0;
 	int wrp = 0;
 	int wrc = 0;
-	uint8_t data_buf[1200]; // receiver buffer,  should be 1024..
+	uint8_t data_buf[1024]; // receiver buffer,  should be 1024..
 	char token_type[4];
 
-	// copy data from proxmark into buffer
-	GetFromBigBuf(data_buf,sizeof(data_buf),0);
-	WaitForResponse(CMD_ACK,NULL);
-
+	// download EML memory, where the "legic read" command puts the data.
+	GetEMLFromBigBuf(data_buf, sizeof(data_buf), 0);
+	if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000)){
+		PrintAndLog("Command execute timeout");
+		return 1;
+	}
+	
 	// Output CDF System area (9 bytes) plus remaining header area (12 bytes)
 	crc = data_buf[4];
 	uint32_t calc_crc =  CRC8Legic(data_buf, 4);	
 	
 	PrintAndLog("\nCDF: System Area");
-
+	PrintAndLog("------------------------------------------------------");
 	PrintAndLog("MCD: %02x, MSN: %02x %02x %02x, MCC: %02x %s",
 		data_buf[0],
 		data_buf[1],
@@ -115,10 +129,27 @@ int CmdLegicDecode(const char *Cmd) {
 	uint32_t segCalcCRC = 0;
 	uint32_t segCRC = 0;
 
+	// see if user area is xored or just zeros.
+	int numOfZeros = 0;
+	for (int index=22; index < 256; ++index){
+		if ( data_buf[index] == 0x00 )
+			++numOfZeros;
+	}
+	// if possible zeros is less then 60%, lets assume data is xored
+	// 256  - 22 (header) = 234
+	// 1024 - 22 (header) = 1002
+	int isXored = (numOfZeros*100/stamp_len) < 50;
+	PrintAndLog("is data xored?  %d  ( %d %)", isXored, (numOfZeros*100/stamp_len));
+
+	print_hex_break( data_buf, 33, 16);
+	
+	return 0;
+	
 	PrintAndLog("\nADF: User Area");
-	printf("-------------------------------------\n");
+	PrintAndLog("------------------------------------------------------");
 	i = 22;  
 	// 64 potential segements
+	// how to detect there is no segments?!?
 	for ( segmentNum=0; segmentNum<64; segmentNum++ ) {
 		segment_len = ((data_buf[i+1]^crc)&0x0f) * 256 + (data_buf[i]^crc);
 		segment_flag = ((data_buf[i+1]^crc)&0xf0)>>4;
@@ -144,7 +175,7 @@ int CmdLegicDecode(const char *Cmd) {
 		segCalcCRC = CRC8Legic(segCrcBytes, 8);
 		segCRC = data_buf[i+4]^crc;
 
-		PrintAndLog("Segment %02u \nraw header=0x%02X 0x%02X 0x%02X 0x%02X \nSegment len: %u,  Flag: 0x%X (valid:%01u, last:%01u), WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)",
+		PrintAndLog("Segment %02u \nraw header | 0x%02X 0x%02X 0x%02X 0x%02X \nSegment len: %u,  Flag: 0x%X (valid:%01u, last:%01u), WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)",
 			segmentNum,
 			data_buf[i]^crc,
 			data_buf[i+1]^crc,
@@ -165,9 +196,10 @@ int CmdLegicDecode(const char *Cmd) {
     
 		if ( hasWRC ) {
 			PrintAndLog("WRC protected area:   (I %d | K %d| WRC %d)", i, k, wrc);
-
+			PrintAndLog("\nrow  | data");
+			PrintAndLog("-----+------------------------------------------------");
 			// de-xor?  if not zero, assume it needs xoring.
-			if ( data_buf[i] > 0) {
+			if ( isXored) {
 				for ( k=i; k < wrc; ++k)
 					data_buf[k] ^= crc;
 			}
@@ -178,9 +210,10 @@ int CmdLegicDecode(const char *Cmd) {
     
 		if ( hasWRP ) {
 			PrintAndLog("Remaining write protected area:  (I %d | K %d | WRC %d | WRP %d  WRP_LEN %d)",i, k, wrc, wrp, wrp_len);
+			PrintAndLog("\nrow  | data");
+			PrintAndLog("-----+------------------------------------------------");
 
-			// de-xor?  if not zero, assume it needs xoring.
-			if ( data_buf[i] > 0) {
+			if (isXored) {
 				for (k=i; k < wrp_len; ++k)
 					data_buf[k] ^= crc;
 			}
@@ -195,8 +228,9 @@ int CmdLegicDecode(const char *Cmd) {
 		}
     
 		PrintAndLog("Remaining segment payload:  (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len);
-		
-		if ( data_buf[i] > 0 ) {
+		PrintAndLog("\nrow  | data");
+		PrintAndLog("-----+------------------------------------------------");
+		if ( isXored ) {
 			for ( k=i; k < remain_seg_payload_len; ++k)
 				data_buf[k] ^= crc;
 		}
@@ -205,7 +239,7 @@ int CmdLegicDecode(const char *Cmd) {
     
 		i += remain_seg_payload_len;
 		
-		printf("\n-------------------------------------\n");
+		PrintAndLog("-----+------------------------------------------------\n");
 
 		// end with last segment
 		if (segment_flag & 0x8) return 0;
@@ -215,6 +249,13 @@ int CmdLegicDecode(const char *Cmd) {
 }
 
 int CmdLegicRFRead(const char *Cmd) {
+	
+	// params:
+	// offset in data
+	// number of bytes.
+	char cmdp = param_getchar(Cmd, 0);
+	if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_read();
+	
 	int byte_count=0, offset=0;
 	sscanf(Cmd, "%i %i", &offset, &byte_count);
 	if(byte_count == 0) byte_count = -1;
@@ -328,15 +369,18 @@ int CmdLegicSave(const char *Cmd) {
 		return 0;
 	}
 
+	GetFromBigBuf(got, requested, offset);
+	if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000)){
+		PrintAndLog("Command execute timeout");	
+		return 1;
+	}
+
 	FILE *f = fopen(filename, "w");
 	if(!f) {
 		PrintAndLog("couldn't open '%s'", Cmd+1);
 		return -1;
 	}
-
-	GetFromBigBuf(got, requested, offset);
-	WaitForResponse(CMD_ACK, NULL);
-
+	
 	for (int j = 0; j < requested; j += 8) {
 		fprintf(f, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
 			got[j+0], got[j+1], got[j+2], got[j+3],
@@ -351,6 +395,7 @@ int CmdLegicSave(const char *Cmd) {
 	return 0;
 }
 
+//TODO: write a help text (iceman)
 int CmdLegicRfSim(const char *Cmd) {
 	UsbCommand c = {CMD_SIMULATE_TAG_LEGIC_RF, {6,3,0}};
 	sscanf(Cmd, " %"lli" %"lli" %"lli, &c.arg[0], &c.arg[1], &c.arg[2]);
@@ -359,6 +404,7 @@ int CmdLegicRfSim(const char *Cmd) {
 	return 0;
 }
 
+//TODO: write a help text (iceman)
 int CmdLegicRfWrite(const char *Cmd) {
     UsbCommand c = {CMD_WRITER_LEGIC_RF};
     int res = sscanf(Cmd, " 0x%"llx" 0x%"llx, &c.arg[0], &c.arg[1]);
@@ -398,12 +444,16 @@ int CmdLegicRfFill(const char *Cmd) {
 int CmdLegicCalcCrc8(const char *Cmd){
 
 	int len =  strlen(Cmd);	
-	if (len & 1 ) return usage_legic_calccrc8(); 
+	if ( len & 1 ) return usage_legic_calccrc8(); 
 	
-	uint8_t *data = malloc(len);
+	// add 1 for null terminator.
+	uint8_t *data = malloc(len+1);
 	if ( data == NULL ) return 1;
 		
-	param_gethex(Cmd, 0, data, len );
+	if (param_gethex(Cmd, 0, data, len )) {
+		free(data);
+		return usage_legic_calccrc8();	
+	}
 	
 	uint32_t checksum =  CRC8Legic(data, len/2);	
 	PrintAndLog("Bytes: %s || CRC8: %X", sprint_hex(data, len/2), checksum );