auth.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. #include "includes.h"
  2. /*
  3. 文件描述
  4. 1、主要处理终端与DTU之间的授权功能所需要的通讯逻辑
  5. 2、终端在正确下载完APP后,如果未进行授权,会自动跳到授权的任务中,直到授权成功
  6. 3、授权码产生算法存在于本设备及服务器中
  7. 4、终端启动后会读取MCU内存中的授权码,并与使用MCU ID进行加密码得出的授权码进行比对,不一样则未授权
  8. */
  9. #define UNIQUE_ID_BYTES 12
  10. #define TAKE_PRINT_FLAG 0
  11. #define RAND_STR_LEN 6
  12. const unsigned char randStr[RAND_STR_LEN]={'s','z','5','0','2','8'};
  13. const unsigned char srcAuth[16]={0x17,0x0d,0x55,0x9f,0xab,0xcc,0x1c,0x8f,0x30,0x0a,0x28,0xda,0x3c,0x91,0x11,0x6d};
  14. const unsigned char FirmSrc[10]={0x50,0x28,0xaf,0x6d,0x08,0x9c,0x1b,0xe4,0x23,0x77};
  15. uint32_t auth_seg_addr,iap_temp_addr,app_seg_addr;
  16. uint16_t this_dev_page_size,this_dev_flash_size;
  17. unsigned char SlaveNum;
  18. unsigned char Authed;
  19. //获取唯一ID接口
  20. typedef enum{
  21. STM32F0,STM32F1,STM32F2,STM32F3,STM32F4,STM32F7,
  22. STM32L0,STM32L1,STM32L4,
  23. STM32H7,
  24. STM_END
  25. }STM32_MCU_DEF;
  26. unsigned int mcustartAddr[STM_END]=
  27. {
  28. 0x1FFFF7AC,/*STM32F0*/
  29. 0x1FFFF7E8,/*STM32F1*/
  30. 0x1FFF7A10,/*STM32F2*/
  31. 0x1FFFF7AC,/*STM32F3*/
  32. 0x1FFF7A10,/*STM32F4*/
  33. 0x1FF0F420,/*STM32F7*/
  34. 0x1FF80050,/*STM32L0*/
  35. 0x1FF80050,/*STM32L1*/
  36. 0x1FFF7590,/*STM32L4*/
  37. 0x1FF0F420 /*STM32H7*/
  38. };
  39. void GetSTM32_McuID(unsigned char *id,STM32_MCU_DEF type)
  40. {
  41. unsigned char i;
  42. if(id==NULL) return;
  43. for(i=0;i<UNIQUE_ID_BYTES;i++){
  44. if(NULL != &id[i])
  45. id[i]=*(unsigned int *)(mcustartAddr[type]+i);
  46. }
  47. }
  48. unsigned int encodeWithID(unsigned char *id,unsigned char idlen)
  49. {
  50. const unsigned char sucRandTable[256]={
  51. 0x68,0x59,0x63,0x64,0xc8,0xcc,0xaa,0xa7,0xa2,0xab,0xa5,0x6e,0x6a,0x56,0x8a,0x57,
  52. 0xf4,0xbb,0xfe,0xfa,0x26,0x21,0x2d,0x29,0x0d,0x09,0x3e,0x3a,0x37,0x32,0x0a,0x07,
  53. 0xf7,0xf2,0xfb,0xf5,0xff,0xf6,0x1c,0x18,0x13,0x14,0xf1,0xfd,0xf9,0x0c,0x9f,0x08,
  54. 0x9a,0x97,0x92,0x9b,0x95,0x9f,0x12,0x1b,0x15,0x2c,0x28,0x23,0xf9,0x2a,0x27,0x22,
  55. 0x24,0x2e,0x67,0x25,0x2f,0x98,0xfc,0x75,0xf8,0xf3,0x3c,0x38,0x33,0x34,0x03,0x04,
  56. 0x05,0x0f,0x06,0x01,0x7a,0x77,0x72,0x62,0x6b,0x83,0x84,0x8e,0xc4,0xcb,0x87,0x82,
  57. 0x35,0x3f,0x36,0x4f,0x3d,0x39,0x9c,0x98,0x93,0x94,0x42,0x4f,0x46,0x41,0x81,0x8d,
  58. 0x4d,0x49,0x71,0x7d,0x79,0x96,0x91,0x9d,0x99,0xc3,0xc4,0x1d,0xce,0xca,0x7f,0x76,
  59. 0x7c,0x78,0x73,0x74,0x7e,0x7b,0x75,0x1e,0x1a,0x17,0x1f,0x16,0x11,0x1d,0x47,0x19,
  60. 0x5d,0xc7,0xc2,0xcb,0xc5,0xcf,0xd1,0xdd,0xd9,0x4c,0x48,0xc6,0xc1,0xcd,0x61,0xc9,
  61. 0xd7,0x8c,0xfd,0x88,0xa1,0xad,0xa9,0xb1,0xbd,0xb9,0x8b,0x85,0x8f,0x4b,0x45,0x86,
  62. 0xdc,0xd8,0xd3,0xd4,0xde,0xd2,0xdb,0xd5,0xdf,0xd6,0x43,0x44,0x4e,0x4a,0xe7,0x47,
  63. 0xac,0xa8,0xa3,0xa4,0xae,0xba,0x0d,0xb7,0xb2,0xaf,0xa6,0xe4,0xee,0xea,0xe7,0xe2,
  64. 0xe1,0xed,0x0f,0xe9,0x66,0x61,0x6d,0x69,0xbb,0xb5,0xbf,0xb6,0xec,0xe8,0x0b,0xe3,
  65. 0x52,0x5c,0x65,0x6f,0x58,0x53,0x54,0x0c,0x5e,0x5b,0x55,0x5f,0x31,0x2f,0x9a,0x0b,
  66. 0x0b,0x5a,0x2b,0x9e,0x02,0x89,0x59,0x3b,0x0e,0x51,0x6c,0xeb,0xda,0xe6,0x31,0xf6
  67. };
  68. unsigned char i;
  69. unsigned int ret;
  70. unsigned char temp1,temp2;
  71. unsigned char idtemp[64];
  72. temp1=0;
  73. for(i=0;i<idlen;i++){
  74. temp1 ^= id[i];
  75. idtemp[i]=id[i];
  76. }
  77. temp1 ^= idlen;
  78. temp2=sucRandTable[temp1];
  79. //循环查表异或运算,生成新id
  80. for(i=0;i<idlen;i++){
  81. temp1=idtemp[i]^temp2;
  82. idtemp[i]=i^temp1;
  83. temp2=sucRandTable[temp1];
  84. }
  85. //最后每3字节再异或得到4字节作为输出
  86. for(i=0;i<4;i++){
  87. temp1=idtemp[3*i] ^ idtemp[3*i+1];
  88. idtemp[i]=temp1 ^ idtemp[3*i+2];
  89. }
  90. ret=idtemp[0];ret <<= 8;ret &= 0xFFFFFF00;
  91. ret |= idtemp[1];ret <<= 8;ret &= 0xFFFFFF00;
  92. ret |= idtemp[2];ret <<= 8;ret &= 0xFFFFFF00;
  93. ret |= idtemp[3];
  94. return ret;
  95. }
  96. void authSendCmd(unsigned char cmd, unsigned char *data, unsigned short len)
  97. {
  98. //协议格式
  99. //head cmd len data
  100. //data:liushui[2] id[12] 均经过cmd和长度加密
  101. static unsigned short liushui=0;
  102. unsigned char sendbuf[128];
  103. unsigned char i,k;
  104. unsigned char *dataPtr=sendbuf+3;
  105. unsigned char datalen=2+len+1;//加上sum
  106. unsigned char temp[3],sum;
  107. i=0;
  108. sendbuf[i++]=PRO_HEADER;
  109. sendbuf[i++]=cmd;
  110. sendbuf[i++]=datalen;
  111. sendbuf[i++]=liushui>>8; //4-5
  112. sendbuf[i++]=liushui;
  113. for(k=0;k<len;k++)
  114. sendbuf[i++]=data[k];
  115. temp[0]=3+datalen;//总长度,包括sum //47+3
  116. temp[1]=sendbuf[0]; //0x89
  117. temp[2]=sendbuf[1]; //0x34
  118. for(k=0;k<datalen-1;k++){
  119. dataPtr[k] ^= temp[k % 3];
  120. dataPtr[k] ^= TX_RX_SEED;
  121. }
  122. sum=0;
  123. for(k=0;k<i;k++) sum ^= sendbuf[k];
  124. sendbuf[i++]=sum;
  125. Uart1Send(sendbuf, i);
  126. #if(TAKE_PRINT_FLAG)
  127. printf("send[%d]:",i);
  128. for(k=0;k<i;k++) printf("%02x",sendbuf[k]);
  129. printf("\r\n");
  130. #endif
  131. }
  132. #define FACTORY_NAME "ZT" //最大16
  133. #define MODE_NAME "ZT200" //最大16
  134. void EncodeKeyWithFactorAndMode(unsigned char *code)
  135. {
  136. int i,j;
  137. char *FN=FACTORY_NAME;
  138. char *MN=MODE_NAME;
  139. j=strlen(FACTORY_NAME);
  140. for(i=0;i<j;i++) code[i%4] ^= FN[i];
  141. j=strlen(MODE_NAME);
  142. for(i=0;i<j;i++) code[i%4] ^= MN[i];
  143. }
  144. char decodeAuthInfo(unsigned char *data, unsigned char len,unsigned int targetcode,AUTH_INFO *authInfo)
  145. {
  146. unsigned char i;
  147. unsigned char sum=0;
  148. unsigned char temp[3];
  149. unsigned char *dataPtr=data+3;
  150. unsigned int codeData;
  151. if(data[0] != PRO_HEADER) return 1;
  152. if((data[2]+3) != len) return 2;
  153. for(i=0;i<len-1;i++) sum ^= data[i];
  154. if(sum != data[len-1]) return 3;
  155. temp[0]=len;
  156. temp[1]=data[0];
  157. temp[2]=data[1];
  158. for(i=0;i<data[1]-1;i++){
  159. dataPtr[i] ^= temp[i % 3];
  160. dataPtr[i] ^= TX_RX_SEED;
  161. }
  162. if(data[1]==PRO_AUTH_ACK){
  163. return 5;
  164. }else if(data[1]==PRO_AUTH_QUERY){
  165. return 6;
  166. }
  167. if(data[1]!=PRO_AUTH_SUC) return 4;
  168. //收到DTU通知鉴权成功,获取鉴权码
  169. //跳过流水号
  170. dataPtr += 2;
  171. EncodeKeyWithFactorAndMode(dataPtr);
  172. codeData=dataPtr[0];codeData <<= 8;codeData &= 0xFFFFFF00;
  173. codeData |= dataPtr[1];codeData <<= 8;codeData &= 0xFFFFFF00;
  174. codeData |= dataPtr[2];codeData <<= 8;codeData &= 0xFFFFFF00;
  175. codeData |= dataPtr[3];
  176. dataPtr += 4;
  177. //SlaveNum=*dataPtr;
  178. authInfo->SlaveNum=*dataPtr;
  179. //write new auth
  180. authInfo->authCode=codeData;
  181. //make lier data
  182. for(i=0;i<sizeof(authInfo->noUseStart);i++){
  183. authInfo->noUseStart[i]=*dataPtr++^data[6];
  184. if(dataPtr>=&data[len]) dataPtr=data;
  185. }
  186. for(i=0;i<sizeof(authInfo->noUseEnd);i++){
  187. authInfo->noUseEnd[i]=*dataPtr++^data[4];
  188. if(dataPtr>=&data[len]) dataPtr=data;
  189. }
  190. //WritePageData(auth_seg_addr,(unsigned char *)authInfo,sizeof(AUTH_INFO));
  191. WritePageData(AUTH_PARA_ADDR,(unsigned char *)authInfo,sizeof(AUTH_INFO));
  192. printf("newAuthInfo:%08x,targetcode:%08x\r\n",codeData,targetcode);
  193. if(codeData == targetcode){//当激活码与本地算的一致时
  194. return 0;
  195. }else return 4;//当激活码与本地算的不一致时
  196. }
  197. //根据MCU的FLASH容量大小判断出page大小,然后得到激活段与升级临时段的起始地址
  198. void GetStartAddrByFlashSize(void)
  199. {
  200. #if 1
  201. auth_seg_addr=0x8000000+124*1024;
  202. #else
  203. this_dev_flash_size=*(uint16_t *)(0x1FFFF7E0);//获取FLASH容量
  204. if(this_dev_flash_size <= 128) this_dev_page_size=2048;
  205. else this_dev_page_size=2048;
  206. //取得激活码段起始地址
  207. auth_seg_addr=APP_CONFIG_ADDR+this_dev_page_size;
  208. //取得临时段起始地址
  209. iap_temp_addr=auth_seg_addr+this_dev_page_size;
  210. //取得APP应用起始地址
  211. app_seg_addr=iap_temp_addr+this_dev_page_size;
  212. if(app_seg_addr % 2048) app_seg_addr += 1024;//跳转地址需要是页大小的倍数
  213. //printf("addr:%08x,%08x,%08x\r\n",auth_seg_addr,iap_temp_addr,app_seg_addr);
  214. #endif
  215. }
  216. void reInitUart1(void)
  217. {//关闭IDLE中断,打开NE中断
  218. USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);
  219. USART_DMACmd(USART1,USART_DMAReq_Rx,DISABLE);
  220. USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  221. rx1_ct=0;
  222. g_usUart1RecvLen=0;
  223. }
  224. void authLink()
  225. {
  226. unsigned int i=0;
  227. AUTH_INFO authInfo;
  228. unsigned char id[UNIQUE_ID_BYTES];
  229. //unsigned char id[UNIQUE_ID_BYTES]={1,2,3,4,5,6,7,8,9,1,1,2};
  230. unsigned int encodeValue;
  231. unsigned char senddata[100];
  232. unsigned int len;
  233. char ret;
  234. unsigned char j=0;
  235. unsigned char handshake=0;
  236. GetSTM32_McuID(id, STM32F1);
  237. #if(TAKE_PRINT_FLAG)
  238. printf("ID[%d]:",UNIQUE_ID_BYTES);
  239. for(i=0;i<sizeof(id);i++) printf("%02x",id[i]);
  240. printf("\r\n");
  241. #endif
  242. //decode with id
  243. encodeValue=encodeWithID(id,UNIQUE_ID_BYTES);//自己计算出 只通过MCUID
  244. #if(TAKE_PRINT_FLAG)
  245. printf("encodeValue:%08x\r\n",encodeValue);
  246. #endif
  247. memcpy(senddata, id, UNIQUE_ID_BYTES);
  248. memset(senddata+UNIQUE_ID_BYTES, 0, 16);
  249. strcpy(senddata+UNIQUE_ID_BYTES, FACTORY_NAME);
  250. memset(senddata+UNIQUE_ID_BYTES+16, 0, 16);
  251. strcpy(senddata+UNIQUE_ID_BYTES+16, MODE_NAME);
  252. //read encode in flash
  253. ReadFlashData( AUTH_PARA_ADDR,(unsigned char *)&authInfo,sizeof(AUTH_INFO));
  254. if(authInfo.authCode == encodeValue)return;
  255. while(1){
  256. if(i==0&&!handshake) authSendCmd(PRO_AUTH_RESPONS,0,0); //请求握手
  257. if(++i>=3){
  258. if(!handshake)j++;
  259. i=0;
  260. }
  261. if(j>3)break;
  262. IWDG_ReloadCounter();//喂狗
  263. DelayMs(100);
  264. if(g_usUart1RecvLen==0) continue;
  265. ret=decodeAuthInfo(RxBuffer1,g_usUart1RecvLen,encodeValue,&authInfo);
  266. if(0==ret){
  267. authSendCmd(PRO_AUTH_OK,id,UNIQUE_ID_BYTES);
  268. return;
  269. //break;
  270. }else if(4==ret){//鉴权码不正确
  271. authSendCmd(PRO_AUTH_FAI,id,UNIQUE_ID_BYTES);
  272. }else if(5==ret){//握手成功
  273. handshake=1;
  274. }else if(6==ret){ //请求基本数据
  275. authSendCmd(PRO_AUTH_REQ,senddata,UNIQUE_ID_BYTES+16+16);
  276. }
  277. g_usUart1RecvLen=0;
  278. }
  279. while(1){
  280. IWDG_ReloadCounter();//喂狗
  281. DelayMs(100);
  282. printf("please try auth-------------------\r\n");
  283. }
  284. }
  285. #define APP_UPDATE_COMPLETED 0x5c44f1d0
  286. #define APP_UPDATE_DEFAULT 0xffffffff
  287. #define APP_UPDATE_NONE_COMPLETED 0x2487314d
  288. void takeNoteThatFlushAppCompleteOrNot(char status)
  289. {
  290. unsigned int flushStatus;
  291. unsigned int currentStatus;
  292. if(status==0) flushStatus=APP_UPDATE_NONE_COMPLETED;//未完成APP的更新
  293. else flushStatus=APP_UPDATE_COMPLETED;//已完成APP的更新
  294. ReadFlashData(iap_temp_addr, (unsigned char *)&currentStatus, 4);
  295. if(currentStatus == flushStatus) return;
  296. WritePageData(iap_temp_addr, (unsigned char *)&flushStatus, 4);
  297. }
  298. void checkLastAppUpdateCompleteOrNot(void)
  299. {
  300. unsigned int currentStatus;
  301. ReadFlashData(iap_temp_addr, (unsigned char *)&currentStatus, 4);
  302. if(currentStatus == APP_UPDATE_COMPLETED || currentStatus == APP_UPDATE_DEFAULT) return;
  303. currentStatus=0;
  304. while(1){
  305. if(currentStatus==0) printf("Last update err, need retry!\r\n");
  306. if(++currentStatus >= 2000*2000) currentStatus=0;
  307. }
  308. }
  309. /*
  310. 对长度为tagetlen的targetstring 进行加密
  311. 入参为randlen的随机串randstring
  312. */
  313. void extCodeBuffer(unsigned char *randString, int randlen, unsigned char *targetString, int targetlen){
  314. int i,j,k;
  315. unsigned char value;
  316. //先使用随机串依次对targetString进行异或
  317. j=0;
  318. for(i=0;i<targetlen;i++){
  319. targetString[i] ^= randString[j];
  320. if(++j>=randlen) j=0;
  321. }
  322. //再对targetstring的奇数索引字节,与randstring的高低4位指向的srcAuth索引字节异或
  323. j=0;
  324. for(i=0;i<targetlen;i++){
  325. if(j%2) k=randStr[j]&0x0F;
  326. else k=(randStr[j]>>4)&0x0F;
  327. value=srcAuth[k];
  328. if(++j>=randlen) j=0;
  329. if(i%2) targetString[i] ^= value;
  330. }
  331. }
  332. unsigned char PocAuthDataPack(unsigned char *Packdata)
  333. {
  334. unsigned char id[UNIQUE_ID_BYTES];
  335. unsigned char i=0;
  336. GetSTM32_McuID(id, STM32F1);
  337. strcpy(&Packdata[i], FACTORY_NAME);
  338. i=i+16;
  339. strcpy(&Packdata[i], MODE_NAME);
  340. i=i+16;
  341. Packdata[i]=UNIQUE_ID_BYTES;
  342. i=i+1;
  343. memcpy(&Packdata[i], id,UNIQUE_ID_BYTES);
  344. i=i+UNIQUE_ID_BYTES;
  345. return i;
  346. }
  347. //unsigned char AscToHex(unsigned char aHex)
  348. //{
  349. // if((aHex>=0)&&(aHex<=9))
  350. // aHex += 0x30;
  351. // else if((aHex>=10)&&(aHex<=15))//A-F
  352. // //aHex += 0x37;
  353. // aHex += 0x57;
  354. // else aHex = 0xff;
  355. // return aHex;
  356. //}
  357. static void AscStrToHexStrForgetZero(char *AscStr, char *HexStr,unsigned char len)
  358. {
  359. char *pAscStr=AscStr;
  360. unsigned char d,h,l;
  361. while(len){
  362. d=(unsigned char)*pAscStr++;
  363. l=d&0x0f;
  364. h=d>>4;
  365. *HexStr++=AscToHex(h);
  366. *HexStr++=AscToHex(l);
  367. len--;
  368. }
  369. *HexStr=0;
  370. }
  371. void PocAuthProcess(char *msg)
  372. {
  373. unsigned char Ranbuf[20];
  374. unsigned char SendDataBuf[120];
  375. unsigned char DelDataBuf[120];
  376. unsigned char i=0;
  377. unsigned char len;
  378. memset(DelDataBuf,0,sizeof(DelDataBuf));
  379. memset(SendDataBuf,0,sizeof(SendDataBuf));
  380. memset(Ranbuf,0,sizeof(Ranbuf));
  381. printf(msg);
  382. //BEA6F8ECFFE4 -->0xBE 0XA6
  383. StrAsciiToHex(msg,Ranbuf);
  384. memcpy(DelDataBuf,FirmSrc,sizeof(FirmSrc));
  385. //MCU参数组包
  386. len=sizeof(FirmSrc);
  387. extCodeBuffer(Ranbuf,strlen(Ranbuf)-1,DelDataBuf,len);
  388. // len=PocAuthDataPack(DelDataBuf);
  389. // extCodeBuffer(Ranbuf,strlen(Ranbuf)-1,DelDataBuf,len); //因为回车换行转成一个字节
  390. AscStrToHexStrForgetZero(DelDataBuf,SendDataBuf,len);
  391. printf(SendDataBuf);
  392. memset(DelDataBuf,0,sizeof(DelDataBuf));
  393. //AT+SAUTH
  394. snprintf(DelDataBuf,sizeof(DelDataBuf),"AT+SAUTH=%s\r\n",SendDataBuf);
  395. printf(DelDataBuf);
  396. ModemSendData(DelDataBuf,len*2+12);
  397. }