安全引导加载

butterfli的片上ROM包含一个安全引导加载 (bootloader),其特性有:

  • UART下载

  • 使用AES加密传输image文件,Flash上可保存加密image,由硬件实时解密执行,也支持明文image

  • 加密保存image密钥,即使复制了加密image,也无法在一颗不同的butterfli芯片上执行

  • 使用RSA数字签名验证image文件完整性,防止下载非法的image文件

  • PingPong下载

  • 安装Patch,修改Flash驱动

密钥

bootloader使用的密钥有:

  • rootkey: 保存于efuse的不可读区域,用于加密image密钥

  • image密钥: image加解密使用的密钥,经rootkey加密后保存于Flash

  • 数字签名RSA公钥: 用于解密验证image身份和完整性

  • UID: 芯片ID,保存于efuse的可读区域,作为nonce参数加密image密钥

image的加密下载过程:

  1. 将rootkey、数字签名公钥的hash和UID写入efuse (只需一次)

  2. 下载Flash配置表和数字签名公钥到Flash (只需一次)

  3. 使用image密钥对image进行加密,使用SHA256计算加密后数据的hash,使用数字签名私钥加密hash得到数字签名, image header(使用rootkey加密,包含image密钥等信息)、加密image和数字签名三者打包生成最终的加密image

  4. 传输加密image,bootloader从image header中提取image密钥对image进行解密,接收完成后比对数字签名确认来源并验证完整性,若合法则下载成功

启动模式

可以通过bootmode跳线设置bootloader的启动模式,若跳线接0,则为正常启动,bootloader读取flash判断是否可以引导用户程序,若跳线接1,则进入下载模式,等待PC发送下载命令, 在正常启动模式如果发现flash上没有有效的用户image,则自动进入下载模式

Memory规划

默认的Flash地址空间规划

名称

起始地址

结束地址

大小(字节)

描述

Flash配置表

0x10000000

0x10004FFF

20*1024

校准表

0x10005000

0x10006FFF

8*1024

保留

0x10007000

0x1000FFFF

36*1024

bootrom patch

0x10010000

0x1001FFFF

64*1024

User Code

0x10020000

其中Flash配置表的位置和格式不可修改,其他表项的地址和大小由Flash配置表指定

Flash配置表格式

名称

起始偏移

结束偏移

大小(字节)

描述

MAGIC

0x00000000

0x00000003

4

0x53454346

Flash分区表

0x00000004

0x00000103

16*16

16个分区

数字签名公钥

0x00000104

0x00000229

294

DER格式的RSA公钥

保留

0x0000022A

0x00000FFF

3542

image描述表

0x00001000

0x00002BFF

14*512

14个image描述条目,

image索引表

0x00002C00

0x00002C0F

4*4

指向激活(当前运行 )的image描述表条目

Flash分区表由16个分区信息组成,每个分区信息指定分区的起始地址和大小

分区表

索引

名称

描述

0

Flash分区表

1

校准表

2

LCPU image Ping区

3

BCPU image Ping区

4

HCPU image Ping区

5

Flash Boot patch区

6

LCPU image Pong区

7

BCPU image Pong区

8

HCPU image Pong区

9

RAM Boot patch区

10

HCPU image扩展区1

11

HCPU image扩展区2

12

LCPU image扩展区1

13

LCPU image扩展区2

14

保留

15

保留

分区信息格式

名称

大小(字节)

描述

分区起始地址

4

分区的起始地址

分区大小

4

分区大小

分区执行地址

4

对于image分区,指定该分区的执行地址

标志

4

未使用

下表为默认的Flash配置表,struct sec_configuration是Flash配置表的数据结构名

const struct sec_configuration sec_config =
{
    .magic = SEC_CONFIG_MAGIC,
    .ftab[0] = {.base = 0x10000000,      .size = 20*1024,      .xip_base = 0,          .flags = 0},
    .ftab[1] = {.base = 0x10005000,      .size = 8*1024,       .xip_base = 0,          .flags = 0},
    .ftab[4] = {.base = 0x10020000,      .size = 0x80000,      .xip_base = 0x10020000, .flags = 0},
    .ftab[5] = {.base = 0x10010000,      .size = 64*1024,      .xip_base = 0x10010000, .flags = 0},
    .ftab[8] = {.base = 0x10020000,      .size = 0x80000,      .xip_base = 0x10020000, .flags = 0},
    .ftab[9] = {.base = 0x20050000,      .size = 64*1024,      .xip_base = 0x20050000, .flags = 0},
    .imgs[0]  = {.length = 0xFFFFFFFF},                                       //LCPU ping
    .imgs[1]  = {.length = 0xFFFFFFFF},                                       //BCPU ping
    .imgs[2]  = {.length = 0x80000, .blksize = 512, .flags = DFU_FLAG_AUTO},  //HCPU ping
    .imgs[3]  = {.length = 0xFFFFFFFF},                                       //Flash boot patch
    .imgs[4]  = {.length = 0xFFFFFFFF},                                       //LCPU pong
    .imgs[5]  = {.length = 0xFFFFFFFF},                                       //BCPU pong
    .imgs[6]  = {.length = 0xFFFFFFFF},                                       //HCPU pong
    .imgs[7]  = {.length = 0xFFFFFFFF},                                       //RAM boot patch   
    .imgs[8]  = {.length = 0xFFFFFFFF},
    .imgs[9]  = {.length = 0xFFFFFFFF},
    .imgs[10] = {.length = 0xFFFFFFFF},
    .imgs[11] = {.length = 0xFFFFFFFF},
    .imgs[12] = {.length = 0xFFFFFFFF},
    .imgs[13] = {.length = 0xFFFFFFFF},
    .running_imgs[0] = (struct image_header_enc *)0xFFFFFFFF,
    .running_imgs[1] = (struct image_header_enc *)0xFFFFFFFF,
    .running_imgs[2] = (struct image_header_enc *) &sec_config.imgs[2],
    .running_imgs[3] = (struct image_header_enc *)0xFFFFFFFF,
};

Bootrom使用下表所示的RAM地址空间,当使用bootrom引导用户程序在RAM中执行时,需要避免地址空间冲突

bootloader RAM地址空间

名称

起始地址

结束地址

大小(字节)

描述

DATA

0x20040000

0x2004FFFF

64*1024

Bootrom数据

PATCH CODE

0x20050000

0x2005FFFF

64*1024

Patch代码

PATCH DATA

0x20060000

0x2006FFFF

64*1024

Patch数据

加密image的生成与下载

不使用bootloader下载

使用JTAG下载SDK提供的默认Flash配置表到0x10000000地址,再下载未加密的用户image到地址0x10020000,复位后bootloader即可引导用户image运行,用户image使用0x10020000地址编译

使用bootloader下载

相关工具在$sdk_root/tools/secureboot下,bootloader使用芯片的UART4作为下载串口

生成密钥

执行脚本genkeys.bat生成UID、rootkey、数字签名密钥和公钥hash,

genkeys.bat sifli01

sifli01为生成密钥的路径,运行后会生成如下几个文件

名称

描述

s01.bin

rootkey

uid.bin

rootkey

sig_hash.bin

数字签名公钥hash

sig_pri.pem

数字签名私钥

sig_pub.pem

数字签名公钥

sig_pub.der

DER格式的数字签名公钥

烧写密钥

将密钥烧写到efuse中只能执行一次,烧写后无法再修改efuse中的密钥

  1. 将butterfli的bootmode跳线设为下载模式

  2. 复位后进入bootloader下载模式

  3. 运行脚本program_efuse.bat烧写密钥,第一个参数为密钥所在路径,第二个参数为串口号

program_efuse.bat sifli01/ COM3
  1. 复位芯片,使得密钥被正确加载

下载Flash配置表

  1. 进入bootloader下载模式

  2. 运行脚本factory_flash_default.bat下载flash配置表(ftab\ftab_flash_default.json)和数字签名公钥,第一个参数为密钥所在路径,第二个参数为串口号

factory_flash_default.bat sifli01/ COM3

如果Flash配置表没有变化,更新image时不需要再次下载

生成image

加密image

运行gen_sec_img.bat,第一个参数为密钥所在路径,第二个参数为待加密的image路径,生成的加密image名为image_sec.bin

gen_sec_img.bat sifli01/ example.bin
明文image

运行gen_plain_img.bat,第一个参数为密钥所在路径,第二个参数为待加密的image路径,生成的加密image名为image_plain.bin

gen_plain_img.bat sifli01/ example.bin

下载image

加密image

运行download_sec_image.bat, 指定的port为bootloader所使用的串口

download_sec_image.bat --port=COM3

明文image

运行download_plain_image.bat,指定的port为bootloader所使用的串口

download_plain_image.bat --port=COM3