/*

*
*
*
*/

#include "function_interface.h"
#include "platform_interface.h"
#include "base_core_user.h"
#include "function.h"
#include "string.h"
#include "AES.h"
#include "HW_MCUIO.h"
//#include "stm32f4xx_hal.h"


//#define 	E2PROM_ADDR_KEYCODE		0x100	
#define 	STORE_AES_KEYCODE_ADDR			0x400	//len =32
#define 	STORE_AES_CONFIG_ADDR				0x420	//0x120	//len =3	//20200427修改，解决和IP地址存储冲突!!														


#define 	KEY_CODE_LEN					32	
#define 	KEYCODE_LEN_HALF			16


const unsigned char Keycode_Sunvote[] ="SunVote1998&JackPei1972CoolBob99";//32字节原始密码原始数据
	
struct AES_STR{
	unsigned char type_0_128_256;
	unsigned char _mcu_flag;	//硬件AES; =0-->软件AES	  AesMcu
	unsigned char key_update_flag;
	
	unsigned char keycode0[KEY_CODE_LEN];	//skey0
	unsigned char keycode[KEY_CODE_LEN];	//skey
};
struct AES_STR aes;





/*
* 加密函数
* input:
	key					--
	_256_mode 	--128 or 256
*/
static void Encrypt(unsigned char *src,unsigned char *dist,unsigned char *key,unsigned char _256_mode)
{ 
	uint32_t output_len;
	
	if(_256_mode==2)
		_256_mode =1;	//AES 256
	else
		_256_mode =0;	//AES 128
	
	if (aes._mcu_flag==1)
	  STM32_AES_ECB_Encrypt(src,16,key,dist,&output_len,_256_mode);//16是src长度，函数里面支持加密模式
	 else
	  AES_Encrypt((char*)src,(char*)dist,(char*)key,_256_mode);	 
}

/*
* 解密函数
* 
*/
static void Decrypt(unsigned char *src,unsigned char *dist,unsigned char *key,unsigned char _256_mode)
{
	uint32_t output_len;
	
	if(_256_mode==2)
		_256_mode =1;	//AES 256
	else
		_256_mode =0; //AES 128
	
	if (aes._mcu_flag==1)
		STM32_AES_ECB_Decrypt(src,16,key,dist,&output_len,_256_mode);
	else
		AES_Decrypt((char*)dist,(char*)src,(char*)key,_256_mode);	
}



/*
* 获取默认的秘钥
* input:key ---对应demo中的sKey0;
* note:使用AES128分别操作前后16bytes
*/
static void generate_default_key0_code(void)
{
	unsigned char i;
	
	memset(aes.keycode0,0,KEY_CODE_LEN);
	memcpy(aes.keycode,Keycode_Sunvote,KEY_CODE_LEN);
	
	for(i=0;i<KEY_CODE_LEN;i++)
		aes.keycode[i] =aes.keycode[i]^rsbox[i];
		
	//用后16字节加密前16字节,保存到输出key[16]
	Encrypt(aes.keycode,aes.keycode0,aes.keycode+16,0);		//special --128AES
	//用前16字节加密后16字节
	Encrypt(aes.keycode+16,aes.keycode0+16,aes.keycode,0);
}



/*
* read key code from E2prom
* input:code ---对应demo里的sKey
*/
static void read_keycode(void)
{
	unsigned char i;
	unsigned char tmp[KEYCODE_LEN_HALF];

	//read first 16bytes
	platform.e2prom_read(STORE_AES_KEYCODE_ADDR,tmp,KEYCODE_LEN_HALF);
	for(i=0;i<KEYCODE_LEN_HALF-1;i++)
		tmp[KEYCODE_LEN_HALF-1-i] = tmp[KEYCODE_LEN_HALF-2-i]^tmp[KEYCODE_LEN_HALF-1-i];	
	Decrypt(tmp,aes.keycode,aes.keycode0,aes.type_0_128_256);
		
	//read second 16bytes	
	platform.e2prom_read(STORE_AES_KEYCODE_ADDR+16,tmp,KEYCODE_LEN_HALF);
	for(i=0;i<KEYCODE_LEN_HALF-1;i++)
		tmp[KEYCODE_LEN_HALF-1-i] = tmp[KEYCODE_LEN_HALF-2-i]^tmp[KEYCODE_LEN_HALF-1-i];	
	Decrypt(tmp,aes.keycode+16,aes.keycode0,aes.type_0_128_256);		
}




/*
* write key code from E2prom
*/
static void write_keycode(unsigned char *keycode)
{
	unsigned char tmp[KEY_CODE_LEN],i;
	
	//first 16 bytes
	Encrypt(keycode,tmp,aes.keycode0,aes.type_0_128_256);
	for(i=0;i<KEYCODE_LEN_HALF-1;i++)
		tmp[1+i] = tmp[i]^tmp[1+i];	
	platform.e2prom_write(STORE_AES_KEYCODE_ADDR,tmp,KEYCODE_LEN_HALF);	

	//next 16 bytes
	Encrypt(keycode+16,tmp,aes.keycode0,aes.type_0_128_256);
	for(i=0;i<KEYCODE_LEN_HALF-1;i++)
		tmp[1+i] = tmp[i]^tmp[1+i];	
	platform.e2prom_write(STORE_AES_KEYCODE_ADDR+16,tmp,KEYCODE_LEN_HALF);	
}



//---------------------- application ------------------------------------------

#define CMDNUM  18
const unsigned char CmdTAB[CMDNUM*2]=
{
	0x10,0x4E,//基础信标
	0x13,0x41,//ID投票信标
	0x14,0x42,//SN投票信标
	0x15,0x43,//ID确认信标
	0x16,0x44,//SN号确认信标
	0x17,0x45,//新版本SN+ID投票信标
	0x18,0x46,//新版本SN+ID确认信标
	0x19,0x47,//新版本SN+ID确认信标---统一到0x46?
	
	0x20,0x4A,//多包指令
	0x30,0x4B,//单包指令
	//0x4C 单独用于按缺省秘钥加密的指令，用于配对时候传输
	0x40,0x4D, //多包下载
	
	0x91,0x51,//ID结果
	0x92,0x52,//SN号结果
	0x93,0x53,//新SN结果
	0x94,0x54,//新SN+ID结果
	0xA0,0x5A,//多包指令键盘应答
	0xB0,0x5B,//单包指令键盘应答
	0xC0,0x5C, //多包下载键盘应答
};

//带加密后命令码转换
static unsigned char CmdXch(unsigned char Cmd)
{
	unsigned char i;
	for (i=0;i<CMDNUM;i++)
	{
		if (CmdTAB[i+i]==Cmd)
			 return CmdTAB[i+i+1];
	}
	
	for (i=0;i<CMDNUM;i++)
	{
		if (CmdTAB[i+i+1]==Cmd)
			 return CmdTAB[i+i];
	}
	
	return 0;
}


/*
* 判断基站是免配对模式
*/
unsigned char base_is_auto_match(void)
{
	if( (base_core.get_log_mode()==3) ||(base_core.get_log_mode()==6) )
		return 1;
	else 
		return 0;
}

/*
* 无线加密
* 数据长度固定33，why??
*/
void rf_Encrypt(unsigned char *src)
{
	unsigned char i,tmp,dist[KEY_CODE_LEN+1];
	
	if(!function.AES__SW) return;
	if(!aes.type_0_128_256) return;
	
//	{//crc check
//	unsigned short crc_tmp;
//	crc_tmp = crc16(src+5,26);
//	src[31]=crc_tmp>>8;
//	src[32]=crc_tmp&0xff;
//	src[0]=32;	
//	}	
	
	//------------ CRC ----------------
	{
	unsigned short crc_tmp;
	crc_tmp = crc16(src+5,26);
	src[31]=crc_tmp>>8;
	src[32]=crc_tmp&0xff;
	src[0]=32;
	}		
	//---------------------------------
	
	//0, copy
	memcpy(dist,src,KEY_CODE_LEN+1);
	
	//a,
	if( (tmp=CmdXch(src[5])) >0)
		dist[5] =tmp;

	//byte6-21 加密
	if( ((dist[5]==0x41)||(dist[5]==0x42) ) &&(dist[9]==40) ){//0x13->0x41 0x14->0x42
		dist[5] =0x4C;
		Encrypt(src+6,dist+6,aes.keycode0,aes.type_0_128_256);
	}
	else{	
		if(base_is_auto_match() ){//---
			//dist[5] =0x4C;
			Encrypt(src+6,dist+6,aes.keycode0,aes.type_0_128_256);
		}
		else //---
		Encrypt(src+6,dist+6,aes.keycode,aes.type_0_128_256);
	}
	//byte22-32 加密：和加密后的前11字节异或；
	for(i=0;i<11;i++)
		dist[22+i] =src[22+i]^dist[6+i];
	
	//d, byte6-32做前后相关处理，避免全0数据容易猜出，和前一个字节异或，好恢复
	for(i=7;i<KEY_CODE_LEN+1;i++)
		dist[i] =dist[i-1]^dist[i];
	
	//e，两两互换位置;
	for(i=6;i<KEY_CODE_LEN-1;i+=2){
		tmp = dist[i]^0x55;
		dist[i] = dist[i+1]^0xA5;
		dist[i+1] =tmp;
	}
		
	memcpy(src,dist,KEY_CODE_LEN+1);
	
	src[0] =32;	//?????????????? 如此写定，只能用于32byte无线传输，64byte的不适用、
}



/*
* 无线解密;
*  CRC错误返回0;
* 其他情况： 没有开启AES; sdk 关闭AES加密和加密完全正确;
*/
unsigned char rf_Decrypt(unsigned char *src)
{
	unsigned char i,tmp,dist[KEY_CODE_LEN+1];	
	unsigned char src1[KEY_CODE_LEN/2];
	
	if(!function.AES__SW) return 1;
	if(!aes.type_0_128_256) return 1;
	
	//0, copy
	memcpy(dist,src,KEY_CODE_LEN+1);
	
	//a,
	if( (tmp=CmdXch(dist[5])) >0)
		dist[5] =tmp;

	for(i=6;i<KEY_CODE_LEN-1;i+=2){
		tmp = dist[i]^0xA5;
		dist[i] = dist[i+1]^0x55;
		dist[i+1] =tmp;
	}	

	for(i=0;i<26;i++)
		dist[32-i] =dist[31-i]^dist[32-i];		
		
	for(i=0;i<11;i++)
		dist[22+i] =dist[22+i]^dist[6+i];	
	
	memcpy(src1,dist+6,KEY_CODE_LEN/2);	

	if(base_is_auto_match() ){
		Decrypt(src1,dist+6,aes.keycode0,aes.type_0_128_256);	
	} else		
	if(dist[5] !=0x4C){
		Decrypt(src1,dist+6,aes.keycode,aes.type_0_128_256);
	}
	else
	{		
		Decrypt(src1,dist+6,aes.keycode0,aes.type_0_128_256);		
		dist[5] =0x13;	//投票信标;
	}	
	
	memcpy(src,dist,KEY_CODE_LEN+1);
	
	//-------- CRC -----------------	
	{
		unsigned short crc_tmp;
		if( (src[31]>0) || (src[32]>0) ){
			crc_tmp = crc16(src+5,26);
			if( ((crc_tmp>>8) !=  src[31]) || ( (crc_tmp&0xff) !=  src[32]) )
				return 0;
		}			
	}			
	//------------------------------
	
	return 1;
}



/*
* 读取AES config
*/
static void read_AES_config(void)
{
	unsigned char tmp[8];
	
	platform.e2prom_read(STORE_AES_CONFIG_ADDR,tmp,3);
	if(tmp[0]== 0xF5){//STORE_FLAG
		aes.type_0_128_256 =tmp[1];
		aes.key_update_flag =tmp[2];		
	}
	else{
		aes.type_0_128_256 =0;		
	}
}



/*
* 0x61 cmd from sdk 
*see protocol xxx  section yy
*/
void process_pc_aes_config(const unsigned char *rx_pc)
{
		unsigned char tmp[32]; 

		if(rx_pc[3] ==24){//write config
			aes.type_0_128_256 =rx_pc[4];
			aes.key_update_flag =rx_pc[5];
			tmp[0]= 0xF5;			
			tmp[1]= rx_pc[4]; 
			tmp[2]= rx_pc[5]; 											
			platform.e2prom_write(STORE_AES_CONFIG_ADDR,tmp,3);
		}
		
		tmp[0]= aes.type_0_128_256;
		tmp[1]= aes.key_update_flag;	
		user__pc_cmd_ack(0x61,23,tmp,2);
}


/*
*快速配对时 增加aes秘钥的传送;
*input :fdata = vote beacon
*/
void aes_load_fastmatch_data(unsigned char *fdata)
{
	static unsigned char aes_pos=0;
//	unsigned char i;
	
	if(!function.AES__SW) return;	
	if(!aes.type_0_128_256) return;
	
	//特殊处理:快速配对下的aes256加密时，byte5都变成0x13;
	if( base_core.get_log_mode() >3 )
			fdata[5] =0x13;
	
	aes_pos ^=1;	
	fdata[14] =aes.type_0_128_256;
	if(aes_pos)
		fdata[10] = 3;
	
	memcpy(fdata+15,aes.keycode+16*aes_pos,16);
}



/*
*更新秘钥，快速配对启动时被调用！
*/
void aes_keycode_upgrade(void)
{
	unsigned char i;

	if(!function.AES__SW) return;	
	if(!aes.type_0_128_256) return;
	
	if(aes.key_update_flag)return;	//判断 更新秘钥的开关
	
	srand(HW_TIMER_Count_get( TIMER5 ));//(TIM5->CNT);//!!否则后面rand生成数字是一样的序列
	for(i=0;i<KEY_CODE_LEN;i++)
		aes.keycode[i] =rand();	
	write_keycode(aes.keycode);
}



/*
* check AES function!! test only
*/
static unsigned char aes_test(void)
{
	unsigned char rfbuf[KEY_CODE_LEN+1];
	unsigned char i,ret_val;
	
	rfbuf[0]=28;
	rfbuf[1]=0x11;
	rfbuf[2]=0x11;
	rfbuf[3]=0x11;
	rfbuf[4]=0x11;//配对码
	rfbuf[5]=0x13;//合理CMD值

	for(i=6;i<KEY_CODE_LEN+1;i++)
		rfbuf[i]='a'-6+i;//好观察数据
	
	rf_Encrypt(rfbuf);
	rfbuf[0]=32;
	
	//
	rf_Decrypt(rfbuf);	
	rfbuf[0]=32;	
	
	//相对demo 来说修改成6,29,30;  byte31-32被CRC占用;
	 if ((rfbuf[6]=='a')&&(rfbuf[29]=='x')&&(rfbuf[30]=='y'))
		 ret_val= 1;
	 else
		 ret_val= 0;	
			
	return ret_val;
}



/*
* mcu flag: MCU or software;
* mode flag:128 or 256 aes
*/
//void aes_init(unsigned char mcuflag,unsigned char _modeflag)
void aes_init(void)
{
	if(!function.AES__SW) return;
	
	//read aes.on_off_flag, from e2prom;
	read_AES_config();
//	aes.type_0_128_256 =1;	//test only!!!!
//	aes._256_flag =1;//AES mode;
	aes._mcu_flag =1;//AES mcu flag;
	
	if (aes._mcu_flag==1){
		//__HAL_RCC_CRC_CLK_ENABLE();//
//		__CRC_CLK_ENABLE();//打开硬件CRC时钟，软件库加解密才正确
	}

	//get sunvote key
	generate_default_key0_code();	
	//
	read_keycode();
	
	//test only
	while(! aes_test());	
}


/*
*
*/
void get_aes_key(unsigned char *key)
{
	memcpy(key,aes.keycode,32);

}


/*
获取AES加密的状态：不加密，128 or 256
*/
unsigned char get_aes_status(void)
{
	if(function.AES__SW==0)
		return 0;
	else
		return aes.type_0_128_256 ;
}




