/************************************************************************* 
* 版权所有：	
* 文件版本： V1.00
* 文件名称：SM2.c
* 生成日期： 2012年7月1日
* 作	者： xxxxxx
* 功	能： 事件记录处理
* 更新信息：
*	  更新日志1：
*		  日期：	  
*		  修改者：	  
*		  修改内容：  
*		  修改原因：  
*	  
**************************************************************************/
#include "head.h"

#ifdef ENCRYPT_SM2
char sm2debugstr[256];
#if 1  // 长沙,测试104
unsigned  char SM2_key1[68]=
{
	0x00,0x01,0x00,0x00,0xB8,0x22,0x88,0x73,0xB8,0x0D,0xE8,0xD8,0x5E,0xDF,0x12,0xB8,
	0x27,0xDD,0x71,0x8A,0x7D,0xF6,0x38,0x22,0xDB,0x79,0x3D,0x42,0x9B,0x20,0xE8,0x3F,
	0x74,0x70,0x22,0x97,0x3E,0x1F,0x19,0x6E,0x41,0x81,0xC7,0x9F,0xA5,0x8D,0xB7,0x89,
	0x8F,0xF9,0x3E,0xC4,0x4B,0x6C,0xAE,0xB1,0xC9,0x8C,0x3B,0xDC,0x53,0xA2,0x78,0xAA,
	0x8D,0x77,0x4E,0x2A
};

unsigned  char SM2_key2[68]=
{
	0x00,0x01,0x00,0x00,0xBF,0xE3,0xC3,0x5B,0xE1,0x1A,0x18,0x0F,0x65,0x43,0x16,0x9D,
	0x0C,0x82,0x6B,0xBF,0x38,0xDA,0xB7,0x2E,0x0E,0x4E,0x01,0x26,0x9C,0x4A,0xE8,0xAB,
	0x16,0xAD,0xEA,0xEC,0x15,0x84,0xA3,0x45,0x7C,0xAE,0xE5,0x8A,0xF1,0x0F,0x9A,0x1E,
	0x17,0x92,0x75,0x94,0xA4,0x72,0x53,0x37,0xFA,0xE9,0xAC,0x3C,0x8D,0xA1,0x64,0xF9,
	0xE1,0x57,0x37,0x28
};

#endif

#if 0  // 电科院，测试101
unsigned  char SM2_key1[68]=
{
	0x00,0x00,0x01,0x00,0xe4,0x00,0xaa,0xef,0xdc,0xf9,0x40,0x84,0x1a,0x24,0x27,0xe0,
	0x9a,0x59,0xeb,0x6d,0x93,0xdb,0x97,0x41,0xbf,0xf3,0x72,0xa0,0x19,0xe8,0xf0,0x04,
	0x80,0xab,0xb5,0xd9,0x27,0x8e,0xde,0x11,0x35,0x1e,0xf3,0xde,0x86,0x25,0x2d,0x60,
	0xe2,0xef,0x90,0xfe,0x57,0xe7,0x98,0x1a,0x60,0xc0,0xad,0xac,0xce,0x2f,0x35,0x05,
	0xeb,0xfc,0xf1,0xd5
};

unsigned  char SM2_key2[68]=
{
	0x00,0x00,0x01,0x00,0x9c,0x5b,0x8d,0x20,0xe6,0xd8,0x51,0x1b,0x27,0x7b,0x81,0x77,
	0xc3,0x5b,0x9f,0xd9,0x87,0x11,0x09,0xe8,0xa9,0x96,0x57,0x83,0x41,0xa9,0x29,0x48,
	0xb3,0xd3,0x58,0xb5,0x63,0x54,0xa9,0xbf,0xdd,0xfd,0x4a,0x71,0xa8,0xb9,0x4a,0x68,
	0x8d,0xa7,0x64,0x77,0xa5,0xcc,0x74,0x69,0x87,0x8c,0x7a,0xd7,0x49,0x71,0x60,0xbe,
	0xb7,0x5a,0x26,0xe6
};

#endif

#if 0  // 珠海许继
unsigned  char SM2_key1[68]=
{
	0x00,0x01,0x00,0x00,0x7D,0xCF,0x5D,0xAD,0xBB,0xB3,0x21,0xD7,0xDA,0xCF,0x82,0x83,
	0x6C,0xAE,0x43,0xD4,0x69,0x60,0xFC,0xA4,0xDB,0xBA,0x58,0xD9,0xB1,0x07,0x45,0xD0,
	0x89,0x73,0x98,0x2A,0x60,0x5C,0x93,0x93,0x24,0x68,0x28,0x55,0xA2,0xE2,0xB7,0xDD,
	0x1A,0x58,0xEC,0x7E,0x8E,0x08,0x16,0x1C,0xA5,0xFC,0x69,0x92,0x9E,0x2F,0x1F,0x0D,
	0x83,0x71,0x03,0xA0
};

unsigned  char SM2_key2[68]=
{
	0x00,0x01,0x00,0x00,0x28,0x1A,0x0B,0x17,0x77,0xE0,0x46,0x2D,0x1E,0x5E,0x1C,0x85,
	0x0C,0x49,0xA2,0xE7,0x17,0x3F,0xDF,0xA7,0xC2,0x09,0xB0,0x21,0xE1,0x0E,0xB9,0xD0,
	0x62,0x72,0x90,0x85,0x5D,0x2C,0x41,0x50,0x7C,0x30,0x29,0xEF,0xCD,0x98,0x73,0x33,
	0xB3,0x3A,0x77,0xD7,0x9C,0xD6,0xDC,0x20,0xDC,0xA8,0x6E,0x1F,0x93,0x75,0x1F,0xE6,
	0xB7,0x33,0x69,0x42
};

#endif

unsigned  char SM2_key3[68]=
{
	0x00,0x00,0x01,0x00,0x7c,0x33,0x14,0x18,0x02,0xb3,0x7d,0x02,0x17,0xd9,0xef,0xe7,
	0xf3,0x1b,0xb3,0xb6,0x86,0x4a,0x76,0x05,0xf5,0xca,0x43,0x72,0x5d,0xa5,0x79,0xe2,
	0xef,0xe3,0x1e,0xbb,0x82,0x82,0x20,0x04,0x5f,0x62,0x48,0xb9,0xfd,0xda,0x83,0xda,
	0xb9,0x69,0x0e,0x89,0x15,0xef,0x55,0xed,0x02,0xe9,0x6e,0x87,0x05,0xc2,0x22,0x5f,
	0x7b,0xfc,0xf0,0xec
};

unsigned  char SM2_key4[68]=
{
	0x00,0x00,0x01,0x00,0x19,0xdc,0x29,0xd8,0x1a,0x2b,0x28,0x7d,0x3e,0x93,0xdf,0x22,
	0xe0,0x70,0xdd,0x9b,0x23,0x63,0x11,0x6b,0x51,0x97,0xb1,0xec,0x74,0xb5,0x17,0xe2,
	0x41,0xd4,0x53,0x8b,0x72,0x4b,0x64,0x3b,0x6c,0x31,0x4f,0x77,0xab,0x93,0xf3,0xfb,
	0x9b,0x21,0x46,0x29,0xc2,0x80,0xae,0x49,0xdf,0xe8,0x43,0x9e,0xef,0x61,0xd2,0x42,
	0xf2,0x02,0x2e,0x90
};

unsigned  char UserId[16]=
{
	//0x8F,0x12,0xE1,0x63,0xD2,0xAF,0x1C,0xAD,0x7C,0x58,0xE7,0xF4,0x65,0x0D,0x9B,0x4E
	0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
};

 int readSM2key(BYTE no,BYTE *dat)
{
	BYTE sm2file[32];
	loff_t pos;
	struct file * gfile;		
	memset(dat,0,68);	
	if(no>4)return -1; //key 最多支持5个
	sprintf(sm2file,"/app/data/sm2key%1d.bin",no);
	gfile = rt_file_open(sm2file,O_RDONLY,0);
	if(IS_ERR(gfile))
	{
		return -2;
	}
	pos = 0;
	rt_file_read(gfile,dat,68,&pos);
	rt_file_close(gfile,NULL);

	return 0;
}

 int writeSM2key(BYTE no,BYTE *dat)
{
	BYTE sm2file[32];
	loff_t pos;
	struct file * gfile;		
	if(no>4)return -1; //key 最多支持5个
	sprintf(sm2file,"/app/data/sm2key%1d.bin",no);
	gfile = rt_file_open(sm2file,O_CREAT|O_RDWR|O_TRUNC,0);
	if(IS_ERR(gfile))
	{
		return -2;
	}	
	pos = 0;
	rt_file_write(gfile,dat,68,&pos);
	rt_file_close(gfile,NULL);

	return 0;
}
 int readUserId(BYTE *dat)
{
	loff_t pos;
	struct file * gfile;		
	gfile = rt_file_open("/app/data/userid.bin",O_RDONLY,0);
	memset(dat,0,16);	
	if(IS_ERR(gfile))
	{
		return -1;
	}
	pos = 0;
	rt_file_read(gfile,dat,16,&pos);
	rt_file_close(gfile,NULL);

	return 0;
}


 int writeUserId(BYTE *dat)
{
	loff_t pos;
	struct file * gfile;		
	gfile = rt_file_open("/app/data/userid.bin",O_CREAT|O_RDWR|O_TRUNC,0);
	if(IS_ERR(gfile))
	{
		return -1;
	}	
	pos = 0;
	rt_file_write(gfile,dat,16,&pos);
	rt_file_close(gfile,NULL);

	return 0;
}

void InitSM2Key(void)
{
	writeSM2key(0,SM2_key1);
	writeSM2key(1,SM2_key2);
	writeSM2key(2,SM2_key3);
	writeSM2key(3,SM2_key4);
	writeUserId(UserId);
}

#if 0 // 此函数对1月解码有问题，不能使用
static uint32_t mktime_me(TIME *ct)
{
    TIME  Tm;
    WORD Year;
    Tm=*ct;
    Year = Tm.year+2000;
    if (0 >= (int) (Tm.month -= 2)) {    /* 1..12 -> 11,12,1..10 */
        Tm.month += 12;      /* Puts Feb last since it has leap day */
        Year -= 1;
    }

    return (((
        (uint32_t) (Year/4 - Year/100 + Year/400 + 367*Tm.month/12 + Tm.day) +
            Year*365 - 719499
        )*24 + Tm.hour /* now have hours */
      )*60 + Tm.min /* now have minutes */
    )*60 + (Tm.ms/1000); /* finally seconds */
}
#endif

ECCrefPublicKey *PubKeyNk;
ECCCipher EccMessage;

static  void IEC101_SM2Echo(IEC101_DEF *pt,BYTE *dat)  // 报文应答cf=3 cf=4
{
	BYTE *txbuf=pt->tx_buf_s;
	BYTE *pd=&txbuf[1];
	DWORD ltime;
	unsigned int outlen;
	BYTE keystr[68];  //
	BYTE datIn[32],pucrandom[32];  //
	
	BYTE sum=0;
	BYTE L2;
	int i;
	BYTE keynew;
	uint32_t us0,us;

	struct timespec ts;
//	struct rtc_time_t rtc;

	clk_time_get(&ts);
//	timespec_to_rtc(ts,&rtc,1);
	
	keynew=(dat[1]&0x03);		//加密或更新的证书
	
	L2=142;
	*pd++=0x16;
	*pd++=L2;
	*pd++=0x00;
	*pd++=0x16;
	*pd++=dat[0]; //功能码
	*pd++=dat[1]; //辅助状态
	*pd++=(BYTE)tRunPara.byAddr;       //装置地址 4字节
	*pd++=(BYTE)(tRunPara.byAddr>>8);
	*pd++=0; 
	*pd++=0; 

//	ltime=mktime_me(&rtc)-28800;   //北京东8区，减去8*3600秒
	ltime=ts.tv_sec-28800;   //北京东8区，减去8*3600秒

//	ltime=0xDF987C4E; //时间戳 测试用
	
	*pd++=(BYTE)ltime;       //时间戳
	*pd++=(BYTE)(ltime>>8);      
	*pd++=(BYTE)(ltime>>16);      
	*pd++=(BYTE)(ltime>>24);      

	*pd++=1;       			//公钥个数
	*pd++=0x00;
	*pd++=0x00;
	*pd++=0x00;
	

      memset(datIn,0,32);
      for(i=0;i<4;i++)
      {
		datIn[i]=dat[10+i];  //接收到的数据(4字节)
      }    
      
	SM2_GenerateRandom_me(32, pucrandom);   //随机变量
	readSM2key(keynew, keystr);			//key值


	us0 = ustimer_get_origin();
	SM2_Encrypt(datIn, 32, (ECCrefPublicKey*)keystr, pucrandom, 32, &EccMessage);	//非对称加密报文128个字节
	us = ustimer_get_duration(us0);
	if(g_print_sys)
	{
		sprintf(sm2debugstr,"SM2_Encrypt程序运行时间:%dus.\r\n",us);
		rt_printf(sm2debugstr);
	}

	memcpy(pd, EccMessage.x, 128);  // 非对称加密报文
	
	pd=&txbuf[5];           // 从功能码开始计算校验和
 	for(i = 0; i < L2; i++)		//  L2=0x8e 142个字节
	{
		sum +=  pd[i]; 
	}

 	for(i = 0; i < 14; i++)		//  
	{
		datIn[i]=  pd[i];  // 安全数据区数据，用做加密的输入数据
	}
  	encrypt_epri(datIn, 14, pd, &outlen, (sum|0xffffff00), (sum%3));	//报文对称加密,输出加密报文到发送缓冲区


	pd=&txbuf[L2+5];   //校验和位置       
	*pd++=sum;	
	*pd++=0x16;
	
	 txbuf[0]=L2+6;  //发送字节数

	if(g_print_101 && (g_print_port & (1<<pt->chnl)))
	{
		rt_printf("上送加密报文:");
		print_msg("TX_101:",&txbuf[1],txbuf[0]);
	 }
	 
	pt->btx_buf_s = true;
}

BYTE sm2dat[160];
BYTE sm2Verifydat[256];

 void IEC101_SM2(IEC101_DEF* pt)
 {
	BYTE *pd=&pt->recvbuf[256];
	BYTE *pv=sm2Verifydat;
	BYTE byL2,byL3,bySum;
	BYTE sum;
	DWORD sm2Addr,sm2Time,localTime,offTime;
	unsigned int lenth;
	int i;
	uint32_t us0,us;

	
	byL2=pd[1];
	byL3=pd[2];
	bySum=pd[byL2+4]; //校验和

	if(g_print_101 && (g_print_port & (1<<pt->chnl)))  
	{
		print_msg("SM_101:",pd,byL2+6);
	}

	if(g_print_sys)
	{
		sprintf(sm2debugstr,"L2=%02x  L3=%02x  bysum=%02x \r\n",byL2,byL3,bySum);
		rt_printf(sm2debugstr);
	}
	
	us0 = ustimer_get_origin();

	
	encrypt_epri(&pd[4], (byL2-byL3), sm2dat,&lenth,(bySum|0xffffff00),(bySum%3));  //解密安全数据区

	us = ustimer_get_duration(us0);
	if(g_print_sys)
	{
	
		sprintf(sm2debugstr,"程序运行时间:%dus.\r\n对称加密解密报文:",us);
		rt_printf(sm2debugstr);
		print_mem_net(NULL,sm2dat,byL2-byL3);
	}

	//校验和
	sum=0;
	for(i=0;i<(byL2-byL3);i++)
	{
		sum+=sm2dat[i];
	}
	for(i=0;i<byL3;i++)
	{
		sum+=pd[(byL2-byL3)+4+i];
	}
	if(g_print_sys)
	{
		sprintf(sm2debugstr,"\r\n校验和:sum=%02x  bySum=%02x\r\n",sum,bySum);
		rt_printf(sm2debugstr);
	}

	if(sum!=bySum)
	{

		return;	//校验和不相等
	}

	sm2Addr=sm2dat[2]+(sm2dat[3]<<8)+(sm2dat[4]<<16)+(sm2dat[5]<<24);  //装置地址

	if(g_print_sys)
	{
		sprintf(sm2debugstr,"\r\n地址:sm2Addr=%d  byAddr=%d\r\n",sm2Addr,tRunPara.byAddr);
		rt_printf(sm2debugstr);
	}

	
	if((tRunPara.byAddr!=(WORD)sm2Addr)&&(sm2Addr!=0xffffffff))
	{
		return; //不是发给本装置的数据
	}	
	sm2Time=sm2dat[6]+(sm2dat[7]<<8)+(sm2dat[8]<<16)+(sm2dat[9]<<24);  // 时间戳

	{
	struct timespec ts;
//	struct rtc_time_t rtc;

	clk_time_get(&ts);
//	timespec_to_rtc(ts,&rtc,1);

//	localTime=mktime_me(&rtc)-28800;   //北京东8区，减去8*3600秒
	localTime=ts.tv_sec-28800;   //北京东8区，减去8*3600秒
	}
	if(g_print_sys)
	{
		sprintf(sm2debugstr,"\r\n时间戳sm2=%d local=%d\r\n",sm2Time,localTime);
		rt_printf(sm2debugstr);
	}

	// 证书有效时间判定
	{
		u8 no;

		no = (sm2dat[0]&0x03);		//公钥号
		if (x509_isvalid_time(no, localTime) != 0)
		{
			return;
		}
	}
	
	if(sm2Time>localTime)
	{
		offTime=sm2Time-localTime;
	}
	else
	{
		offTime=localTime-sm2Time;
	}
	
	if(offTime>tRunPara.dSM2Time)	//时间戳超时
	{

		if(g_print_sys)
		{
			rt_printf("时间戳无效\r\n");
		}
		 return;
	}
	
	if((sm2dat[0]&0x40)==0)	//主站下发数据
	{
		BYTE keyno,Cf,keynew;
		BYTE keystr[68];
		BYTE vlenth=0;			//待鉴签数据长度包括遥控报文、安全数据头4字节 +安全数据区报文(L2-L3)
		int ret;
		BYTE pUserId[16];
		Cf=((sm2dat[0]>>2)&0x0f);		//功能号
		keyno=(sm2dat[0]&0x03);		//公钥号
		keynew=(sm2dat[1]&0x03);		//加密或更新的证书

		if(g_print_sys)
		{
			sprintf(sm2debugstr,"\r\n功能号=%d 公钥号=%d  更新号=%d\r\n",Cf,keyno,keynew);
			rt_printf(sm2debugstr);
		}
		
		readSM2key(keyno,keystr);

		if(Cf==1) //遥控报文，鉴签包括遥控数据(101报文)
		{
			for(i=0;i<(pt->recvbuf[1]+6);i++)
			{
				*pv++=pt->recvbuf[i];
				vlenth++;
	 		}			
		}
		for(i=0;i<4;i++)  // 安全报文头
		{
			*pv++=pd[i];
			vlenth++;
		}
		for(i=0;i<(byL2-byL3);i++)  // 安全数据报文
		{
			*pv++=sm2dat[i];
			vlenth++;
		}
		if(g_print_sys)
		{
			print_msg("对称加密报文:",sm2Verifydat,vlenth);
		}
	
			//rt_irq_save(flags);
		us0 = ustimer_get_origin();

		readUserId(pUserId);		
            ret=SM2_Verify(sm2Verifydat, vlenth,pUserId,16,(ECCrefPublicKey*)keystr,(ECCSignature *)&pd[byL2-byL3+4]);  //验签
		us = ustimer_get_duration(us0);
			//rt_irq_restore(flags);

		if(g_print_sys)
		{
			sprintf(sm2debugstr,"SM2_Verify程序运行时间:%dus.\r\n",us);
			rt_printf(sm2debugstr);
			sprintf(sm2debugstr,"SM2_Verify ret=%d\r\n",ret);
			rt_printf(sm2debugstr);
		}            	
             	
            	if(ret==0)  //鉴签成功
            	{

			switch(Cf)
			{
				case 1:			//Cf==1 控制命令
				{
					pt->bData=true;	//遥控报文验证成功，可转正常101规约数据处理

					if(g_print_sys)
					{
						sprintf(sm2debugstr,"SM2_Verify 成功,转遥控处理\r\n",ret);
						rt_printf(sm2debugstr);
					}
					break;
				}
				case 2:			//Cf==2  会话密钥协商			
				break;
				case 3:			//Cf==3  检查公钥
				{
					IEC101_SM2Echo(pt,sm2dat);	
					break;
				}
				case 4:			//Cf==4 更新公钥
				{
					for(i=0;i<68;i++)
					{
						keystr[i]=sm2dat[14+i];		//取得新公钥
					}
					if(g_print_sys)
					{

						sprintf(sm2debugstr,"新公钥%d:",keynew);
						print_msg(sm2debugstr,keystr,68);
					}					
					writeSM2key(keynew,keystr);  //保存新公钥
					IEC101_SM2Echo(pt,sm2dat);	
					break;
				}
				default:
				break;
			}
		}
	}
 }



static  void IEC104_SM2Echo(IEC104_DEF *pt,BYTE *dat)  // 报文应答cf=3 cf=4
{
	BYTE *pd=&pt->arrSendBuf[1];
	DWORD ltime;
	unsigned int outlen;
	BYTE keystr[68];  //
	BYTE datIn[32],pucrandom[32];  //
	
	BYTE sum=0;
	BYTE L2;
	int i;
	BYTE keynew;
	uint32_t us0,us;

	struct timespec ts;
//	struct rtc_time_t rtc;

	clk_time_get(&ts);
//	timespec_to_rtc(ts,&rtc,1);
	
	keynew=(dat[1]&0x03);		//加密或更新的证书
	
	L2=142;
	*pd++=0x16;
	*pd++=L2;
	*pd++=0x00;
	*pd++=0x16;
	*pd++=dat[0]; //功能码
	*pd++=dat[1]; //辅助状态
	*pd++=(BYTE)tRunPara.byAddr;       //装置地址 4字节
	*pd++=(BYTE)(tRunPara.byAddr>>8);
	*pd++=0; 
	*pd++=0; 

//	ltime=mktime_me(&rtc)-28800;   //北京东8区，减去8*3600秒
	ltime=ts.tv_sec-28800;   //北京东8区，减去8*3600秒
	
//	ltime=0xDF987C4E; //时间戳 测试用
	
	*pd++=(BYTE)ltime;       //时间戳
	*pd++=(BYTE)(ltime>>8);      
	*pd++=(BYTE)(ltime>>16);      
	*pd++=(BYTE)(ltime>>24);      

	*pd++=1;       			//公钥个数
	*pd++=0x00;
	*pd++=0x00;
	*pd++=0x00;
	

      memset(datIn,0,32);
      for(i=0;i<4;i++)
      {
		datIn[i]=dat[10+i];  //接收到的数据(4字节)
      }    
      
	SM2_GenerateRandom_me(32, pucrandom);   //随机变量
	readSM2key(keynew, keystr);			//key值


	us0 = ustimer_get_origin();
	SM2_Encrypt(datIn, 32, (ECCrefPublicKey*)keystr, pucrandom, 32, &EccMessage);	//非对称加密报文128个字节
	us = ustimer_get_duration(us0);
	if(g_print_sys)
	{
		sprintf(sm2debugstr,"SM2_Encrypt程序运行时间:%dus.\r\n",us);
		rt_printf(sm2debugstr);
	}

	memcpy(pd, EccMessage.x, 128);  // 非对称加密报文
	
	pd=&pt->arrSendBuf[5];           // 从功能码开始计算校验和
 	for(i = 0; i < L2; i++)		//  L2=0x8e 142个字节
	{
		sum +=  pd[i]; 
	}

 	for(i = 0; i < 14; i++)		//  
	{
		datIn[i]=  pd[i];  // 安全数据区数据，用做加密的输入数据
	}
  	encrypt_epri(datIn, 14, pd, &outlen, (sum|0xffffff00), (sum%3));	//报文对称加密,输出加密报文到发送缓冲区


	pd=&pt->arrSendBuf[L2+5];   //校验和位置       
	*pd++=sum;	
	*pd++=0x16;
	
	 pt->arrSendBuf[0]=L2+6;  //发送字节数
	if(g_print_104 && (g_print_port & (1<<pt->chnl)))
	{
		rt_printf("上送加密报文:");
		print_msg("TX_104:",&pt->arrSendBuf[1],L2+6);
	 }
	 IEC104_SM2Send(pt);
	
}

 void IEC104_SM2(IEC104_DEF* pt)
 {
	BYTE *pd=&pt->arrRecvBuf[256];
	BYTE *pv=sm2Verifydat;
	BYTE byL2,byL3,bySum;
	BYTE sum;
	DWORD sm2Addr,sm2Time,localTime,offTime;
	unsigned int lenth;
	int i;
	uint32_t us0,us;

	
	byL2=pd[1];
	byL3=pd[2];
	bySum=pd[byL2+4]; //校验和
	
	if(g_print_104 && (g_print_port & (1<<pt->chnl)))  
	{
		print_msg("SM_104:",pd,byL2+6);
	}

	if(g_print_sys)
	{
		sprintf(sm2debugstr,"L2=%02x  L3=%02x  bysum=%02x \r\n",byL2,byL3,bySum);
		rt_printf(sm2debugstr);
	}
	
	us0 = ustimer_get_origin();

	
	encrypt_epri(&pd[4], (byL2-byL3), sm2dat,&lenth,(bySum|0xffffff00),(bySum%3));  //解密安全数据区

	us = ustimer_get_duration(us0);
	if(g_print_sys)
	{
	
		sprintf(sm2debugstr,"程序运行时间:%dus.\r\n对称加密解密报文:",us);
		rt_printf(sm2debugstr);
		print_mem_net(NULL,sm2dat,byL2-byL3);
	}

	//校验和
	sum=0;
	for(i=0;i<(byL2-byL3);i++)
	{
		sum+=sm2dat[i];
	}
	for(i=0;i<byL3;i++)
	{
		sum+=pd[(byL2-byL3)+4+i];
	}
	if(g_print_sys)
	{
		sprintf(sm2debugstr,"\r\n校验和:sum=%02x  bySum=%02x\r\n",sum,bySum);
		rt_printf(sm2debugstr);
	}

	if(sum!=bySum)
	{

		return;	//校验和不相等
	}

	sm2Addr=sm2dat[2]+(sm2dat[3]<<8)+(sm2dat[4]<<16)+(sm2dat[5]<<24);  //装置地址

	if(g_print_sys)
	{
		sprintf(sm2debugstr,"\r\n地址:sm2Addr=%d  byAddr=%d\r\n",sm2Addr,tRunPara.byAddr);
		rt_printf(sm2debugstr);
	}

	
	if((tRunPara.byAddr!=(WORD)sm2Addr)&&(sm2Addr!=0xffffffff))
	{
		return; //不是发给本装置的数据
	}	
	sm2Time=sm2dat[6]+(sm2dat[7]<<8)+(sm2dat[8]<<16)+(sm2dat[9]<<24);  // 时间戳

	{
	struct timespec ts;
//	struct rtc_time_t rtc;

	clk_time_get(&ts);
//	timespec_to_rtc(ts,&rtc,1);

//	localTime=mktime_me(&rtc)-28800;   //北京东8区，减去8*3600秒
	localTime=ts.tv_sec-28800;   //北京东8区，减去8*3600秒
	}
	if(g_print_sys)
	{
		struct timespec ts;
		sprintf(sm2debugstr,"\r\n时间戳sm2=%d local=%d\r\n",sm2Time,localTime);
		rt_printf(sm2debugstr);
		
		ts.tv_nsec =0;
		ts.tv_sec = sm2Time += 28800;
		rt_printf("  sm2Time:");
		rt_printf_time2(ts);
		
		ts.tv_sec = localTime += 28800;
		rt_printf("localTime:");
		rt_printf_time2(ts);
	}

	// 证书有效时间判定
	{
		u8 no;

		no = (sm2dat[0]&0x03);		//公钥号
		if (x509_isvalid_time(no, localTime) != 0)
		{
			return;
		}
	}
	
	if(sm2Time>localTime)
	{
		offTime=sm2Time-localTime;
	}
	else
	{
		offTime=localTime-sm2Time;
	}
	
	if(offTime>tRunPara.dSM2Time)	//时间戳超时
	{

		if(g_print_sys)
		{
			rt_printf("时间戳无效\r\n");
		}
		 return;
	}
	
	if((sm2dat[0]&0x40)==0)	//主站下发数据
	{
		BYTE keyno,Cf,keynew;
		BYTE keystr[68];
		BYTE vlenth=0;			//待鉴签数据长度包括遥控报文、安全数据头4字节 +安全数据区报文(L2-L3)
		int ret;
		BYTE pUserId[16];
		Cf=((sm2dat[0]>>2)&0x0f);		//功能号
		keyno=(sm2dat[0]&0x03);		//公钥号
		keynew=(sm2dat[1]&0x03);		//加密或更新的证书

		if(g_print_sys)
		{
			sprintf(sm2debugstr,"\r\n功能号=%d 公钥号=%d  更新号=%d\r\n",Cf,keyno,keynew);
			rt_printf(sm2debugstr);
		}
		
		readSM2key(keyno,keystr);

		if(Cf==1) //遥控报文，鉴签包括遥控数据(101报文)
		{
			for(i=0;i<(pt->arrRecvBuf[1]+2);i++)
			{
				*pv++=pt->arrRecvBuf[i];
				vlenth++;
	 		}			
		}
		for(i=0;i<4;i++)  // 安全报文头
		{
			*pv++=pd[i];
			vlenth++;
		}
		for(i=0;i<(byL2-byL3);i++)  // 安全数据报文
		{
			*pv++=sm2dat[i];
			vlenth++;
		}
		if(g_print_sys)
		{
			print_msg("对称加密报文:",sm2Verifydat,vlenth);
		}
	
			//rt_irq_save(flags);
		us0 = ustimer_get_origin();

		readUserId(pUserId);		
            ret=SM2_Verify(sm2Verifydat, vlenth,pUserId,16,(ECCrefPublicKey*)keystr,(ECCSignature *)&pd[byL2-byL3+4]);  //验签
		us = ustimer_get_duration(us0);
			//rt_irq_restore(flags);

		if(g_print_sys)
		{
			sprintf(sm2debugstr,"SM2_Verify程序运行时间:%dus.\r\n",us);
			rt_printf(sm2debugstr);
			sprintf(sm2debugstr,"SM2_Verify ret=%d\r\n",ret);
			rt_printf(sm2debugstr);
		}            	
             	
            	if(ret==0)  //鉴签成功
            	{

			switch(Cf)
			{
				case 1:			//Cf==1 控制命令
				{
					pt->bRecvOk=true;	//遥控报文验证成功，可转正常104规约数据处理

					if(g_print_sys)
					{
						sprintf(sm2debugstr,"SM2_Verify 成功,转遥控处理\r\n",ret);
						rt_printf(sm2debugstr);
					}
					break;
				}
				case 2:			//Cf==2  会话密钥协商			
				break;
				case 3:			//Cf==3  检查公钥
				{
					IEC104_SM2Echo(pt,sm2dat);	
					break;
				}
				case 4:			//Cf==4 更新公钥
				{
					for(i=0;i<68;i++)
					{
						keystr[i]=sm2dat[14+i];		//取得新公钥
					}
					if(g_print_sys)
					{

						sprintf(sm2debugstr,"新公钥%d:",keynew);
						print_msg(sm2debugstr,keystr,68);
					}					
					writeSM2key(keynew,keystr);  //保存新公钥
					IEC104_SM2Echo(pt,sm2dat);	
					break;
				}
				default:
				break;
			}
		}
	}
 }



/***************下面为空函数**************************/

int SM2_GenerateRandom_me(unsigned int uiLength, unsigned char *pucRandom)
{
	int i;
	for(i=0;i<uiLength;i++)
	{
		pucRandom[i]=0;

	}
	pucRandom[0]=0x1f;
	pucRandom[1]=0xBB;
	pucRandom[2]=0x36;
	pucRandom[3]=0x82;
	return 0;

}

unsigned char  SM2TestYKOKFrame[256]={0x16,0x4A,0x40,0x16,0x3B,0x26,0x3E,0x3F,0x3F,0x26,0x2E,0x17,0x43,0x68,0xFB,0x7A,0x49,0x51,0x19,0x4E,0x34,0x06,0x78,0x02,0xC4,0x62,
0x32,0xF1,0x72,0x0A,0x34,0x7C,0x12,0x69,0x50,0x50,0x74,0x4C,0xC9,0xE1,0xA4,0xCD,0xAE,0x5D,0xF8,0x05,0x2F,0xA9,0x54,0xD2,0x99,0x73,
0x28,0x4A,0x23,0x85,0xEA,0x27,0xB4,0xC2,0x56,0x35,0xDE,0x74,0xD2,0xEE,0x92,0x8F,0x68,0xB1,0x61,0xAC,0xB3,0xEE,0xD5,0x5C,0xC3,0xD2,
0x9B,0x16};

unsigned char SM2Test104YKOKFrame[256]=
{
	0x16,0x4a,0x40,0x16,0x4e,0xbf,0x01,0x00,0xbf,0xbf,0x30,0xa8,0x69,0xee,0x75,0x2b,0xa3,0x7d,0x51,0x14,0x4b,0xc1,0x12,
	0x07,0x83,0x85,0x8f,0x00,0x91,0xed,0x3e,0xe6,0x17,0xd5,0x59,0x15,0x4d,0xd4,0x98,0x36,0x17,0x6f,0x85,0x29,0x41,0xa2, 
	0xc5,0xcb,0xac,0x37,0x4c,0x0f,0x7a,0xa9,0x6b,0x17,0x38,0xef,0x4f,0x92,0x7c,0x5d,0x52,0xc6,0x18,0x25,0x63,0x33,0x46,
	0xf4,0x48,0xf9,0x46,0x76,0xf1,0x19,0x80,0x59,0x40,0x16
};
unsigned char  SM2YKOKFrame[256]={0x68,0x0C,0x0C,0x68,0x53,0x01,0x00,0x2E,0x01,0x06,0x00,0x01,0x00,0x02,0x60,0x82,0x6E,0x16};
unsigned char  SM2YK104OKFrame[256]=
{
	0x68,0x0e,0x12,0x00,0xa0,0x00,0x2d,0x01,0x06,0x00,0x01,0x00,0x01,0x60,0x00,0x81
};

unsigned char  SM2TestYKERRFrame[256]={0x16,0x4A,0x40,0x16,0x33,0xC2,0x01,0x00,0xC2,0xC2,0xBA,0x28,0xBE,0x8C,0xAE,0x79,0x91,0xFE,0x21,0xFE,0x65,0xE4,0xBE,0x27,0xE1,
0xA0,0x5A,0x0A,0x53,0x86,0xC4,0x4A,0x53,0x33,0x36,0x16,0x10,0x4F,0x48,0xEA,0x24,0xF8,0x0B,0x7D,0x21,0x76,0x91,0x7A,0xCF,0x17,
0x8E,0x7C,0x8F,0x53,0x67,0xE7,0x61,0x73,0xE2,0xB6,0x9B,0xDE,0x6C,0xB2,0xB3,0x35,0xDD,0xF7,0x13,0x9B,0x99,0xC5,0x92,0xD1,0xF3,
0x2B,0xED,0xBB,0x3D,0x16};



unsigned char  SM2YKERRFrame[256]={0x68,0x0C,0x0C,0x68,0x53,0x01,0x00,0x2E,0x01,0x06,0x00,0x01,0x00,0x02,0x60,0x82,0x6E,0x16};
unsigned char  SM2YK104ERRFrame[256]={0x68, 0x0E, 0x1C, 0x00, 0x40, 0x00, 0x2D, 0x01, 0x06, 0x00, 0x01, 0x00, 0x01, 0x60, 0x00, 0x81};

unsigned char  SM2TestKeyFrame[256]={
0x16,0x4E,0x40,0x16,0x92,0x6E,0x01,0x00,0x6E,0x6E,0x5F,0x28,0x12,0x20,0x1F,0xBB,0x58,0xEC,0x6E,0x76,0xF3,0xBE,0x6A,0x54,
0x25,0x12,0xDE,0x78,0xAB,0x99,0xB3,0x54,0x57,0xED,0x4A,0x6B,0xD0,0xD4,0xE9,0x1E,0x80,0xDB,0xD7,0x9F,0x56,0x48,0xCB,0xBB,
0xC7,0x2D,0xB9,0x9B,0x74,0xAC,0xF0,0x8D,0xC8,0x36,0x5A,0xB1,0x70,0x6D,0xC8,0xFA,0xC6,0x39,0x5E,0x1D,0x57,0x32,0xB5,0x2F,
0xFE,0xBA,0x58,0xE5,0x45,0x99,0x87,0x2E,0x4F,0x91,0x91,0x16};

extern union u_RsIEC 	g_tRsIEC[CFG_UART_NUM_MAX];		// 串口规约共用结构buf区，目前有101 104规约

int stack_test(void)
{
	return 0;
}

int encrypt_test(void)
{
	IEC101_DEF *pt=(IEC101_DEF*)&g_tRsIEC;
	int i;
	tRunPara.byAddr=1;
	
	rt_printf("IEC101遥控测试 begin....\r\n");
	for(i=0;i<160;i++)
	{
		pt->recvbuf[256+i]=SM2TestYKOKFrame[i];
	}

	for(i=0;i<160;i++)
	{
		pt->recvbuf[i]=SM2YKOKFrame[i];
	}

#if 0
	{  //  //防止时间戳无效
		TIME ct;
//		struct timespec ts;
//		struct rtc_time_t rtc;
		ct.ms=44000;
		ct.min=43;
		ct.hour=16;
		ct.day=13;
		ct.month=7;
		ct.year=35;
		sys_time_set_rmt(&ct);
	}
#else
	{  //  //防止时间戳无效
		TIME ct;
//		struct timespec ts;
//		struct rtc_time_t rtc;
		ct.ms=2760;
		ct.min=32;
		ct.hour=14;
		ct.day=23;
		ct.month=9;
		ct.year=11;
		sys_time_set_rmt(&ct);
	}

#endif

	IEC101_SM2(pt);	

	rt_printf("遥控测试 end\r\n\r\n");
	rt_printf("\r\nIEC101遥控错误测试 begin....\r\n");
	for(i=0;i<160;i++)
	{
		pt->recvbuf[256+i]=SM2TestYKERRFrame[i];
	}

	for(i=0;i<160;i++)
	{
		pt->recvbuf[i]=SM2YKERRFrame[i];
	}

#if 0
	tSysTime.ms=2761; //防止时间戳无效
	tSysTime.min=32;
	tSysTime.hour=14;
	tSysTime.day=23;
	tSysTime.month=9;
	tSysTime.year=11;
#endif

	IEC101_SM2(pt);

	rt_printf("\r\n遥控错误测试 end\r\n");

	rt_printf("\r\nIEC101证书检查测试 begin....\r\n");
	for(i=0;i<160;i++)
	{
		pt->recvbuf[256+i]=SM2TestKeyFrame[i];
	}

#if 0
	tSysTime.ms=2762; //防止时间戳无效
	tSysTime.min=32;
	tSysTime.hour=14;
	tSysTime.day=23;
	tSysTime.month=9;
	tSysTime.year=11;
#endif

	IEC101_SM2(pt);
	rt_printf("\r\n证书检查测试 end\r\n");

/*********************下面是104加密测试******************************/
	{
		IEC104_DEF *pt104=(IEC104_DEF*)&g_t104[0];


		rt_printf("IEC104遥控测试 begin....\r\n");
		for(i=0;i<160;i++)
		{
			pt104->arrRecvBuf[256+i]=SM2Test104YKOKFrame[i];
		}

		for(i=0;i<160;i++)
		{
			pt104->arrRecvBuf[i]=SM2YK104OKFrame[i];
		}

		{  //  //防止时间戳无效
			TIME ct;
			ct.ms=16000;
			ct.min=04;
			ct.hour=19;
			ct.day=5;
			ct.month=7;
			ct.year=13;
			sys_time_set_rmt(&ct);
		}

		IEC104_SM2(pt104);	

		rt_printf("遥控测试 end\r\n\r\n");
		rt_printf("\r\nIEC104遥控错误测试 begin....\r\n");
		for(i=0;i<160;i++)
		{
			pt104->arrRecvBuf[256+i]=SM2TestYKERRFrame[i];
		}

		for(i=0;i<160;i++)
		{
			pt104->arrRecvBuf[i]=SM2YK104ERRFrame[i];
		}

#if 1
		{  //  //防止时间戳无效
			TIME ct;
			ct.ms=2761;
			ct.min=32;
			ct.hour=14;
			ct.day=23;
			ct.month=9;
			ct.year=11;
			sys_time_set_rmt(&ct);
		}
#endif

		IEC104_SM2(pt104);

		rt_printf("\r\n遥控错误测试 end\r\n");

		rt_printf("\r\nIEC104证书检查测试 begin....\r\n");
		for(i=0;i<160;i++)
		{
			pt104->arrRecvBuf[256+i]=SM2TestKeyFrame[i];
		}

#if 0
		tSysTime.ms=2762; //防止时间戳无效
		tSysTime.min=32;
		tSysTime.hour=14;
		tSysTime.day=23;
		tSysTime.month=9;
		tSysTime.year=11;
#endif

		IEC104_SM2(pt104);
		rt_printf("\r\n证书检查测试 end\r\n");

	}






	

	return 0;
}



#endif





