sc1161y.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  1. /*******************************************************************************
  2. 版权所有:
  3. 文件名称: sc1161y.c
  4. 文件版本: 01.01
  5. 创建作者: xxxxxx
  6. 创建日期: 2016-10-23
  7. 功能说明: sc1161y加密芯片驱动程序。
  8. 其它说明:
  9. 注意事项:
  10. 芯片上电期间, SSN 引脚应维持高电平.SSN=0:将 SSN 置低; SSN=1:将 SSN 置高。
  11. Len1 代表长度的高字节, Len2 代表长度的低字节。
  12. LRC1 的计算方法:对 CLA INS P1 P2 Len1 Len2 DATA 数据,每个字节的异或值,再取反。
  13. LRC2 的计算方法:对 SW1 SW2 Len1 Len2 DATA 数据,每个字节的异或值,再取反。
  14. Len1 Len2 代表 DATA 域的长度,不包括 LRC1 或 LRC2。
  15. 接口设备接收 BUSY 状态字的最长等待时间为 3s。
  16. 严格按照流程中对 SSN 信号的处理方式,禁止在数据传输中,将 SSN 置高。
  17. SCK 推荐速率 5 MHz。(智芯确认SC1161Y最高25M)
  18. 接口设备发送/接收数据完成后,建议在 10μ s 内将 SSN 置高。
  19. 发送数据、接收数据字节间延时设为 1μ s。
  20. 在市电供电的情况下,为了保证和主站会话通道的连续性,正常情况下不建议接口设备断电。
  21. 在 SSN 置高后,将进入低功耗状态,高电平保持时间至少 10μ s 以上,才能置低。
  22. 接口设备将 SSN 再次置低后,需等待 50μ s 以上时间,才能开始发送数据。
  23. 1) 发送数据结构
  24. 发送数据的结构为: 0x55 CLA INS P1 P2 Len1 Len2 DATA LRC1,其中:
  25. 0x55 为发送命令结构的命令头;
  26. CLA 是命令类别;
  27. INS 是命令类别中的指令代码;
  28. P1、 P2 是一个完成指令代码的参考符号;
  29. Len1 Len2 是后续 DATA 的长度, 不包含 LRC1, 由两字节表示;
  30. DATA 是处理的数据输入;
  31. LRC1 是发送数据的校验值,计算方法见 SPI 通信流程说明。
  32. 2) 接收数据结构
  33. 接收数据的结构为: SW1 SW2 Len1 Len2 DATA LRC2,其中:
  34. SW1 SW2 是指令执行完毕后,从设备返回的状态字;
  35. Len1 Len2 是后续 DATA 的长度, 不包含 LRC2, 由两字节表示;
  36. DATA 是处理数据完毕后,返回的输出数据;
  37. LRC2 是接收数据的校验值,计算方法见 SPI 通信流程说明;
  38. 3) 状态字节
  39. SW1、 SW2 构成结束序列,结束序列在命令的结尾指示芯片的状态。
  40. SW1 SW2=‘9000’表示正常结束。
  41. 注:接口设备在接收数据时, MOSI 引脚应始终保持低电平。
  42. 修改记录:
  43. */
  44. #include "head.h"
  45. u16 g_esam_errno;
  46. u8 esam_buf[2048];
  47. int OrderSearch(unsigned char *a,int n, unsigned char des) {
  48. int i;
  49. for (i = 0; i < n; i++)
  50. if (des == a[i])
  51. return i + 1;
  52. return 0;
  53. }
  54. u8 _esam_lrc(u8* buf0, u16 len0,u8* buf1,u16 len1)
  55. {
  56. u8 lrc;
  57. u16 i;
  58. lrc = buf0[0];
  59. for(i=1; i<len0; i++)
  60. {
  61. lrc ^= buf0[i];
  62. }
  63. for(i=0; i<len1; i++)
  64. {
  65. lrc ^= buf1[i];
  66. }
  67. return ~lrc;
  68. }
  69. int _esam_cmd(u8* cmd,u16 cmd_len,u8 *in,u16 in_len,u8 *out,u16 out_len)
  70. {
  71. u8 lrc,c,buf[5];
  72. int i,ret,len=0;
  73. uint64_t us0;
  74. u8 *pd = NULL;
  75. u16 index = 0;
  76. pd = esam_buf;
  77. //前导字节0X55
  78. *pd++ = 0x55;
  79. // 命令
  80. memcpy(pd,cmd,cmd_len);
  81. pd += cmd_len;
  82. // 数据
  83. memcpy(pd,in,in_len);
  84. pd += in_len;
  85. // 计算发送LRC
  86. lrc = _esam_lrc(cmd,cmd_len,in,in_len);
  87. *pd = lrc;
  88. len = (cmd_len + in_len + 2); // +2 -> 0x55 lrc
  89. dspi_esam_send(esam_buf,len);
  90. // 接收BUSY状态字,超时3S
  91. c = 0;
  92. len = 0;
  93. us0 = bsp_ustimer_get_origin();
  94. memset(esam_buf, 0, sizeof(esam_buf));
  95. while(bsp_ustimer_get_duration(us0) < 3*USTIMER_SEC)
  96. {
  97. dspi_esam_recv(esam_buf, sizeof(esam_buf));
  98. index = OrderSearch(esam_buf,sizeof(esam_buf),0x55);
  99. if(index != 0)
  100. {
  101. c = 0x55;
  102. break;
  103. }
  104. }
  105. //如果不成功,直接返回错误
  106. if(c != 0x55)
  107. {
  108. rt_printf("%s:接收BUSY状态字超时!\r\n",__FUNCTION__);
  109. ret = -11;
  110. goto LABEL_RET;
  111. }
  112. pd = &esam_buf[index];
  113. // 接收固定的4个字节,并检查状态字和长度
  114. if((pd[0] != 0x90) || (pd[1] != 0x00))
  115. {
  116. ret = -12;
  117. goto LABEL_RET;
  118. }
  119. len = (pd[2]<<8) + pd[3];
  120. if(len > out_len)
  121. {
  122. rt_printf("%s:输出缓冲空间不足,缓冲长度=%d,数据长度=%d.\r\n",__FUNCTION__,out_len,len);
  123. len = 0;
  124. ret = -13;
  125. goto LABEL_RET;
  126. }
  127. // 索引位置到buf结束,长度少于应接收报文长度( +4+1 -> CLA INS P1 P2 ... LRC)
  128. // 测试未出现这种情况,考虑到有概率还是增加此情况处理。
  129. if(len +4+1 > (sizeof(esam_buf) - index))
  130. {
  131. u16 cp_len = (sizeof(esam_buf) - index); //已接收长度
  132. rt_printf("%s 数据接收不完整,再次接收剩余报文,应接收长度:%d,已接收长度%d,剩余应接收长度:%d,index:%d\n",__FUNCTION__,len+4+1,cp_len,len+4+1-cp_len,index);
  133. memmove(esam_buf,&esam_buf[index],cp_len);
  134. dspi_esam_recv(&esam_buf[cp_len], sizeof(esam_buf)-cp_len);
  135. index = 0;
  136. pd = &esam_buf[index];
  137. }
  138. pd +=4;
  139. memcpy(out,pd,len);
  140. pd += len;
  141. // LRC2
  142. c = *pd;
  143. lrc = _esam_lrc(&esam_buf[index],4,out,len);
  144. if(c != lrc)
  145. {
  146. rt_printf("%s:接收=0x%02x,计算=0x%02x.\r\n",__FUNCTION__,c,lrc);
  147. ret = -14;
  148. goto LABEL_RET;
  149. }
  150. // 所有正常,返回输出BUF中的数据长度
  151. ret = len;
  152. LABEL_RET:
  153. if(g_print_sys || ret < 0)
  154. {
  155. print_mem("esam_cmd:",cmd,cmd_len);
  156. print_mem("esam_in :",in, in_len);
  157. print_mem("esam_out:",out,len);
  158. }
  159. if(ret >= 0)
  160. {
  161. g_esam_errno = 0x9000;
  162. }
  163. else if(ret == -12)
  164. {
  165. 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]);
  166. g_esam_errno = (pd[0]<<8) | pd[1];
  167. }
  168. else
  169. {
  170. g_esam_errno = ret;
  171. }
  172. return ret;
  173. }
  174. // 得到芯片序列号
  175. int esam_get_sn(u8* out, u16 out_len)
  176. {
  177. //发送:00b0990500020008
  178. //返回:9000+0008+ID
  179. u8 cmd[] = {0x00, 0xb0, 0x99, 0x05, 0x00, 0x02, 0x00, 0x08};
  180. // 检查参数
  181. if(out == NULL)
  182. {
  183. return -1;
  184. }
  185. // 调用ESAM命令
  186. return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
  187. }
  188. // 得到密钥版本
  189. int esam_get_version(u8* out, u16 out_len)
  190. {
  191. //发送:801A00000000
  192. //返回:9000+0001+KeyVersion //Keyversion: 1 字节
  193. u8 cmd[] = {0x80, 0x1a, 0x00, 0x00, 0x00, 0x00};
  194. // 检查参数
  195. if(out == NULL)
  196. {
  197. return -1;
  198. }
  199. // 调用ESAM命令
  200. return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
  201. }
  202. // 随机数产生
  203. int esam_get_random(u8* out, u16 out_len)
  204. {
  205. //发送:008400080000
  206. //返回:9000+0008+R3 //R3:终端随机数, 8 字节
  207. u8 cmd[] = {0x00, 0x84, 0x00, 0x08, 0x00, 0x00};//len高字节在前
  208. // 检查参数
  209. if(out == NULL)
  210. {
  211. return -1;
  212. }
  213. // 调用ESAM命令
  214. return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
  215. }
  216. // 随机数签名
  217. // 签名密钥标识: 固定为 01
  218. int esam_sign_random(u8 *in,u16 in_len, u8* out, u16 out_len)
  219. {
  220. //发送:801600800008+R1 //R1:网关或主站随机数, 8 字节
  221. //返回:9000+0048+R2+ Sign1 // R2:终端随机数, 8 字节,Sign1:签名结果, 64 字节
  222. u8 cmd[] = {0x80, 0x16, 0x00, 0x80, in_len>>8, in_len};
  223. // 检查参数
  224. if(out == NULL)
  225. {
  226. return -1;
  227. }
  228. // 调用ESAM命令
  229. return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);
  230. }
  231. // 网关、主站签名验证
  232. // 网关签名密钥索引: 0x05
  233. // 主站的签名密钥索引取值范围: 0x01,0x02,0x03,0x04
  234. int esam_sign_verify_zz(u8 key,u8 *in,u16 in_len)
  235. {
  236. //发送:801800050040+ Sign2 //Sign2:签名结果, 64 字节
  237. //返回:9000+0000
  238. u8 cmd[] = {0x80, 0x18, 0x00, key, in_len>>8, in_len};
  239. // 检查参数
  240. if(in == NULL)
  241. {
  242. return -1;
  243. }
  244. // 调用ESAM命令
  245. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  246. }
  247. // 遥控签名验证
  248. int esam_sign_verify_yk(u8 key,u8 *in,u16 in_len)
  249. {
  250. //发送:800800+asKID+Lc+TcsData + Date+StcsData //asKID:签名密钥索引。Lc:发送数据长度, 2 字节
  251. //返回:9000+0000
  252. u8 cmd[] = {0x80, 0x08, 0x00, key, in_len>>8, in_len};
  253. // 检查参数
  254. if(in == NULL)
  255. {
  256. return -1;
  257. }
  258. // 调用ESAM命令
  259. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  260. }
  261. // 主站报文加密
  262. int esam_encrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
  263. {
  264. //发送:80266001+Lc+IVData+ Data
  265. // Lc:表示长度, 2 字节
  266. // IVData:初始向量,随机数 R1+对 R1 按位取反, 16 字节
  267. // Data: 数据域(应用类型、报文长度和报文内容)
  268. //返回:9000+Le+enData+MAC
  269. // Data:终端明文数据, enData:终端数据密文值, MAC: enData 的 MAC值
  270. u8 cmd[] = {0x80, 0x26, 0x60, 0x01, in_len>>8, in_len};//len高字节在前
  271. // 检查参数
  272. if(in == NULL)
  273. {
  274. return -1;
  275. }
  276. // 调用ESAM命令
  277. return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);
  278. }
  279. // 主站报文解密
  280. int esam_decrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
  281. {
  282. //发送:802C6001+Lc+IVData+enData+MAC
  283. // Lc:表示长度, 2 字节
  284. // IVData:初始向量,随机数 R1+对 R1 按位取反, 16 字节
  285. //返回:9000+Le+ Data
  286. // Le:芯片返回数据长度,2 字节 Data:明文数据
  287. u8 cmd[] = {0x80, 0x2c, 0x60, 0x01, in_len>>8, in_len};//len高字节在前
  288. // 检查参数
  289. if(in == NULL)
  290. {
  291. return -1;
  292. }
  293. // 调用ESAM命令
  294. return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);
  295. }
  296. // 更新对称密钥
  297. // 密钥版本大于 0 为更新:更新命令头: 801C00
  298. // 密钥版本等于 0 为恢复:恢复命令头: 801C01
  299. int esam_key_update(u8 key,u8 *in,u16 in_len)
  300. {
  301. //发送:密钥更新或恢复命令头+asKID+Lc+newKeyVersion+UpdateKeyData+Skeydata
  302. // newKeyVersion:密钥版本, 1字节
  303. // UpdateKeyData:密钥数据,5*36 字节
  304. // Skeydata:签名结果, 64 字节
  305. // asKID:签名密钥索引, 1 字节
  306. //返回:9000+0000
  307. u8 cmd[] = {0x80, 0x1c, 0x00, key, in_len>>8, in_len};//len高字节在前
  308. // 检查参数
  309. if(in == NULL)
  310. {
  311. return -1;
  312. }
  313. if(*in == 0)
  314. {
  315. cmd[2] = 0x01;
  316. }
  317. // 调用ESAM命令
  318. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  319. }
  320. // 终端主站证书、认证网关证书远程更新
  321. //写入 CA 根证书(cer:0)
  322. //写入 主站证书(cer:1~4)
  323. //写入 网关证书(cer:5)
  324. int esam_cer_zz_update( u8 cer,u8 *in,u16 in_len)
  325. {
  326. //发送:8022+cerID+00+Lc+Cer
  327. //返回:9000+0000
  328. u8 cmd[] = {0x80, 0x22, cer,0x00, in_len>>8, in_len};//len高字节在前
  329. // 检查参数
  330. if(in == NULL)
  331. {
  332. return -1;
  333. }
  334. // 调用ESAM命令
  335. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  336. }
  337. // 终端证书远程下装
  338. int esam_cer_zd_update(u8 *in,u16 in_len)
  339. {
  340. //发送:80240000+Lc+Cer
  341. //返回:9000+0000
  342. u8 cmd[] = {0x80, 0x24, 0x00,0x00, in_len>>8, in_len};//len高字节在前
  343. // 检查参数
  344. if(in == NULL)
  345. {
  346. return -1;
  347. }
  348. // 调用ESAM命令
  349. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  350. }
  351. // 读取终端正式证书
  352. int esam_cer_zd_get(u8 *out,u16 out_len)
  353. {
  354. //发送:803001000000
  355. //返回:9000+Le+Cer//Le:表示长度, 2 个字节
  356. u8 cmd[] = {0x80, 0x30, 0x01,0x00, 0x00, 0x00};//len高字节在前
  357. // 检查参数
  358. if(out == NULL)
  359. {
  360. return -1;
  361. }
  362. // 调用ESAM命令
  363. return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
  364. }
  365. // 读取终端测试证书长度
  366. int esam_cer_zd_test_get_len(u8 *out,u16 out_len)
  367. {
  368. //发送:00b0810000020002
  369. //返回:9000+ 0002+Len //Len:证书长度, 2 个字节
  370. u8 cmd[] = {0x00, 0xb0, 0x81, 0x00, 0x00, 0x02, 0x00,0x02};//len高字节在前
  371. // 检查参数
  372. if(out == NULL)
  373. {
  374. return -1;
  375. }
  376. // 调用ESAM命令
  377. return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
  378. }
  379. // 读取终端测试证书
  380. int esam_cer_zd_test_get(u16 cer_len,u8 *out,u16 out_len)
  381. {
  382. //发送:00b081020002+Len
  383. //返回:9000+Le+Cer//Le:表示长度, 2 个字节
  384. u8 cmd[] = {0x00, 0xb0, 0x81, 0x02, 0x00, 0x02, cer_len>>8, cer_len};//len高字节在前
  385. // 调用ESAM命令
  386. return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
  387. }
  388. // 以下为证书管理工具指令
  389. // 验证证书管理工具证书的有效性
  390. int esam_yw_cer_verify(u8 *in,u16 in_len)
  391. {
  392. //发送:801E0000+Lc+Cer,Lc:表示长度, 2 字节
  393. //返回:9000+0000
  394. u8 cmd[] = {0x80, 0x1e, 0x00,0x00, in_len>>8, in_len};//len高字节在前
  395. // 检查参数
  396. if(in == NULL)
  397. {
  398. return -1;
  399. }
  400. // 调用ESAM命令
  401. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  402. }
  403. // 对证书请求文件进行签名
  404. // 终端签名,运维工具验证正确性
  405. int esam_yw_sign(u8 *in,u16 in_len,u8 *out,u16 out_len)
  406. {
  407. //发送:800A0080+Lc+TotalReqData
  408. //返回:9000+0040+ SrReq
  409. // SrReq: TotalReqData 签名结果
  410. u8 cmd[] = {0x80, 0x0a, 0x00, 0x80, in_len>>8, in_len};//len高字节在前
  411. // 检查参数
  412. if(in == NULL)
  413. {
  414. return -1;
  415. }
  416. // 调用ESAM命令
  417. return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);
  418. }
  419. // 验证签名的正确性
  420. // 运维工具签名,终端验证正确性
  421. int esam_yw_sign_verify(u8 *in,u16 in_len)
  422. {
  423. //发送:802000000040+Sr1
  424. //返回:9000+0000
  425. u8 cmd[] = {0x80, 0x20, 0x00,0x00, in_len>>8, in_len};//len高字节在前
  426. // 检查参数
  427. if(in == NULL)
  428. {
  429. return -1;
  430. }
  431. // 调用ESAM命令
  432. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  433. }
  434. // 获取终端安全芯片公钥
  435. int esam_yw_get_pubkey(u8 *out,u16 out_len)
  436. {
  437. //发送:803000000000
  438. //返回:9000+0040+pubKey
  439. u8 cmd[] = {0x80, 0x30, 0x00, 0x00, 0x00, 0x00};//len高字节在前
  440. // 检查参数
  441. if(out == NULL)
  442. {
  443. return -1;
  444. }
  445. // 调用ESAM命令
  446. return _esam_cmd(cmd,sizeof(cmd),0,0,out,out_len);
  447. }
  448. // 运维加密
  449. int esam_yw_encrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
  450. {
  451. //发送:80266202+Lc+ID+R1+IVData+ Data
  452. // Lc:表示长度, 2 字节ID:证书管理工具 ID,8 字节;
  453. // R1:随机数,身份认证时终端芯片产生的随机数, 8 字节
  454. // IVData:初始向量,随机数 R1+对 R1 按位取反, 16 字节
  455. // Data: 数据域(应用类型、报文长度和报文内容)
  456. //返回:9000+Le+enData+MAC
  457. // Data:终端明文数据, enData:终端数据密文值, MAC: enData 的 MAC值
  458. u8 cmd[] = {0x80, 0x26, 0x62, 0x02, in_len>>8, in_len};//len高字节在前
  459. // 检查参数
  460. if(in == NULL)
  461. {
  462. return -1;
  463. }
  464. // 调用ESAM命令
  465. return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);
  466. }
  467. // 运维解密
  468. int esam_yw_decrypt(u8 *in,u16 in_len,u8 *out,u16 out_len)
  469. {
  470. //发送:802C6202+Lc+ID+R1+IVData+enData+MAC
  471. // Lc:表示长度, 2 字节ID:证书管理工具 ID,8 字节;
  472. // R1:随机数,身份认证时终端芯片产生的随机数, 8 字节
  473. // IVData:初始向量,随机数 R1+对 R1 按位取反, 16 字节
  474. //返回:9000+Le+ Data
  475. // Le:芯片返回数据长度,2 字节 Data:明文数据
  476. u8 cmd[] = {0x80, 0x2c, 0x62, 0x02, in_len>>8, in_len};//len高字节在前
  477. // 检查参数
  478. if(in == NULL)
  479. {
  480. return -1;
  481. }
  482. // 调用ESAM命令
  483. return _esam_cmd(cmd,sizeof(cmd),in,in_len,out,out_len);
  484. }
  485. // 恢复终端对称密钥
  486. int esam_yw_key_restore(u8 *in,u16 in_len)
  487. {
  488. //发送:801C0200+Lc+KeyData,Lc: 2 字节, KeyData 长度,KeyData:密钥恢复数据包
  489. //返回:9000+0000
  490. u8 cmd[] = {0x80, 0x1c, 0x02, 0x00, in_len>>8, in_len};//len高字节在前
  491. // 检查参数
  492. if(in == NULL)
  493. {
  494. return -1;
  495. }
  496. // 调用ESAM命令
  497. return _esam_cmd(cmd,sizeof(cmd),in,in_len,0,0);
  498. }
  499. int esam_init(void)
  500. {
  501. int ret;
  502. u8 out;
  503. // 上电并延时1ms【放置到DSPI初始化之前】
  504. // GPIO_ESAM_POWER_INIT();
  505. // ustimer_delay(USTIMER_MS*10);
  506. #ifndef ENCRYPT_CHNL_EN
  507. if(pRunSet->bTT_ESAM == 0)
  508. #else
  509. if((pRunSet->bTT_ESAM_COM == 0)&&(pRunSet->bTT_ESAM_NET == 0))
  510. #endif
  511. {
  512. return 0;
  513. }
  514. // 版本
  515. ret = esam_get_version(&out,1);
  516. if(ret < 0)
  517. {
  518. rt_printf("加密芯片检查失败!\n");
  519. rt_err_set(ERR_CODE_ESAM,0);
  520. return ret;
  521. }
  522. rt_printf("加密芯片检查通过!\n");
  523. return 0;
  524. }
  525. int esam_exit(void)
  526. {
  527. #if defined(CPU_MCF54418) // sunxi 20220628
  528. // 关闭电源,确保重启时有上电过程
  529. GPIO_ESAM_POWER_HIGH();
  530. #endif // sunxi 20220628
  531. return 0;
  532. }
  533. u8 g_test_buf[1024];
  534. u8 g_decrypt_data[] =
  535. {
  536. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  537. 0x71,0x41,0xa3,0x9e,0x0e,0x58,0x54,0xe2,0x7c,0xce,0x04,0xc1,0x88,0xc8,0xc1,0x3c,
  538. 0x2c,0x09,0x74,0x26,0x5b,0x8c,0x46,0x7d,0xa8,0x48,0x8e,0xf7,0x46,0x2a,0x45,0x98,
  539. 0x7a,0xbe,0x8d,0x89,0xf2,0xf7,0x6f,0xcb,0x4c,0x86,0x5a,0x07,0xbb,0xe9,0x7c,0x67,
  540. 0x67,0x90,0x17,0x81,0x47,0x7c,0x2d,0x88,0x0a,0xf6,0x60,0x2a,0x4d,0xeb,0x8f,0x80,
  541. 0xda,0xb8,0x3d,0xec,0x52,0x1a,0xf0,0x75,0xc3,0xd7,0xc4,0x18,0x2e,0xcd,0x16,0x47,
  542. 0x53,0xca,0x3c,0x55,0xe5,0xba,0x6d,0x0c,0x88,0x57,0xde,0x06,0x66,0x04,0xf6,0x6d,
  543. 0xbe,0x7a,0xed,0x27
  544. };
  545. //esam_cmd:,0x80,0x16,0x00,0x80,0x00,0x08
  546. u8 g_cmd00[] =
  547. {
  548. 0x52,0xe6,0x77,0xfc,0xaf,0x12,0x4b,0x91
  549. };
  550. //esam_cmd:,0x80,0x18,0x00,0x05,0x00,0x40
  551. u8 g_cmd01[] =
  552. {
  553. 0x31,0xfd,0x52,0xf0,0x96,0x08,0xed,0xaf,0x3f,0x5b,0xa9,0x81,0x33,0xdc,0x0b,0xb4,
  554. 0x1e,0xd1,0x7e,0x71,0xc0,0x5f,0xb1,0x00,0xfe,0xaf,0x0e,0xdf,0xc7,0xf3,0x85,0xb5,
  555. 0x9a,0xb5,0xd4,0x47,0xe7,0xf0,0x1b,0x90,0xc1,0x0d,0x25,0x9a,0x90,0x4f,0xc5,0xe1,
  556. 0xb8,0x82,0x17,0x50,0x5a,0xc5,0x2f,0xa1,0xde,0x2b,0x79,0x0b,0x0c,0x29,0xa2,0x86,
  557. };
  558. //esam_cmd:,0x80,0x16,0x00,0x80,0x00,0x08
  559. u8 g_cmd02[] =
  560. {
  561. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7
  562. };
  563. //esam_cmd:,0x80,0x18,0x00,0x01,0x00,0x40
  564. u8 g_cmd03[] =
  565. {
  566. 0x99,0x00,0x4d,0x4e,0x76,0xb4,0x2f,0x16,0xb9,0x80,0xc6,0x8f,0xc6,0xf9,0x1c,0xd0,
  567. 0x04,0x38,0x30,0xd6,0x3b,0xb5,0x5a,0xef,0x21,0xa5,0x15,0xc2,0x36,0xe0,0xd9,0xaa,
  568. 0x31,0x26,0x11,0x8e,0xa1,0x8c,0x3e,0x66,0x2a,0xd2,0x9e,0xc9,0x0a,0x8f,0x5d,0xab,
  569. 0x9a,0xaf,0x43,0x62,0xcb,0x12,0x3f,0xb9,0xe4,0xc3,0xab,0x3d,0x2d,0x54,0x4f,0xa7,
  570. };
  571. //esam_cmd:,0x00,0xb0,0x99,0x05,0x00,0x02,0x00,0x08
  572. u8 g_cmd04[] =
  573. {
  574. };
  575. //esam_cmd:,0x80,0x1a,0x00,0x00,0x00,0x00
  576. u8 g_cmd05[] =
  577. {
  578. };
  579. //esam_cmd:,0x00,0x84,0x00,0x08,0x00,0x00
  580. u8 g_cmd06[] =
  581. {
  582. };
  583. //esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x24
  584. u8 g_cmd07[] =
  585. {
  586. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  587. 0x00,0x10,0x68,0x0e,0x00,0x00,0x00,0x00,0x46,0x01,0x04,0x00,0x01,0x00,0x00,0x00,
  588. 0x00,0x02,0x00,0x00
  589. };
  590. //esam_cmd:,0x80,0x2c,0x60,0x01,0x00,0x34
  591. u8 g_cmd08[] =
  592. {
  593. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  594. 0xbb,0x0c,0xdb,0x0b,0x22,0x3a,0x4a,0x1e,0xc6,0xaf,0x92,0x40,0x40,0x41,0x76,0x82,
  595. 0x8c,0xa3,0xc5,0x6a,0x77,0xa0,0xb1,0xae,0x2b,0xeb,0xb1,0x78,0xca,0xbb,0x30,0x11,
  596. 0x90,0x74,0x5c,0x1f
  597. };
  598. //esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x24
  599. u8 g_cmd09[] =
  600. {
  601. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  602. 0x00,0x10,0x68,0x0e,0x02,0x00,0x02,0x00,0x64,0x01,0x07,0x00,0x01,0x00,0x00,0x00,
  603. 0x00,0x14,0x00,0x00
  604. };
  605. //esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x8c
  606. u8 g_cmd10[] =
  607. {
  608. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  609. 0x00,0x78,0x68,0x76,0x04,0x00,0x02,0x00,0x09,0xa3,0x14,0x00,0x01,0x00,0x01,0x40,
  610. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  611. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,
  612. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  613. 0x00,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  614. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
  615. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,
  616. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
  617. };
  618. //esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x41
  619. u8 g_cmd11[] =
  620. {
  621. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  622. 0x00,0x2d,0x68,0x2b,0x06,0x00,0x02,0x00,0x01,0x9e,0x14,0x00,0x01,0x00,0x01,0x00,
  623. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  624. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
  625. 0x00
  626. };
  627. //esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x24
  628. u8 g_cmd12[] =
  629. {
  630. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  631. 0x00,0x10,0x68,0x0e,0x08,0x00,0x02,0x00,0x64,0x01,0x0a,0x00,0x01,0x00,0x00,0x00,
  632. 0x00,0x14,0x00,0x00
  633. };
  634. //esam_cmd:,0x80,0x2c,0x60,0x01,0x00,0x34
  635. u8 g_cmd13[] =
  636. {
  637. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  638. 0x17,0xdc,0xd8,0x09,0xa0,0x2a,0x72,0xad,0xfc,0x69,0xfd,0xc1,0xe6,0x35,0x7b,0x74,
  639. 0xc8,0x72,0xc6,0xca,0x18,0x06,0x30,0xf7,0x1f,0x52,0xe3,0xc2,0xb4,0x8a,0xb0,0xb8,
  640. 0x93,0x54,0x8d,0xd0
  641. };
  642. //esam_cmd:,0x80,0x26,0x60,0x01,0x00,0x2a
  643. u8 g_cmd14[] =
  644. {
  645. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  646. 0x00,0x16,0x68,0x14,0x0a,0x00,0x04,0x00,0x67,0x01,0x07,0x00,0x01,0x00,0x00,0x00,
  647. 0x00,0xee,0xc9,0x0c,0x11,0x15,0x05,0x11,0x00,0x00
  648. };
  649. //esam_cmd:,0x80,0x2c,0x60,0x01,0x00,0x74
  650. u8 g_cmd15[] =
  651. {
  652. 0x64,0x50,0x82,0x18,0xc7,0xf4,0x3d,0xa7,0x9b,0xaf,0x7d,0xe7,0x38,0x0b,0xc2,0x58,
  653. 0x71,0x41,0xa3,0x9e,0x0e,0x58,0x54,0xe2,0x7c,0xce,0x04,0xc1,0x88,0xc8,0xc1,0x3c,
  654. 0x2c,0x09,0x74,0x26,0x5b,0x8c,0x46,0x7d,0xa8,0x48,0x8e,0xf7,0x46,0x2a,0x45,0x98,
  655. 0x7a,0xbe,0x8d,0x89,0xf2,0xf7,0x6f,0xcb,0x4c,0x86,0x5a,0x07,0xbb,0xe9,0x7c,0x67,
  656. 0x67,0x90,0x17,0x81,0x47,0x7c,0x2d,0x88,0x0a,0xf6,0x60,0x2a,0x4d,0xeb,0x8f,0x80,
  657. 0xda,0xb8,0x3d,0xec,0x52,0x1a,0xf0,0x75,0xc3,0xd7,0xc4,0x18,0x2e,0xcd,0x16,0x47,
  658. 0x53,0xca,0x3c,0x55,0xe5,0xba,0x6d,0x0c,0x88,0x57,0xde,0x06,0x66,0x04,0xf6,0x6d,
  659. 0xbe,0x7a,0xed,0x27
  660. };
  661. int esam_test(void)
  662. {
  663. int ret;
  664. #if 0
  665. // 加密
  666. ret = esam_encrypt(g_cmd07,sizeof(g_cmd07),g_test_buf,1024);
  667. rt_printf(" 加密[%d].\r\n\r\n",ret);
  668. // 加密
  669. ret = esam_decrypt(g_cmd08,sizeof(g_cmd08),g_test_buf,1024);
  670. rt_printf(" 加密[%d].\r\n\r\n",ret);
  671. // 加密
  672. ret = esam_encrypt(g_cmd09,sizeof(g_cmd09),g_test_buf,1024);
  673. rt_printf(" 加密[%d].\r\n\r\n",ret);
  674. // 加密
  675. ret = esam_encrypt(g_cmd10,sizeof(g_cmd10),g_test_buf,1024);
  676. rt_printf(" 加密[%d].\r\n\r\n",ret);
  677. // 加密
  678. ret = esam_encrypt(g_cmd11,sizeof(g_cmd11),g_test_buf,1024);
  679. rt_printf(" 加密[%d].\r\n\r\n",ret);
  680. // 加密
  681. ret = esam_encrypt(g_cmd12,sizeof(g_cmd12),g_test_buf,1024);
  682. rt_printf(" 加密[%d].\r\n\r\n",ret);
  683. // 对时解密
  684. ret = esam_decrypt(g_cmd13,sizeof(g_cmd13),g_test_buf,1024);
  685. rt_printf(" 解密[%d].\r\n\r\n",ret);
  686. #endif
  687. // 对时加密
  688. ret = esam_encrypt(g_cmd14,sizeof(g_cmd14),g_test_buf,1024);
  689. rt_printf(" 加密[%d].\r\n\r\n",ret);
  690. // 遥控解密
  691. ret = esam_decrypt(g_cmd15,sizeof(g_cmd15),g_test_buf,1024);
  692. rt_printf(" 解密[%d].\r\n\r\n",ret);
  693. return 0;
  694. }
  695. int esam_info_printf(void)
  696. {
  697. static int count=1;
  698. int ret;
  699. int i;
  700. static u8 in[256];
  701. static u8 out[128];
  702. s8 sz[64];
  703. u16 cer_len=0;
  704. int g_print_sys_old;
  705. g_print_sys_old = g_print_sys;
  706. g_print_sys = 1;
  707. rt_printf("esam info...\r\n");
  708. for(i=0;i<128;i++)
  709. {
  710. in[i] =i;
  711. }
  712. // 版本
  713. ret = esam_get_version(out,1);
  714. if(ret < 0)
  715. {
  716. rt_printf("检测不到加密芯片[%d]\r\n",ret);
  717. g_print_sys = g_print_sys_old;
  718. return -1;
  719. }
  720. rt_printf("版本[%d]:0x%02x.\r\n",ret,out[0]);
  721. // 序号
  722. for(i=0;i<1;i++)
  723. {
  724. ret = esam_get_sn(out,8);
  725. sprintf(sz,"%02d序号[%d]:",count,ret);
  726. print_mem(sz,out,8);
  727. if(ret < 0)
  728. {
  729. break;
  730. }
  731. }
  732. // 得到随机数
  733. ret = esam_get_random(out,8);
  734. rt_printf("随机数[%d].\r\n",ret);
  735. // 随机数签名
  736. ret = esam_sign_random(in,8,out,0x48);
  737. rt_printf("随机数签名[%d].\r\n",ret);
  738. // 终端公钥
  739. ret = esam_yw_get_pubkey(g_test_buf,1024);
  740. rt_printf("获取终端公钥[%d].\r\n",ret);
  741. #if 0
  742. // 主站签名验证
  743. ret = esam_sign_verify_zz(1,in,64);
  744. rt_printf("主站签名验证[%d].\r\n",ret);
  745. // 规约签名验证
  746. ret = esam_sign_verify_yk(2,in,128);
  747. rt_printf("规约签名验证[%d].\r\n",ret);
  748. // 加密
  749. ret = esam_encrypt(in,65,out,128);
  750. rt_printf("加密[%d].\r\n",ret);
  751. // 解密
  752. ret = esam_decrypt(out,ret,in,128);
  753. rt_printf("解密[%d].\r\n",ret);
  754. // 读取终端测试证书长度
  755. ret = esam_cer_zd_test_get_len((u8*)&cer_len,2);
  756. rt_printf("读取终端测试证书长度[%d].\r\n",ret);
  757. // 读取终端测试证书
  758. ret = esam_cer_zd_test_get(cer_len,g_test_buf,1024);
  759. rt_printf("读取终端测试证书[%d].\r\n",ret);
  760. #endif
  761. // 读取终端正式证书
  762. ret = esam_cer_zd_get(g_test_buf,1024);
  763. rt_printf("读取终端正式证书[%d].\r\n",ret);
  764. // 如果成功,将测试证书写入文件
  765. if(ret > 0)
  766. {
  767. loff_t pos;
  768. struct file * gfile;
  769. gfile = rt_file_open("/tmp/zd_test.cer",O_CREAT|O_RDWR|O_TRUNC,0);
  770. if(IS_ERR(gfile))
  771. {
  772. g_print_sys = g_print_sys_old;
  773. return -1;
  774. }
  775. pos = 0;
  776. rt_file_write(gfile,g_test_buf,ret,&pos);
  777. rt_file_close(gfile,NULL);
  778. rt_printf("证书输出路径:/tmp/zd_test.cer.\r\n");
  779. cer_len = ret;
  780. }
  781. // esam_test();
  782. // ret = esam_cer_zd_update(g_test_buf,cer_len);
  783. // rt_printf("更新终端正式证书[%d].\r\n",ret);
  784. g_print_sys = g_print_sys_old;
  785. return 0;
  786. }