/*******************************************************************************
版权所有：	
文件名称：	sc1161y.c
文件版本：	01.01
创建作者:	xxxxxx
创建日期：	2016-10-23
功能说明：	sc1161y加密芯片驱动程序。
其它说明：
注意事项:
	芯片上电期间， SSN 引脚应维持高电平.SSN=0：将 SSN 置低； SSN=1：将 SSN 置高。
	Len1 代表长度的高字节， Len2 代表长度的低字节。
	LRC1 的计算方法：对 CLA INS P1 P2 Len1 Len2 DATA 数据，每个字节的异或值，再取反。
	LRC2 的计算方法：对 SW1 SW2 Len1 Len2 DATA 数据，每个字节的异或值，再取反。
	Len1 Len2 代表 DATA 域的长度，不包括 LRC1 或 LRC2。
	接口设备接收 BUSY 状态字的最长等待时间为 3s。
	严格按照流程中对 SSN 信号的处理方式，禁止在数据传输中，将 SSN 置高。
	SCK 推荐速率 5 MHz。(智芯确认SC1161Y最高25M)
	接口设备发送/接收数据完成后，建议在 10μ s 内将 SSN 置高。
	发送数据、接收数据字节间延时设为 1μ s。
	在市电供电的情况下，为了保证和主站会话通道的连续性，正常情况下不建议接口设备断电。
	在 SSN 置高后，将进入低功耗状态，高电平保持时间至少 10μ s 以上，才能置低。
	接口设备将 SSN 再次置低后，需等待 50μ s 以上时间，才能开始发送数据。

	1） 发送数据结构
	发送数据的结构为： 0x55 CLA INS P1 P2 Len1 Len2 DATA LRC1，其中：
		0x55 为发送命令结构的命令头；
		CLA 是命令类别；
		INS 是命令类别中的指令代码；
		P1、 P2 是一个完成指令代码的参考符号；
		Len1 Len2 是后续 DATA 的长度， 不包含 LRC1， 由两字节表示；
		DATA 是处理的数据输入；
		LRC1 是发送数据的校验值，计算方法见 SPI 通信流程说明。
	2） 接收数据结构
	接收数据的结构为： SW1 SW2 Len1 Len2 DATA LRC2，其中：
		SW1 SW2 是指令执行完毕后，从设备返回的状态字；
		Len1 Len2 是后续 DATA 的长度， 不包含 LRC2， 由两字节表示；
		DATA 是处理数据完毕后，返回的输出数据；
		LRC2 是接收数据的校验值，计算方法见 SPI 通信流程说明；
	3） 状态字节
		SW1、 SW2 构成结束序列，结束序列在命令的结尾指示芯片的状态。 
		SW1	SW2=‘9000’表示正常结束。

	注：接口设备在接收数据时， MOSI 引脚应始终保持低电平。

修改记录:
*/

#include "head.h"

u16 g_esam_errno;
u8 esam_buf[2048];

int OrderSearch(unsigned char *a,int n, unsigned char des) {
    int i;
    for (i = 0; i < n; i++)
        if (des == a[i])
            return i + 1;
    return 0;
}

u8 _esam_lrc(u8* buf0, u16 len0,u8* buf1,u16 len1)
{
	u8 lrc;
	u16 i;

	lrc = buf0[0];
	for(i=1; i<len0; i++)
	{
		lrc ^= buf0[i];
	}

	for(i=0; i<len1; i++)
	{
		lrc ^= buf1[i];

	}
	return ~lrc;
}

int _esam_cmd(u8* cmd,u16 cmd_len,u8 *in,u16 in_len,u8 *out,u16 out_len)
{
	u8 lrc,c,buf[5];
	int i,ret,len=0;
	uint64_t us0;
	u8 *pd = NULL;
	u16 index = 0;

	pd = esam_buf;

	//前导字节0X55
	*pd++ = 0x55;

	// 命令
	memcpy(pd,cmd,cmd_len);
	pd += cmd_len;

	// 数据
	memcpy(pd,in,in_len);
	pd += in_len;
	
	// 计算发送LRC
	lrc = _esam_lrc(cmd,cmd_len,in,in_len);
	*pd = lrc;

	len = (cmd_len + in_len + 2); // +2 -> 0x55 lrc
	dspi_esam_send(esam_buf,len);
	
	// 接收BUSY状态字，超时3S
	c = 0;
	len = 0;
	us0 = bsp_ustimer_get_origin(); 
	memset(esam_buf, 0, sizeof(esam_buf));
	while(bsp_ustimer_get_duration(us0) < 3*USTIMER_SEC)
	{
		dspi_esam_recv(esam_buf, sizeof(esam_buf));
		index = OrderSearch(esam_buf,sizeof(esam_buf),0x55);

		if(index != 0)
		{
			c = 0x55;
			break;
		}
	}

	//如果不成功，直接返回错误
	if(c != 0x55)
	{
		rt_printf("%s:接收BUSY状态字超时!\r\n",__FUNCTION__);
		ret = -11;
		goto LABEL_RET;
	}
	pd = &esam_buf[index];
	// 接收固定的4个字节，并检查状态字和长度
	if((pd[0] != 0x90) || (pd[1] != 0x00))
	{
		ret = -12;
		goto LABEL_RET;
	}
	len = (pd[2]<<8) + pd[3];

	if(len > out_len)
	{
		rt_printf("%s:输出缓冲空间不足，缓冲长度=%d,数据长度=%d.\r\n",__FUNCTION__,out_len,len);
		len = 0;
		ret = -13;
		goto LABEL_RET;
	}

	// 索引位置到buf结束，长度少于应接收报文长度( +4+1 -> CLA INS P1 P2 ... LRC)
	// 测试未出现这种情况，考虑到有概率还是增加此情况处理。
	if(len +4+1 > (sizeof(esam_buf) - index))
	{
		u16 cp_len = (sizeof(esam_buf) - index); //已接收长度
		rt_printf("%s 数据接收不完整,再次接收剩余报文，应接收长度:%d,已接收长度%d,剩余应接收长度:%d,index:%d\n",__FUNCTION__,len+4+1,cp_len,len+4+1-cp_len,index);

		memmove(esam_buf,&esam_buf[index],cp_len);
		dspi_esam_recv(&esam_buf[cp_len], sizeof(esam_buf)-cp_len);

		index = 0;
		pd = &esam_buf[index];
	}
	
	pd +=4;
	memcpy(out,pd,len);
	pd += len;

	// LRC2
	c = *pd;
	lrc = _esam_lrc(&esam_buf[index],4,out,len);
	if(c != lrc)
	{
		rt_printf("%s:接收=0x%02x,计算=0x%02x.\r\n",__FUNCTION__,c,lrc);
		ret = -14;
		goto LABEL_RET;
	}

	// 所有正常，返回输出BUF中的数据长度
	ret = len;

LABEL_RET:	

	if(g_print_sys || ret < 0)
	{
		print_mem("esam_cmd:",cmd,cmd_len);
		print_mem("esam_in :",in, in_len);
		print_mem("esam_out:",out,len);
	}
	
	if(ret >= 0)
	{
		g_esam_errno = 0x9000;
	}
	else if(ret == -12)
	{
		rt_printf("%s:返回状态字错误(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)c=%02x.\r\n",__FUNCTION__,pd[0],pd[1],pd[2],pd[3],pd[4],pd[5]);
		g_esam_errno = (pd[0]<<8) | pd[1];
	}
	else
	{
		g_esam_errno = ret;
	}

	return ret;
}


// 得到芯片序列号
int esam_get_sn(u8* out, u16 out_len)
{
	//发送：00b0990500020008
	//返回：9000+0008+ID
	u8 cmd[] = {0x00, 0xb0, 0x99, 0x05, 0x00, 0x02, 0x00, 0x08};

	// 检查参数
	if(out == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
}


// 得到密钥版本
int esam_get_version(u8* out, u16 out_len)
{
	//发送：801A00000000
	//返回：9000+0001+KeyVersion //Keyversion： 1 字节
	u8 cmd[] = {0x80, 0x1a, 0x00, 0x00, 0x00, 0x00};

	// 检查参数
	if(out == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
}


// 随机数产生
int esam_get_random(u8* out, u16 out_len)
{
	//发送：008400080000
	//返回：9000+0008+R3 //R3：终端随机数， 8 字节
	u8 cmd[] = {0x00, 0x84, 0x00, 0x08, 0x00, 0x00};//len高字节在前

	// 检查参数
	if(out == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
}


// 随机数签名
// 签名密钥标识： 固定为 01
int esam_sign_random(u8 *in,u16 in_len, u8* out, u16 out_len)
{
	//发送：801600800008+R1 //R1：网关或主站随机数， 8 字节
	//返回：9000+0048+R2+ Sign1 // R2：终端随机数， 8 字节，Sign1：签名结果， 64 字节
	u8 cmd[] = {0x80, 0x16, 0x00, 0x80, in_len>>8, in_len};

	// 检查参数
	if(out == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);
}

// 网关、主站签名验证
// 网关签名密钥索引： 0x05
// 主站的签名密钥索引取值范围： 0x01,0x02,0x03,0x04
int esam_sign_verify_zz(u8 key,u8 *in,u16 in_len)
{
	//发送：801800050040+ Sign2 //Sign2：签名结果， 64 字节
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x18, 0x00, key, in_len>>8, in_len};

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
}


// 遥控签名验证
int esam_sign_verify_yk(u8 key,u8 *in,u16 in_len)
{
	//发送：800800+asKID+Lc+TcsData + Date+StcsData //asKID：签名密钥索引。Lc：发送数据长度， 2 字节
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x08, 0x00, key, in_len>>8, in_len};

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
}


// 主站报文加密
int esam_encrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
{
	//发送：80266001+Lc+IVData+ Data 
	//		Lc：表示长度， 2 字节
	//		IVData：初始向量，随机数 R1+对 R1 按位取反， 16 字节
	//		Data： 数据域（应用类型、报文长度和报文内容）
	//返回：9000+Le+enData+MAC
	// 		Data：终端明文数据， enData：终端数据密文值， MAC： enData 的 MAC值
	u8 cmd[] = {0x80, 0x26, 0x60, 0x01, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);	
}


// 主站报文解密
int esam_decrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
{
	//发送：802C6001+Lc+IVData+enData+MAC
	//		Lc：表示长度， 2 字节
	//		IVData：初始向量，随机数 R1+对 R1 按位取反， 16 字节
	//返回：9000+Le+ Data 
	// 		Le：芯片返回数据长度，2 字节 Data：明文数据
	u8 cmd[] = {0x80, 0x2c, 0x60, 0x01, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);	
}


// 更新对称密钥
// 密钥版本大于 0 为更新：更新命令头： 801C00
// 密钥版本等于 0 为恢复：恢复命令头： 801C01
int esam_key_update(u8 key,u8 *in,u16 in_len)
{
	//发送：密钥更新或恢复命令头+asKID+Lc+newKeyVersion+UpdateKeyData+Skeydata
	//		newKeyVersion：密钥版本， 1字节
	//		UpdateKeyData：密钥数据，5*36 字节
	//		Skeydata：签名结果， 	64 字节
	//		asKID：签名密钥索引， 	1 字节
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x1c, 0x00, key, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	if(*in == 0)
	{
		cmd[2] = 0x01;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
}


// 终端主站证书、认证网关证书远程更新
//写入 CA 根证书(cer:0)
//写入  主站证书(cer:1~4)
//写入  网关证书(cer:5)
int esam_cer_zz_update( u8 cer,u8 *in,u16 in_len)
{
	//发送：8022+cerID+00+Lc+Cer
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x22, cer,0x00, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);	
}

// 终端证书远程下装
int esam_cer_zd_update(u8 *in,u16 in_len)
{
	//发送：80240000+Lc+Cer
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x24, 0x00,0x00, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);	
}

// 读取终端正式证书
int esam_cer_zd_get(u8 *out,u16 out_len)
{
	//发送：803001000000
	//返回：9000+Le+Cer//Le：表示长度， 2 个字节
	u8 cmd[] = {0x80, 0x30, 0x01,0x00, 0x00, 0x00};//len高字节在前

	// 检查参数
	if(out == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);	
}


// 读取终端测试证书长度
int esam_cer_zd_test_get_len(u8 *out,u16 out_len)
{
	//发送：00b0810000020002
	//返回：9000+ 0002+Len //Len：证书长度， 2 个字节
	u8 cmd[] = {0x00, 0xb0, 0x81, 0x00, 0x00, 0x02, 0x00,0x02};//len高字节在前

	// 检查参数
	if(out == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);	
}

// 读取终端测试证书
int esam_cer_zd_test_get(u16 cer_len,u8 *out,u16 out_len)
{
	//发送：00b081020002+Len
	//返回：9000+Le+Cer//Le：表示长度， 2 个字节
	u8 cmd[] = {0x00, 0xb0, 0x81, 0x02, 0x00, 0x02, cer_len>>8, cer_len};//len高字节在前


	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
}

// 以下为证书管理工具指令
// 验证证书管理工具证书的有效性
int esam_yw_cer_verify(u8 *in,u16 in_len)
{
	//发送：801E0000+Lc+Cer，Lc：表示长度， 2 字节
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x1e, 0x00,0x00, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);	
}


// 对证书请求文件进行签名
// 终端签名，运维工具验证正确性
int esam_yw_sign(u8 *in,u16 in_len,u8 *out,u16 out_len)
{
	//发送：800A0080+Lc+TotalReqData
	//返回：9000+0040+ SrReq
	// 		SrReq： TotalReqData 签名结果
	u8 cmd[] = {0x80, 0x0a, 0x00, 0x80, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);	
}


// 验证签名的正确性
// 运维工具签名，终端验证正确性
int esam_yw_sign_verify(u8 *in,u16 in_len)
{
	//发送：802000000040+Sr1
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x20, 0x00,0x00, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);	
}

// 获取终端安全芯片公钥
int esam_yw_get_pubkey(u8 *out,u16 out_len)
{
	//发送：803000000000
	//返回：9000+0040+pubKey
	u8 cmd[] = {0x80, 0x30, 0x00, 0x00, 0x00, 0x00};//len高字节在前

	// 检查参数
	if(out == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);	
}

// 运维加密
int esam_yw_encrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
{
	//发送：80266202+Lc+ID+R1+IVData+ Data 
	//		Lc：表示长度， 2 字节ID：证书管理工具 ID，8 字节；
	//		R1：随机数，身份认证时终端芯片产生的随机数， 8 字节
	//		IVData：初始向量，随机数 R1+对 R1 按位取反， 16 字节
	//		Data： 数据域（应用类型、报文长度和报文内容）
	//返回：9000+Le+enData+MAC
	// 		Data：终端明文数据， enData：终端数据密文值， MAC： enData 的 MAC值
	u8 cmd[] = {0x80, 0x26, 0x62, 0x02, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);	
}


// 运维解密
int esam_yw_decrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
{
	//发送：802C6202+Lc+ID+R1+IVData+enData+MAC
	//		Lc：表示长度， 2 字节ID：证书管理工具 ID，8 字节；
	//		R1：随机数，身份认证时终端芯片产生的随机数， 8 字节
	//		IVData：初始向量，随机数 R1+对 R1 按位取反， 16 字节
	//返回：9000+Le+ Data 
	// 		Le：芯片返回数据长度，2 字节 Data：明文数据
	u8 cmd[] = {0x80, 0x2c, 0x62, 0x02, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);	
}


// 恢复终端对称密钥
int esam_yw_key_restore(u8 *in,u16 in_len)
{
	//发送：801C0200+Lc+KeyData，Lc： 2 字节， KeyData 长度，KeyData：密钥恢复数据包
	//返回：9000+0000
	u8 cmd[] = {0x80, 0x1c, 0x02, 0x00, in_len>>8, in_len};//len高字节在前

	// 检查参数
	if(in == NULL)
	{
		return -1;
	}

	// 调用ESAM命令
	return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
}


int esam_init(void)
{

	int ret;
	u8 out;

	// 上电并延时1ms【放置到DSPI初始化之前】
//	GPIO_ESAM_POWER_INIT();
//	ustimer_delay(USTIMER_MS*10);

#ifndef ENCRYPT_CHNL_EN
	if(pRunSet->bTT_ESAM == 0)
#else
	if((pRunSet->bTT_ESAM_COM == 0)&&(pRunSet->bTT_ESAM_NET == 0))
#endif
	{
		return 0;
	}

	// 版本
	ret = esam_get_version(&out,1);
	if(ret < 0)
	{
		rt_printf("加密芯片检查失败!\n");

		rt_err_set(ERR_CODE_ESAM,0);
		
		return ret;
	}
	
	rt_printf("加密芯片检查通过!\n");
	return 0;
	
}


int esam_exit(void)
{
#if defined(CPU_MCF54418) // sunxi 20220628
	// 关闭电源，确保重启时有上电过程
	GPIO_ESAM_POWER_HIGH();
#endif // sunxi 20220628

	return 0;
}


u8  g_test_buf[1024];
u8 g_decrypt_data[] = 
{
	0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
	0x71,0x41,0xa3,0x9e,0x0e,0x58,0x54,0xe2,0x7c,0xce,0x04,0xc1,0x88,0xc8,0xc1,0x3c,
	0x2c,0x09,0x74,0x26,0x5b,0x8c,0x46,0x7d,0xa8,0x48,0x8e,0xf7,0x46,0x2a,0x45,0x98,
	0x7a,0xbe,0x8d,0x89,0xf2,0xf7,0x6f,0xcb,0x4c,0x86,0x5a,0x07,0xbb,0xe9,0x7c,0x67,
	0x67,0x90,0x17,0x81,0x47,0x7c,0x2d,0x88,0x0a,0xf6,0x60,0x2a,0x4d,0xeb,0x8f,0x80,
	0xda,0xb8,0x3d,0xec,0x52,0x1a,0xf0,0x75,0xc3,0xd7,0xc4,0x18,0x2e,0xcd,0x16,0x47,
	0x53,0xca,0x3c,0x55,0xe5,0xba,0x6d,0x0c,0x88,0x57,0xde,0x06,0x66,0x04,0xf6,0x6d,
	0xbe,0x7a,0xed,0x27
};

//esam_cmd:,0x80,0x16,0x00,0x80,0x00,0x08
u8 g_cmd00[] = 
{
0x52,0xe6,0x77,0xfc,0xaf,0x12,0x4b,0x91
};

//esam_cmd:,0x80,0x18,0x00,0x05,0x00,0x40
u8 g_cmd01[] = 
{
0x31,0xfd,0x52,0xf0,0x96,0x08,0xed,0xaf,0x3f,0x5b,0xa9,0x81,0x33,0xdc,0x0b,0xb4,
0x1e,0xd1,0x7e,0x71,0xc0,0x5f,0xb1,0x00,0xfe,0xaf,0x0e,0xdf,0xc7,0xf3,0x85,0xb5,
0x9a,0xb5,0xd4,0x47,0xe7,0xf0,0x1b,0x90,0xc1,0x0d,0x25,0x9a,0x90,0x4f,0xc5,0xe1,
0xb8,0x82,0x17,0x50,0x5a,0xc5,0x2f,0xa1,0xde,0x2b,0x79,0x0b,0x0c,0x29,0xa2,0x86,
};

//esam_cmd:,0x80,0x16,0x00,0x80,0x00,0x08
u8 g_cmd02[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7
};

//esam_cmd:,0x80,0x18,0x00,0x01,0x00,0x40
u8 g_cmd03[] = 
{
0x99,0x00,0x4d,0x4e,0x76,0xb4,0x2f,0x16,0xb9,0x80,0xc6,0x8f,0xc6,0xf9,0x1c,0xd0,
0x04,0x38,0x30,0xd6,0x3b,0xb5,0x5a,0xef,0x21,0xa5,0x15,0xc2,0x36,0xe0,0xd9,0xaa,
0x31,0x26,0x11,0x8e,0xa1,0x8c,0x3e,0x66,0x2a,0xd2,0x9e,0xc9,0x0a,0x8f,0x5d,0xab,
0x9a,0xaf,0x43,0x62,0xcb,0x12,0x3f,0xb9,0xe4,0xc3,0xab,0x3d,0x2d,0x54,0x4f,0xa7,
};

//esam_cmd:,0x00,0xb0,0x99,0x05,0x00,0x02,0x00,0x08
u8 g_cmd04[] = 
{
};


//esam_cmd:,0x80,0x1a,0x00,0x00,0x00,0x00
u8 g_cmd05[] = 
{
};


//esam_cmd:,0x00,0x84,0x00,0x08,0x00,0x00
u8 g_cmd06[] = 
{
};


//esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x24
u8 g_cmd07[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x00,0x10,0x68,0x0e,0x00,0x00,0x00,0x00,0x46,0x01,0x04,0x00,0x01,0x00,0x00,0x00,
0x00,0x02,0x00,0x00
};

//esam_cmd:,0x80,0x2c,0x60,0x01,0x00,0x34
u8 g_cmd08[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0xbb,0x0c,0xdb,0x0b,0x22,0x3a,0x4a,0x1e,0xc6,0xaf,0x92,0x40,0x40,0x41,0x76,0x82,
0x8c,0xa3,0xc5,0x6a,0x77,0xa0,0xb1,0xae,0x2b,0xeb,0xb1,0x78,0xca,0xbb,0x30,0x11,
0x90,0x74,0x5c,0x1f
};

//esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x24
u8 g_cmd09[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x00,0x10,0x68,0x0e,0x02,0x00,0x02,0x00,0x64,0x01,0x07,0x00,0x01,0x00,0x00,0x00,
0x00,0x14,0x00,0x00
};

//esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x8c
u8 g_cmd10[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x00,0x78,0x68,0x76,0x04,0x00,0x02,0x00,0x09,0xa3,0x14,0x00,0x01,0x00,0x01,0x40,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

//esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x41
u8 g_cmd11[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x00,0x2d,0x68,0x2b,0x06,0x00,0x02,0x00,0x01,0x9e,0x14,0x00,0x01,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
0x00
};

//esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x24
u8 g_cmd12[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x00,0x10,0x68,0x0e,0x08,0x00,0x02,0x00,0x64,0x01,0x0a,0x00,0x01,0x00,0x00,0x00,
0x00,0x14,0x00,0x00
};

//esam_cmd:,0x80,0x2c,0x60,0x01,0x00,0x34
u8 g_cmd13[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x17,0xdc,0xd8,0x09,0xa0,0x2a,0x72,0xad,0xfc,0x69,0xfd,0xc1,0xe6,0x35,0x7b,0x74,
0xc8,0x72,0xc6,0xca,0x18,0x06,0x30,0xf7,0x1f,0x52,0xe3,0xc2,0xb4,0x8a,0xb0,0xb8,
0x93,0x54,0x8d,0xd0
};

//esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x2a
u8 g_cmd14[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x00,0x16,0x68,0x14,0x0a,0x00,0x04,0x00,0x67,0x01,0x07,0x00,0x01,0x00,0x00,0x00,
0x00,0xee,0xc9,0x0c,0x11,0x15,0x05,0x11,0x00,0x00
};

//esam_cmd:,0x80,0x2c,0x60,0x01,0x00,0x74
u8 g_cmd15[] = 
{
0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
0x71,0x41,0xa3,0x9e,0x0e,0x58,0x54,0xe2,0x7c,0xce,0x04,0xc1,0x88,0xc8,0xc1,0x3c,
0x2c,0x09,0x74,0x26,0x5b,0x8c,0x46,0x7d,0xa8,0x48,0x8e,0xf7,0x46,0x2a,0x45,0x98,
0x7a,0xbe,0x8d,0x89,0xf2,0xf7,0x6f,0xcb,0x4c,0x86,0x5a,0x07,0xbb,0xe9,0x7c,0x67,
0x67,0x90,0x17,0x81,0x47,0x7c,0x2d,0x88,0x0a,0xf6,0x60,0x2a,0x4d,0xeb,0x8f,0x80,
0xda,0xb8,0x3d,0xec,0x52,0x1a,0xf0,0x75,0xc3,0xd7,0xc4,0x18,0x2e,0xcd,0x16,0x47,
0x53,0xca,0x3c,0x55,0xe5,0xba,0x6d,0x0c,0x88,0x57,0xde,0x06,0x66,0x04,0xf6,0x6d,
0xbe,0x7a,0xed,0x27
};
int esam_test(void)
{
	int ret;

#if 0
	// 加密
	ret = esam_encrypt(g_cmd07,sizeof(g_cmd07),g_test_buf,1024);
	rt_printf(" 加密[%d].\r\n\r\n",ret);
	
	// 加密
	ret = esam_decrypt(g_cmd08,sizeof(g_cmd08),g_test_buf,1024);
	rt_printf(" 加密[%d].\r\n\r\n",ret);
	// 加密
	ret = esam_encrypt(g_cmd09,sizeof(g_cmd09),g_test_buf,1024);
	rt_printf(" 加密[%d].\r\n\r\n",ret);
	// 加密
	ret = esam_encrypt(g_cmd10,sizeof(g_cmd10),g_test_buf,1024);
	rt_printf(" 加密[%d].\r\n\r\n",ret);


	// 加密
	ret = esam_encrypt(g_cmd11,sizeof(g_cmd11),g_test_buf,1024);
	rt_printf(" 加密[%d].\r\n\r\n",ret);
	// 加密
	ret = esam_encrypt(g_cmd12,sizeof(g_cmd12),g_test_buf,1024);
	rt_printf(" 加密[%d].\r\n\r\n",ret);


	// 对时解密
	ret = esam_decrypt(g_cmd13,sizeof(g_cmd13),g_test_buf,1024);
	rt_printf(" 解密[%d].\r\n\r\n",ret);

#endif

	// 对时加密
	ret = esam_encrypt(g_cmd14,sizeof(g_cmd14),g_test_buf,1024);
	rt_printf(" 加密[%d].\r\n\r\n",ret);
	
	// 遥控解密
	ret = esam_decrypt(g_cmd15,sizeof(g_cmd15),g_test_buf,1024);
	rt_printf(" 解密[%d].\r\n\r\n",ret);


	return 0;
}

int esam_info_printf(void)
{
	static int count=1;
	int ret;
	int i;
	static 	u8 in[256];
	static 	u8 out[128];
	s8 sz[64];
	u16 cer_len=0;
	int g_print_sys_old;

	g_print_sys_old = g_print_sys;
	g_print_sys = 1;
	rt_printf("esam info...\r\n");
	for(i=0;i<128;i++)
	{
		in[i] =i;
	}

	// 版本
	ret = esam_get_version(out,1);
	if(ret < 0)
	{
		rt_printf("检测不到加密芯片[%d]\r\n",ret);
		g_print_sys = g_print_sys_old;
		return -1;
	}
	rt_printf("版本[%d]:0x%02x.\r\n",ret,out[0]);

	// 序号
	for(i=0;i<1;i++)
	{
		ret = esam_get_sn(out,8);
		sprintf(sz,"%02d序号[%d]:",count,ret);
		print_mem(sz,out,8);
		if(ret < 0)
		{
			break;
		}
	}

	// 得到随机数
	ret = esam_get_random(out,8);
	rt_printf("随机数[%d].\r\n",ret);

	// 随机数签名
	ret = esam_sign_random(in,8,out,0x48);
	rt_printf("随机数签名[%d].\r\n",ret);

	// 终端公钥
	ret = esam_yw_get_pubkey(g_test_buf,1024);
	rt_printf("获取终端公钥[%d].\r\n",ret);


#if 0
	// 主站签名验证
	ret = esam_sign_verify_zz(1,in,64);
	rt_printf("主站签名验证[%d].\r\n",ret);
	
	// 规约签名验证
	ret = esam_sign_verify_yk(2,in,128);
	rt_printf("规约签名验证[%d].\r\n",ret);
	
	// 加密
	ret = esam_encrypt(in,65,out,128);
	rt_printf("加密[%d].\r\n",ret);

	// 解密
	ret = esam_decrypt(out,ret,in,128);
	rt_printf("解密[%d].\r\n",ret);


	// 读取终端测试证书长度
	ret = esam_cer_zd_test_get_len((u8*)&cer_len,2);
	rt_printf("读取终端测试证书长度[%d].\r\n",ret);

	// 读取终端测试证书
	ret = esam_cer_zd_test_get(cer_len,g_test_buf,1024);
	rt_printf("读取终端测试证书[%d].\r\n",ret);

#endif

	// 读取终端正式证书
	ret = esam_cer_zd_get(g_test_buf,1024);
	rt_printf("读取终端正式证书[%d].\r\n",ret);

	// 如果成功，将测试证书写入文件
	if(ret > 0)
	{
		loff_t pos;
		struct file * gfile;		
		gfile = rt_file_open("/tmp/zd_test.cer",O_CREAT|O_RDWR|O_TRUNC,0);
		if(IS_ERR(gfile))
		{
			g_print_sys = g_print_sys_old;
			return -1;
		}	
		pos = 0;
		rt_file_write(gfile,g_test_buf,ret,&pos);
		rt_file_close(gfile,NULL);

		rt_printf("证书输出路径:/tmp/zd_test.cer.\r\n");
		cer_len = ret;
	}

//	esam_test();

	// ret = esam_cer_zd_update(g_test_buf,cer_len);
	// rt_printf("更新终端正式证书[%d].\r\n",ret);

	g_print_sys = g_print_sys_old;
	return 0; 
}



