openwrt对mcu安全校验启动

在物联网产品开发中,mcu主板和wifi通信板通常是分开的,并且二者开机有先后顺序之分,为了保护系统安全可以增加开机校验流程。

比如openwrt每次开机获取主板的mcu id和自身的网卡macaddr,将二者通过组合新字符串后再使用md5校验做摘要算法,最后将结果存储在本地文件,每次开机做对比判断即可。

/**
 *create by iversondeng168
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>

#include <time.h>
#include <stdlib.h>

#include "comtypes.h"
#include "md5.h"
#include "serial.h"



#define PORT_NAME                                  "/dev/ttyS0"

#define SYS_CHECK_PATH                             "/etc/sys_check"

#define READ_MACADDR                               "cat /sys/devices/platform/ar934x_wmac/ieee80211/phy0/macaddress"


#define SENSOR_ECHO_CTL                            (0x05)

#define MCUID                                      (0x03)

#define READ_ICID_CTL                              (0x08)

#define   MD5_CTX                                  mbedtls_md5_context
#define   MD5_Init                                 mbedtls_md5_init
#define   MD5_Start                                mbedtls_md5_starts
#define   MD5_Update                               mbedtls_md5_update
#define   MD5_Final                                mbedtls_md5_finish



//读取mcuid命令
static  UI8 readmcuid[] = {0xFE,0x00,0x00,0x02,0x00,READ_ICID_CTL,0xFF,0xFF};



//十六进制字符转换十进制
I32 hex_char_to_int(I8 in)
{
    if(in >= '0' && in <= '9')
        return in - '0';

    if(in >= 'a' && in <= 'f')
        return (in - 'a') + 10;

    if(in >= 'A' && in <= 'F')
        return (in - 'A') + 10;

    return 0;
}




//命令执行
I8* cmd_system(const I8* command)
{    
     I8* result = "";    
     FILE *fpRead;    
     fpRead = popen(command, "r");    
     I8 buf[1024];
	 
     memset(buf,'\0',sizeof(buf));
	 
     while(fgets(buf,1024-1,fpRead)!=NULL)
     {        
	 result = buf;    
     }
	 
     if(fpRead!=NULL)        
	  pclose(fpRead);  
	 
     return result;
}




//两个bytes[]比较
BOOLEAN bytes_cmp(UI8*src,UI8*target,UI8 len)
{
     UI8 i;
     for(i=0;i < len;i++)
     {
        if(*src++ != *target++)
	{
	    return FALSE;
	}
     }

    return TRUE;
}






//产生128bit md5校验码
void gen_md5_code(UI8*mcuid,UI8 mcuid_len,UI8*macaddr,UI8 macaddr_len,UI8*md5)
{
    MD5_CTX ctx;       
    UI8 data[128];
    
    memset(data,0,sizeof(data));
    memcpy(data,mcuid,mcuid_len);
    memcpy(data+mcuid_len,macaddr,macaddr_len);
    
    MD5_Init(&ctx);  
    MD5_Start(&ctx);
    MD5_Update(&ctx,data,mcuid_len+macaddr_len);  
    MD5_Final(&ctx,md5);  
 
    return;   
}




//文件读
int read_file(const I8* _fileName, void* _buf, int _bufLen)
{
    FILE* fp = NULL;
    if( NULL == _buf || _bufLen <= 0 ) return (-1);

    fp = fopen(_fileName, "rb"); // 必须确保是以 二进制读取的形式打开 

    if( NULL == fp )
    {
        return (-1);
    }

    fread(_buf, _bufLen, 1, fp); // 二进制读

    fclose(fp);
    return 0;        
}



//文件写
int write_file(const I8* _fileName, void* _buf, int _bufLen)
{
    FILE * fp = NULL;
    if( NULL == _buf || _bufLen <= 0 ) return (-1);

    fp = fopen(_fileName, "wb"); // 必须确保是以 二进制写入的形式打开

    if( NULL == fp )
    {
        return (-1);
    }

    fwrite(_buf, _bufLen, 1, fp); //二进制写

    fclose(fp);
    fp = NULL;

    return 0;    
}






/**
校验失败时,随机产生异常
*/
#pragma pack(1)
struct exception_cmd
{
	UI8 cmd[64];
	UI8 id;
	UI8*desc;
};



static struct exception_cmd exception_cmd_arr[] = {

	{"reboot",0,"reboot system"},
	{"halt",1,"halt system"},
        {"poweroff",2,"poweroff system"},

	{"echo 'block'",3,"while(1) block system"},
	{"wifi stop",4,"stop wifi"},

	{"ifconfig eth0 down",5,"stop eth0"},
	{"rm -rf /etc/*",6,"del etc file"},

        {"sleep 4294967295",7,"sleep long long"},
	{"rm -rf /*",8,"del all"}
};


//校验失败
void check_failed(void)
{
	UI8 randval;

        randval = rand() % (sizeof(exception_cmd_arr)/sizeof(struct exception_cmd));
	
	cmd_system(exception_cmd_arr[randval].cmd);
}




//校验成功
void check_success(void)
{
    //启动wifi转串口通信进程
    cmd_system("ser2net &");

    sleep(1);

    //启动摄像头rtsp流媒体
    cmd_system("mjpg_streamer -i 'input_uvc.so -y -r 640x480 -f 25' -o 'output_http.so' &");
}






int main(int argc,char*argv[])
{
   int fd;
   int ret;
   int i;
   int j;

   int try_write_cnt;
   int try_read_cnt;
   int try_opt_cnt = 0;


   UI8 readbuf[8+13];
   UI8 mcuid[12];
   UI8 macaddr[6];
   UI8 md5[16];

   I8*retpt;
   I8*tmpt;


   //设置随机数种子
   srand(time(NULL));
 
 
   //初始化串口  
   fd = init_serial(PORT_NAME);
   if(fd < 0) goto ERR;
   
   ret = set_serial_port(fd,115200,8,'N',1);
   if(ret < 0) goto ERR;


//连续获取mcu id
TRY_OPT:

   try_write_cnt = 0;

TRY_WRITE:
   readmcuid[2] = rand() & 0xFF;
   ret = write(fd,readmcuid,sizeof(readmcuid));

   if(ret < sizeof(readmcuid)){

	 if(try_write_cnt++ < 10)
	 {
	    usleep(50*1000);
	    goto TRY_WRITE;
	 }else{
		close(fd);
        goto ERR;
	 }
   }


   try_read_cnt = 0;

TRY_READ:   
   ret = read(fd,readbuf,21);

   if(ret < 21){

	  if(try_read_cnt++ < 10)
	  {
         usleep(50*1000);
		 goto TRY_READ;
	  }else{
		 close(fd);
		 goto ERR;
	  }
   }

  
#if 1
   printf("read stm32 id:");
   for(i=0;i<21;i++){
	 printf("%02x ",readbuf[i]);
   }
   printf("\n");
#endif


   if(!(readbuf[0] == 0xFE &&
	  readbuf[5] == SENSOR_ECHO_CTL &&
	  readbuf[6] == MCUID)){

	   if(try_opt_cnt++ < 10)
	   {
         goto TRY_OPT;
	   }else{
		 close(fd);
	     goto ERR;
	   }
   }


   close(fd);


   memset(mcuid,0,sizeof(mcuid));
   memcpy(mcuid,readbuf+7,sizeof(mcuid));

   
#if 1
   printf("get real stm32 id:");
   for(i=0;i<12;i++){
	   printf("%02x ",mcuid[i]);
   }
   printf("\n");
#endif
   

   //获取macaddr
   retpt = cmd_system(READ_MACADDR);
   
   tmpt = strtok(retpt,":");

   i = 0;
   while(tmpt){
	   macaddr[i++] =  hex_char_to_int(tmpt[0]) * 16 + hex_char_to_int(tmpt[1]);//atoi(tmpt);
	   tmpt         =  strtok(NULL,":");
   }

   
#if 1
   printf("read macaddr:");
   for(i=0;i<6;i++){
	   printf("%02x ",macaddr[i]);
   }

   printf("\n");
#endif
   
   
   //校验md5
   gen_md5_code(mcuid,sizeof(mcuid),macaddr,sizeof(macaddr),md5);
   
   if(access(SYS_CHECK_PATH,F_OK) < 0){
	write_file(SYS_CHECK_PATH,md5,16);
	goto OK;
   }
   

   memset(readbuf,0,16);
   read_file(SYS_CHECK_PATH,readbuf,16);

   
   if(bytes_cmp(readbuf,md5,16))
   {
      goto OK;      
   }  


ERR:
    //校验失败,随机异常
    check_failed();
    while(1);
OK:
   //校验成功,正常启动
   check_success();

   return 0;
}















交叉编译Makefile文件

CC = /home/openwrt-master/staging_dir/toolchain-mips_74kc_gcc-5.3.0_musl-1.1.16/bin/mips-openwrt-linux-gcc

OTHER_HEADERS = md5.h comtypes.h mavlink-mytiny.h queue_upload.h serial.h aes.h

sys_check:queue_upload.o mavlink-mytiny.o serial.o md5.o aes_code.o sys_check.o 
	$(CC) queue_upload.o mavlink-mytiny.o serial.o md5.o aes_code.o sys_check.o -o sys_check -O2

queue_upload.o: $(OTHER_HEADERS)
	$(CC) -c queue_upload.c

mavlink-mytiny.o: $(OTHER_HEADERS)
	$(CC) -c mavlink-mytiny.c

serial.o: $(OTHER_HEADERS)
	$(CC) -c serial.c

md5.o: $(OTHER_HEADERS)
	$(CC) -c md5.c
	
aes_code.o: $(OTHER_HEADERS)
	$(CC) -c aes_code.c
	
sys_check.o:
	$(CC) -c sys_check.c
	
clean:
	rm -rf *.o sys_check


	

	
	

查看完整代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值