/******************************************************************************* 版权所有: 文件名称: 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 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; }