打印
[菜农助学交流]

运行在助学板上的加密Bootloader

[复制链接]
15709|76
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lxyppc|  楼主 | 2011-12-13 10:12 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
为什么要用加密的Bootloader:
一般加密的Bootloader用在客户端的升级上,把密文程序发给用户,在用户处进行升级,加密可以防止传输过程中程序泄露出去。

下面是这个bootloader的可执行文件和相关源代码
hidisp.zip (874.21 KB)
文件夹说明
firmware            bootloader固件代码工程
software            bootloader windows上位机程序源代码
out                   工程输出文件夹,里面包括了Bootloader的bin文件,PC上位机可执行程序

相关帖子

沙发
lxyppc|  楼主 | 2011-12-13 10:22 | 只看该作者
现在来扯扯淡:
很早以前抢沙发抢了菜农大叔的一块助学板,拿来也没怎么玩过,俺先前拼凑了一个加密的Bootloader出来,正好大叔也喜欢搞密码的东西,就在助学板上面折腾了下。

为啥是拼凑,各位看官往下看
新塘M0有一个好玩的应用,那就是AN1024,用USB Mass Storage实现的ISP。本以为这没有什么,因为俺在STM32上就玩过。
《5分钟用STM32的内置Flash做一个超小U盘》
我晕,EDNChina坑爹啊,以前发的**排版都不成样子了,难道是firefox的问题
这是ednchina的原文链接
http://bbs.**/BLOG_ARTICLE_280560.HTM
算了,还是看盗版的吧。还好盗版链接的排版没变,太坑爹了,看个自己发的**都要看盗版的。
http://www.**.com/bbs/article_244_97168.html

扯远了,言归正传,继续来看新塘的Mass Storage ISP
下载编译后一看,俺不淡定了,这玩意儿居然是塞在LDROM中的,也就是整个做下来不到4K。
我X,这是什么样的代码啊。还好这是开源的。
我看了看,很显然,他没有用BSP中的USB Framework,而直接处理的USB中断。哦,说错了,在LDROM中是没有中断的,需要不停地去查询USB相关寄存器的标志。
而且所有descriptor都限制在了64bytes以内,这样简化了UsbStdReq的代码和逻辑。

既然Mass Storage都能放进4K的空间中,那HID协议更能放得下了,然后我就尝试将他的Mass Storage ISP转换成HID ISP。
HID设备也是不需要驱动程序的,不过需要一个应用程序。
HID ISP做成之后用了还不到3K的空间,还有1K多空余的,心想这不浪费了么。
于是琢磨着加点料在里面,和ISP相关的那就是加密了,加密算法网上也有现成的,而且也是用来做bootloader的,那就是Atmel的AVR231,AES Bootloader。
AVR231说他的ROM空间占用不到2K,“AES Bootloader fits into 2-KB”。

心想我只是做个ISP,加密在PC上做,芯片里面只要解密就行了。
AES是个对称算法,我不用加密的只用解密,那就应该"fits into 1-KB"。下代码,稍微改了下,编译,我了个去,果然是4K不到。
当然光下载还是不行,还得校验一下下载的程序是否正确,我用CRC做校验,正好菜农大叔也喜欢CRC。
32位机当然用crc32。多项式和顺序就用STM32的那个。(因为之前做过STM32的Bootloader,STM32的CRC代码是现成的,又被我借来用了)
/*0001*/  unsigned long  CalcCrc32(const unsigned char* data, unsigned long size)
/*0002*/  {
/*0003*/      unsigned long crc = CRC32_MASK;
/*0004*/      while(size--){
/*0005*/          crc = (crc << 8) ^ Crc32Table[ ((crc >> (32-8)) & 0xFF) ^ *data++];
/*0006*/      }
/*0007*/      crc ^= CRC32_MASK;
/*0008*/      return crc;
/*0009*/  }
好了就这样吧,不过还有问题,这密钥不能全都一样吧,于是乎,我把LDROM的最后一个page用来存一些参数,其实只用了几十个bytes。里面包括序列号和密钥的信息。
NUC120的一页是512字节,所以我的这个bootloader占用的空间要控制在 4096-512=3584 bytes。还好,折腾一番之后代码刚好能塞进去。


就这样
修改了新塘AN1024的Mass Storage ISP,加入了Atmel AVR231的AES加密算法,再用STM32的CRC32做校验。
于是乎,一个只有3.5K的AES HID Bootloader就这样拼凑出来了。

该Bootloader的最大特点就是VID和PID都是0x250。菜农要不再去化点缘,把这个VID买下来吧。
#define VENDOR_ID               0x0250
#define PRODUCT_ID               0x0250

当然,它的默认密钥也全是250
unsigned char kTable[32]
#ifdef  STM32
;
#else
={
  0x02, 0x50, 0x02, 0x50, 0x02, 0x50, 0x02, 0x50,
  0x02, 0x50, 0x02, 0x50, 0x02, 0x50, 0x02, 0x50,
  0x02, 0x50, 0x02, 0x50, 0x02, 0x50, 0x02, 0x50,
  0x02, 0x50, 0x02, 0x50, 0x02, 0x50, 0x02, 0x50,
};
#endif

使用特权

评论回复
板凳
lxyppc|  楼主 | 2011-12-13 10:30 | 只看该作者

生成并下载Bootlader到助学板中

本帖最后由 lxyppc 于 2011-12-13 10:32 编辑

淡扯得差不多了,下面来说说如何使用这个Bootloader
要使用这个bootloader当然先要把它下载进助学板的LDROM中。直接编译出来的Bootloader没有序列号没有设置密钥,需要处理一下再下载。
处理过程如下:
bootloader的bin文件名是HID_ISP.bin,它在楼主位的附件中,解压后在out目录里面
下载过程有点曲折,希望不会晕掉。
由于bootloader编译好之后没有设置密钥,用的是默认250密钥。先要生成一个有密钥和序列号的bootloader镜像。
这里用ispcrypt这个命令行工具来制作镜像。这个工具也在楼主位附件中的out目录下,貌似大叔的HotISP也很喜欢命令行的东西,要不大叔的HotISP把它收编了吧。
在命令行中输入“ispcrypt ld HID_ISP.bin 250”或是直接执行create_loader.bat文件
命令行中执行結果如下

运行成功后会生成三个文件,如果失败可以在命令行中看到失败原因
00000250.ld.bin      bootloader镜像文件,它的序列号是00000250,密钥是随机生成的。序列号只能是8个字符,不足8个前面补0,超过了只取前8个。
00000250.ld.img      加密的bootloader镜像文件,有了NuLink就不用管他了。(我以前没有NuLink只有JLink的时候用的,过程很纠结。)
00000250.bin         密钥文件,密钥文件是以序列号命名的,里面包含了序列号和密钥信息。这个文件一定要保管好,因为以后用这个bootloader下载程序就全靠它了。

实际上 HID_ISP.bin + 00000250.bin = 00000250.ld.bin
00000250.ld.bin用默认密钥加密后就是00000250.ld.img

用新塘的ICP工具把这个00000250.ld.img下载到LDROM中,并且把助学板设置为从LDROM启动。


下载配置完成后,拨掉NuLink,连上助学板的USB线,这个时候电脑会发现新硬件,由于是HID设备,会自动安装驱动程序。

运行楼主位附件中out目录下的HidISP.exe这个程序,如果看到connect并且显示Bootloader,说明Bootloader下载成功,且运行正常。

使用特权

评论回复
地板
lxyppc|  楼主 | 2011-12-13 10:36 | 只看该作者

用这个加密的Bootloader下载一个程序

本帖最后由 lxyppc 于 2011-12-13 10:43 编辑

Bootloader准备好了,下面来实验一下这个bootloader好不好用。
到园地上随便找一个程序,最好是有bin或者是hex的,这样省得再去编译了
我用的是园地中的这个程序来测试
LOOK+红杏头文件 学习第一帖:1个KEY控制4个LED闪烁
这个程序的hex文件已经包含在楼主位的附件中。

把这个文件放在和ispcrypt相同的目录中,并且准备好刚才用来制作bootloader的序列号文件,即将00000250.bin也放在和ispcrypt.exe相同的目录中。
在命令行中执行"ispcrypt ap led.hex 250"或是直接运行create_app.bat文件。ispcrypt同时支持bin和hex格式。
命令行中运行内容如下:(看起来可能和windows上的不一样,这个是在ubuntu中运行的画面)

运行成功后会生成一个img文件,如果失败可以在命令行中看到失败原因
00000250.ap.img 便是加密的应用程序镜像,稍候我们通过这个镜像将程序烧写入助学板中。
这个镜像是加密后的,他是用00000250.bin这个密钥文件制作出来的,因此只有密钥为00000250.bin的Bootloader才能解密下载。
只要别人不知道密钥文件的内容,这个程序镜像就是相对安全的。
同一个文件用同一个密钥文件多次加密会得到不同大小和内容的密文,这是正常的,不是bug。

运行HidISP.exe这个程序

将刚才生成的00000250.ap.img加载进来,点击[Update]。

下载成功后出来下面的提示。

如果出现的是别的提示,那说明下载失败。至于下载失败的具体原因,我也不知道。

下载成功后按下助学板的reset键,程序会跳转到APROM中运行。这样可以看led灯的程序已经开始运行,4个led依次点亮,按key2改变顺序


如果要想回到Bootloader程序,更新其它的程序,可拨掉USB线,然后按住助学板上Key1键不放,再插上USB线,这个时候可以看到Bootloader又重新连上了。
重复上面的步骤即可下载别的程序。

使用特权

评论回复
5
lxyppc|  楼主 | 2011-12-13 10:48 | 只看该作者

Bootloader使用的注意事項

本帖最后由 lxyppc 于 2011-12-13 10:50 编辑

Bootloader使用的注意事項
1. Bootloader通过检测APP_FLAG_ADDR这个地址的值是否为APP_VALID来查看APROM中是否有合法的程序,如果有则跳转到APROM执行,没有就在LDROM中执行。如果APROM的这个地址非法或是被APP使用,需要更改APP_FLAG_ADDR定义的地址或者是不用这个方式检测APROM中是否有程序
/* APP Flag is used to determine the application is update success */
#define  APP_FLAG_ADDR            (128*1024-512)
#define  APP_VALID                (0xfeedbacc)

2. Bootloader通过检测助学板上的Key1是否按下来决定是否执行LDROM中的程序。如果Key1按下,则执行LDROM中的程序。如果Key1对应引脚在启动时需要设为低电平,需要更改检测条件或是不使用引脚来检测是否需要进入LDROM
/*0001*/      /* Check if GPB15 is low */
/*0002*/      /* GPB15 is key 1 on 120 board */
/*0003*/      if ( ( ISPRead(APP_FLAG_ADDR) ==  APP_VALID  )
/*0004*/        && ( (inp32(GPIOB_BASE + 0x10) & BIT15) != 0)
/*0005*/        && (! IsUserReset())
/*0006*/           )
/*0007*/      {
/*0008*/          ClearUserReset();
/*0009*/          /* Boot from AP */
/*0010*/          if(FMC->ISPCON.BS){
/*0011*/              FMC->ISPCON.BS = 0;   
/*0012*/              outp32(&SYS->IPRSTC1, 0x02);
/*0013*/              while(1);
/*0014*/          }
/*0015*/      }

3. Bootloader通过检测内存地址RESET_REASON_ADDR中的值是否为RESET_REASON_USER来查看是否是软件造成的复位。内存上电时有一定的机率产生和标志RESET_REASON_USER相同的值,造成上电后不能正常进入APROM的问题,可以取消这个检测,或是用别的方式替代。
#define  RESET_REASON_ADDR        (0x20000000 + 4096 - 4)
#define  RESET_REASON_USER      (0xbaccfeed)
#define  IsUserReset()            (*((uint32_t*)RESET_REASON_ADDR) == RESET_REASON_USER)
#define  SetUserReset()            (*((uint32_t*)RESET_REASON_ADDR) = RESET_REASON_USER)
#define  ClearUserReset()       (*((uint32_t*)RESET_REASON_ADDR) = 0)

4. Bootloader不对数据合法性进行检测,只对最后結果进行校验,在更新一个密钥不同的加密文件时可能会写入或者擦除不可知的区域。
/*0001*/  void  ProgramROM(uint32_t address, const uint32_t* buf, uint32_t size)
/*0002*/  {
/*0003*/      uint32_t row = (address-startAddress)/PAGE_SIZE;
/*0004*/      uint32_t bits = 1<<(row&31);
/*0005*/      //if(address & 0x80000000) return;
/*0006*/      /*    there is no need to check the address, ISP will do it
|*0007*|      if(g_u32FlashBaseAddress == APROM_BASE){
|*0008*|          // Program in APROM
|*0009*|          if( (address < g_u32FlashBaseAddress)
|*0010*|          ||  ((address+size) > (g_u32FlashBaseAddress + g_u32FlashSize))){
|*0011*|              // address out of range, do nothing here
|*0012*|              return;
|*0013*|          }
|*0014*|      }else{
|*0015*|          // Program in LDROM
|*0016*|          if( (address+size) > g_u32FlashSize ){
|*0017*|  
|*0018*|              return;
|*0019*|          }
|*0020*|      }*/

/*0021*/      row /= 32;
/*0022*/      if(row >= sizeof(pageUsage)/sizeof(pageUsage[0])){
/*0023*/          return;
/*0024*/      }

9.png (27.3 KB )

9.png

使用特权

评论回复
6
john_lee| | 2011-12-13 10:56 | 只看该作者
这个要顶!

使用特权

评论回复
7
lixiaoxu2meng| | 2011-12-13 11:09 | 只看该作者
原来楼主是只大牛啊 顶 以后还得多向楼主学习

使用特权

评论回复
8
plc_avr| | 2011-12-13 12:00 | 只看该作者
强!非常值得学习。

使用特权

评论回复
9
电子write_cai| | 2011-12-13 14:55 | 只看该作者
不错呀,还用到了linux平台呀。

使用特权

评论回复
10
chy117| | 2011-12-13 14:58 | 只看该作者
mark

使用特权

评论回复
11
weshiluwei6| | 2011-12-13 21:18 | 只看该作者
这么牛:kiss:

使用特权

评论回复
12
hotpower| | 2011-12-14 00:43 | 只看该作者
晕,250是俺的专利呀~~

使用特权

评论回复
13
毅如靳往| | 2011-12-14 10:42 | 只看该作者
好帖子需要支持   慢慢学习中

使用特权

评论回复
14
lxyppc|  楼主 | 2011-12-14 11:39 | 只看该作者
晕,250是俺的专利呀~~
hotpower 发表于 2011-12-14 00:43

呵呵,被俺借来用用,不会收专利费吧

使用特权

评论回复
15
Ryanhsiung| | 2011-12-14 11:51 | 只看该作者
不错,很牛 收藏了

使用特权

评论回复
16
murex| | 2011-12-14 21:01 | 只看该作者
一向都是先下,后顶,哈哈,秒霸果然牛哄哄

使用特权

评论回复
17
564451696| | 2011-12-15 13:16 | 只看该作者
牛,不是一般的牛,是只大水牛

使用特权

评论回复
18
缥缈九哥| | 2011-12-15 13:32 | 只看该作者
非常给力呀。我喜欢这种帖子。。

使用特权

评论回复
19
乡村男孩| | 2011-12-15 13:47 | 只看该作者
这个强悍得。。。

使用特权

评论回复
20
xukaiming| | 2011-12-15 13:47 | 只看该作者
想看代码~~~~~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:代码发BBS不好看?你需要它 代码着色https://bbs.21ic.com/icview-135254-1-1.html

27

主题

2249

帖子

19

粉丝