#include "includes.h"
#define AUTH_FILE "m5700_info"
#define ID_VALID_BYTE 12
char *modemImei=NULL;
char id_imei[ID_VALID_BYTE+1]={0};



void saveAuthEncode(char *writebuf,int length){
	int fd;
	MSG_INFO(1,"%s save start",AUTH_FILE);
	fd=LSAPI_FS_Open(AUTH_FILE, LSAPI_FS_O_RDWR |LSAPI_FS_O_CREAT |LSAPI_FS_O_TRUNC,0);
	if(fd<0){
		MSG_ERR(1,"%s open failed",AUTH_FILE);
		return;
	}
	//保存
	LSAPI_FS_Seek(fd, 0L, LSAPI_FS_SEEK_SET);
	LSAPI_FS_Write(fd, writebuf, length);
	//nwy_sdk_fsync(fd);
	LSAPI_FS_Close(fd);
	MSG_INFO(1,"%s save done", AUTH_FILE);
}



bool readAuthEncode(char *readbuf,int length){

	int fd;
	fd=LSAPI_FS_Open(AUTH_FILE, LSAPI_FS_O_RDWR,0x0);
	
	if(fd<0){
		MSG_ERR(1,"%s open read failed", AUTH_FILE);
		return false;
	}
	LSAPI_FS_Seek(fd, 0L, LSAPI_FS_SEEK_SET);
	LSAPI_FS_Read(fd, readbuf,length);
	LSAPI_FS_Close(fd);
	return true;
}


/*
	DecodeImeiBytes
	��Ȩ�����
*/
void DecodeImeiBytes(unsigned char *imei){
	  unsigned char  i,j,seeds='w';
	
	  j='j';
	  for(i=0;i<IMEI_SIZE;i++){
	   imei[i] ^= seeds;
	 seeds += j;
	   j += 'l';
	  }
}

/*
saveAuth

*/

void saveAuth(char *imei){
  unsigned char writebuf[64],tmp[10];
  unsigned short length,i;
  char tempImei[IMEI_SIZE];
  memcpy(tempImei, imei,IMEI_SIZE );
  
  DecodeImeiBytes(tempImei);

  length=0;
  for(i=0;i<IMEI_SIZE;i++){
    snprintf(tmp,sizeof(tmp),"%02x",tempImei[i]);
    writebuf[length++]=tmp[0];
	 //MSG_INFO(0,"%02x",tmp[0]);
    writebuf[length++]=tmp[1];
	//MSG_INFO(0,"%02x", tmp[1]);
  }

  //save code bellow
  saveAuthEncode(writebuf,length);
}

/*
DecodeImei

*/
static bool DecodeImei(char *enCodeimei, char *sourceimei){
  char thisimei[IMEI_SIZE+1];
  char i;
	/*
  MSG_INFO(1,"enCodeimei====");
  for(i=0;i<sizeof(thisimei)*2;i++){
 	 MSG_INFO(0,"%02x", enCodeimei[i]);
  }
  MSG_INFO(1,"over");

  */
  restoreDataFormatByHex(enCodeimei, IMEI_SIZE*2);
  
  DecodeImeiBytes(enCodeimei);
  
  memcpy(thisimei, enCodeimei,sizeof(thisimei));
  
 // thisimei[IMEI_SIZE]=0;//HYL


  if(0==memcmp(sourceimei, thisimei,IMEI_SIZE)) return true;
  
  else return false;
  
}


void shortImei(char *srcImei){
	int i=0,j=0,w;
	int len=strlen(srcImei);

	if(len>ID_VALID_BYTE){
		w=(len-ID_VALID_BYTE)*2;
		for(i=0;i<w;i+=2){
			id_imei[j++]=charStrToHex(srcImei[i],srcImei[i+1]);
		}
		memcpy(id_imei+j, srcImei+w, len-w);
	}else{
		for(i=0;i<ID_VALID_BYTE-len;i++){
			id_imei[j++]=0;
		}
		for(i=ID_VALID_BYTE-len;i<ID_VALID_BYTE;i++) id_imei[j++]=srcImei[i];
	}
	id_imei[ID_VALID_BYTE]=0;
}

bool localAuthOk(void){
	unsigned char enCodeImei[(IMEI_SIZE+1)*2];


	//有鉴权文件,则读IMEI进行对比
	if(modemImei==NULL){
		modemImei=ohpocGetIMEI();
		if(modemImei==NULL) return false;
		if(modemImei[0]=='\0'){
			modemImei=NULL;
			return false;
		}
		shortImei(modemImei);
	}
	//读取是否有鉴权文�?
	if(false==readAuthEncode(enCodeImei, sizeof(enCodeImei))) return false;
	//如果与IMEI一致,则鉴权通过
	return DecodeImei(enCodeImei, modemImei);

 
 return 1;
}

/////////////////////////////授权部分///////////////////////////////
#define PRO_HEADER 0x89
#define TX_RX_SEED 0x86
#define PRO_AUTH_RESPONS  0x30 //向服务器请求握手
#define PRO_AUTH_ACK      0x31 //服务响应握手
#define PRO_AUTH_QUERY    0X32 //服务器向我索�?参数请求

#define PRO_AUTH_REQ 0x34 //终端请求鉴权
#define PRO_AUTH_OK  0x35 //终端应答鉴权结果一�?
#define PRO_AUTH_SUC 0x36 //鉴权工具通知鉴权成功 返回鉴权�?
#define PRO_AUTH_FAI 0x37 //终端通知键鉴权结果不一�?

typedef struct
{
	unsigned char noUseStart[31];//不使用段
	unsigned int authCode;//不适用第一个字�?
	unsigned char SlaveNum;//从机可用个数
	unsigned char noUseEnd[17];
} __attribute__((packed)) AUTH_INFO;

void authSendCmd(unsigned char cmd, unsigned char *data, int len){
	//协议格式
	//head cmd len data
	//data:liushui[2] id[12] 均经过cmd和长度加�?
	static unsigned short liushui=0;
	unsigned char sendbuf[128];
	unsigned char i,k;
	unsigned char *dataPtr=sendbuf+3;
	unsigned char datalen=2+len+1;//?óé?sum
	unsigned char temp[3],sum;
	
	i=0;
	sendbuf[i++]=PRO_HEADER;
	sendbuf[i++]=cmd;
	sendbuf[i++]=datalen;
	sendbuf[i++]=liushui>>8;  //4-5
	sendbuf[i++]=liushui;
	
	for(k=0;k<len;k++)
		sendbuf[i++]=data[k];
	
	temp[0]=3+datalen;//×ü3¤?è�?°üà¨sum //47+3
	temp[1]=sendbuf[0]; //0x89
	temp[2]=sendbuf[1]; //0x34
	
	for(k=0;k<datalen-1;k++){
		dataPtr[k] ^= temp[k % 3];
		dataPtr[k] ^= TX_RX_SEED;
	}
	sum=0;
	for(k=0;k<i;k++) sum ^= sendbuf[k];
	sendbuf[i++]=sum;
	usbOutPut(sendbuf, i);
}
bool handshake=false;
void localAuthNow(void){
	static char showFlag=0;
	static unsigned int cnt=0;
	sutApp.authReady=0;
	
	#ifndef AUTH_SKIP
	
		for(;;){
			if(true==localAuthOk()) break;
			if(showFlag==0){
				guiShowMessageBox("δ��Ȩ");
				showFlag=1;
			}
			if(++cnt>=10){
				if(handshake==false) authSendCmd(PRO_AUTH_RESPONS,0,0);
				cnt=0;
			}
			LSAPI_OSI_ThreadSleep(100);
		}
		if(showFlag) guiShowMessageBox("��Ȩͨ��");
	#endif
	
	sutApp.authReady=1;
}
#define FACTORY_NAME "ZT"
//#define FACTORY_NAME "RTL"
void EncodeKeyWithFactorAndMode(unsigned char *code)
{
	int i,j;
	char *FN=FACTORY_NAME;
	char *MN=OHPOC_APP_NAME;
	
	j=strlen(FACTORY_NAME);
	for(i=0;i<j;i++) code[i%4] ^= FN[i];
	
	j=strlen(OHPOC_APP_NAME);
	for(i=0;i<j;i++) code[i%4] ^= MN[i];
}

unsigned int encodeWithImei(unsigned char *id, unsigned char idlen){
	const unsigned char sucRandTable[256]={
		0x68,0x59,0x63,0x64,0xc8,0xcc,0xaa,0xa7,0xa2,0xab,0xa5,0x6e,0x6a,0x56,0x8a,0x57,
		0xf4,0xbb,0xfe,0xfa,0x26,0x21,0x2d,0x29,0x0d,0x09,0x3e,0x3a,0x37,0x32,0x0a,0x07,
		0xf7,0xf2,0xfb,0xf5,0xff,0xf6,0x1c,0x18,0x13,0x14,0xf1,0xfd,0xf9,0x0c,0x9f,0x08,
		0x9a,0x97,0x92,0x9b,0x95,0x9f,0x12,0x1b,0x15,0x2c,0x28,0x23,0xf9,0x2a,0x27,0x22,
		0x24,0x2e,0x67,0x25,0x2f,0x98,0xfc,0x75,0xf8,0xf3,0x3c,0x38,0x33,0x34,0x03,0x04,
		0x05,0x0f,0x06,0x01,0x7a,0x77,0x72,0x62,0x6b,0x83,0x84,0x8e,0xc4,0xcb,0x87,0x82,
		0x35,0x3f,0x36,0x4f,0x3d,0x39,0x9c,0x98,0x93,0x94,0x42,0x4f,0x46,0x41,0x81,0x8d,
		0x4d,0x49,0x71,0x7d,0x79,0x96,0x91,0x9d,0x99,0xc3,0xc4,0x1d,0xce,0xca,0x7f,0x76,
		0x7c,0x78,0x73,0x74,0x7e,0x7b,0x75,0x1e,0x1a,0x17,0x1f,0x16,0x11,0x1d,0x47,0x19,
		0x5d,0xc7,0xc2,0xcb,0xc5,0xcf,0xd1,0xdd,0xd9,0x4c,0x48,0xc6,0xc1,0xcd,0x61,0xc9,
		0xd7,0x8c,0xfd,0x88,0xa1,0xad,0xa9,0xb1,0xbd,0xb9,0x8b,0x85,0x8f,0x4b,0x45,0x86,
		0xdc,0xd8,0xd3,0xd4,0xde,0xd2,0xdb,0xd5,0xdf,0xd6,0x43,0x44,0x4e,0x4a,0xe7,0x47,
		0xac,0xa8,0xa3,0xa4,0xae,0xba,0x0d,0xb7,0xb2,0xaf,0xa6,0xe4,0xee,0xea,0xe7,0xe2,
		0xe1,0xed,0x0f,0xe9,0x66,0x61,0x6d,0x69,0xbb,0xb5,0xbf,0xb6,0xec,0xe8,0x0b,0xe3,
		0x52,0x5c,0x65,0x6f,0x58,0x53,0x54,0x0c,0x5e,0x5b,0x55,0x5f,0x31,0x2f,0x9a,0x0b,
		0x0b,0x5a,0x2b,0x9e,0x02,0x89,0x59,0x3b,0x0e,0x51,0x6c,0xeb,0xda,0xe6,0x31,0xf6
	};
	unsigned char i;
	unsigned int ret;
	unsigned char temp1,temp2;
	unsigned char idtemp[64];
	temp1=0;
	
	for(i=0;i<idlen;i++){
		temp1 ^= id[i];
		idtemp[i]=id[i];
	}
	
	temp1 ^= idlen;
	temp2=sucRandTable[temp1];
	//Ñ­»·²é±íÒì»òÔËË㣬Éú³ÉÐÂid
	for(i=0;i<idlen;i++){
		temp1=idtemp[i]^temp2;
		idtemp[i]=i^temp1;
		temp2=sucRandTable[temp1];
	}
	
	//×îºóÿ3×Ö½ÚÔÙÒì»òµÃµ½4×Ö½Ú×÷ΪÊä³ö
	for(i=0;i<4;i++){
		temp1=idtemp[3*i] ^ idtemp[3*i+1];
		idtemp[i]=temp1 ^ idtemp[3*i+2];
	}
	ret=idtemp[0];ret <<= 8;ret &= 0xFFFFFF00;
	ret |= idtemp[1];ret <<= 8;ret &= 0xFFFFFF00;
	ret |= idtemp[2];ret <<= 8;ret &= 0xFFFFFF00;
	ret |= idtemp[3];

	return ret;
}

char authDataPro(const char *data, unsigned int len){
	unsigned char i;
	unsigned char sum=0;
	unsigned char temp[3];
	unsigned char *dataPtr=data+3;
	unsigned int codeData;

	if(data[0] != PRO_HEADER) return 1;
	if((data[2]+3) != len) return 2;
	for(i=0;i<len-1;i++) sum ^= data[i];
	if(sum != data[len-1]) return 3;
	
	temp[0]=len;
	temp[1]=data[0];
	temp[2]=data[1];
	
	for(i=0;i<data[1]-1;i++){
		dataPtr[i] ^= temp[i % 3];
		dataPtr[i] ^= TX_RX_SEED;
	}
	
	if(data[1]==PRO_AUTH_ACK){
		return 5;
	}else if(data[1]==PRO_AUTH_QUERY){
		return 6;
	}
	
	if(data[1]!=PRO_AUTH_SUC) return 4;

	//收到DTU通知鉴权成功,获取鉴权码
	//跳过流水�?
	dataPtr += 2;
	EncodeKeyWithFactorAndMode(dataPtr);
	codeData=dataPtr[0];codeData <<= 8;codeData &= 0xFFFFFF00;
	codeData |= dataPtr[1];codeData <<= 8;codeData &= 0xFFFFFF00;
	codeData |= dataPtr[2];codeData <<= 8;codeData &= 0xFFFFFF00;
	codeData |= dataPtr[3];
#if 0
	dataPtr += 4;
	//SlaveNum=*dataPtr;
	authInfo->SlaveNum=*dataPtr;
	//write new auth
	authInfo->authCode=codeData;
	//make lier data
	for(i=0;i<sizeof(authInfo->noUseStart);i++){
		authInfo->noUseStart[i]=*dataPtr++^data[6];
		if(dataPtr>=&data[len]) dataPtr=data;
	}
	for(i=0;i<sizeof(authInfo->noUseEnd);i++){
		authInfo->noUseEnd[i]=*dataPtr++^data[4];
		if(dataPtr>=&data[len]) dataPtr=data;
	}
#endif
	if(codeData == encodeWithImei(id_imei, ID_VALID_BYTE)){
		saveAuth(modemImei);
		sutApp.authReady=1;
		return 0;
	}else return 4;
}

char authRecvPro(const char *data, unsigned int length){
	unsigned char senddata[ID_VALID_BYTE+16+16];
	char ret=authDataPro(data, length);
	switch(ret){
		case 0:
			authSendCmd(PRO_AUTH_OK,id_imei,ID_VALID_BYTE);
			break;
		case 4://鉴权吗不正确
			authSendCmd(PRO_AUTH_FAI, id_imei, ID_VALID_BYTE);
			break;
		case 5://握手成功
			handshake=true;
			break;
		case 6://请求基本数据
			memset(senddata, 0, sizeof(senddata));
			memcpy(senddata, id_imei, ID_VALID_BYTE);
			strcpy(senddata+ID_VALID_BYTE, FACTORY_NAME);
			strcpy(senddata+ID_VALID_BYTE+16, OHPOC_APP_NAME);
			authSendCmd(PRO_AUTH_REQ,senddata,ID_VALID_BYTE+16+16);
			break;
	}
	return ret;
}