生成量产固件
按照本节流程编译加密的量产固件。
配置 U-Boot
- 进入 SDK
根目录:
cd <SDK_ROOT>
- 在 SDK
根目录,执行下列命令应用一个项目:
示例如下:
make d211_demo88_nand_defconfig
-
打开 U-Boot 的 menuconfig 菜单:
make uboot-menuconfig
-
勾选或确认已勾选下列选项:
ARTINCHIP_SPIENC AICUPG_FIRMWARE_SECURITY SPL_DRIVERS_MISC
对应的配置界面如下:SPL / TPL ---> [*] Support misc drivers Device Drivers ---> [*] Secure transfer firmware and burn Multifunction device drivers ---> [*] ArtInChip SPI Memory Encryption support
注:编译量产固件时,务必将编译烧录 eFuse 程序时的代码修改还原。 -
在正式版本的固件中,建议删除下列功能选项同时禁用 U-Boot 控制台,防攻击者通过控制台读出 Flash 中的数据,否则可跳过此步。
- 删除下列功能选项:
-
CMD_MEMORY
-
CMD_MTD
对应的配置界面如下:Command line interface ---> Memory commands ---> [ ] md, mm, nm, mw, cp, cmp, base, loop Device access commands ---> [ ] mtd
-
- 将 target/d211/common/env.txt 文件中 bootdelay 设置为 -2,禁用 U-Boot 控制台。
- 删除下列功能选项:
配置 Kernel
- 进入 SDK
根目录:
cd <SDK_ROOT>
-
打开 Kernel 的 menuconfig 菜单:
make kernel-menuconfig
-
在配置界面,勾选或确认已勾选下列参数:
CRYPTO_DEV_ARTINCHIP_SPIENC
参数对应的配置界面如下:-*- Cryptographic API ---> [*] Hardware crypto devices ---> [*] Support for artinchip cryptographic accelerator <*> Artinchip's SPI Bus on-the-fly encryption driver
配置 ITS
按照以下步骤配置和编译 U-Boot,并生成烧录固件。
- 在芯片级的 DTS 配置文件中使能 SPIENC
模块。
spienc: spienc@18100000 { compatible = "artinchip,aic-spienc-v1.0"; reg = <0x18100000 0x1000>; interrupts-extended = <&plic0 41 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cmu CLK_SPIENC>; resets = <&rst RESET_SPIENC>; aic,spienc-tweak = <0>; };
在板级的 DTS 配置文件 board.dts中,使能 SPIENC 模块。若要在 SPL 中使用 SPI_ENC,需设置标记u-boot,dm-pre-reloc
:&spienc { aic,spienc-tweak = <0>; status = "okay"; u-boot,dm-pre-reloc; };
-
DTS 中的
aic,spienc-tweak
参数可以影响 COUNTER 的生成,进而改变加密的结果。修改该值,可以在不同产品的相同数据上获得不同的加密结果。此时,还需要配置下列参数,对具体的 SPI NAND / SPI NOR 设备使能加密:-
aic,encrypt
:标记该存储设备使能 SPI_ENC -
aic,spi-id
:设置当前存储设备所挂载的 SPI 控制器 ID
board.dts 中的配置示例如下:&spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_pins_a>; status = "okay"; u-boot,dm-pre-reloc; spi-flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "spi-nand"; spi-max-frequency = <24000000>; spi-tx-bus-width = <1>; spi-rx-bus-width = <1>; reg = <0>; aic,encrypt; // 标记该存储设备使能 SPI_ENC aic,spi-id = <0>; // 设置当前存储设备所挂载的 SPI 控制器 ID status = "okay"; u-boot,dm-pre-reloc; }; };
-
-
在正式版本的固件中,建议禁用读写 Flash 和 Memory 相关的命令,同时禁用 U-Boot 控制台,防攻击者通过控制台读出 Flash 中的数据,否则可跳过此步。
将 target/d211/common/env.txt 文件中 bootdelay 设置为 -2,禁用 U-Boot 控制台。
固件签名加密
在 SDK/target/d211/demo88-nand/image_cfg.json 文件中进行下列配置,用于生成签名加密固件
-
配置生成签名的组件开启了安全启动后,需要对 U-Boot SPL 进行签名。参考签名相关部分的内容进行修改:
{ "spi-nand": { ... }, "image": { ... }, "info": { // Header information about image ... }, "updater": { // Image writer which is downloaded to RAM by USB/UART ... }, "target": { // Image components which will be burn to device's partitions ... }, "pre-process": { // before v1.0.6 is the name "temporary" "aicimage": { // Create aic boot image "usbupg-ddr-init.aic": { // No loader, only PreBootProgram to initialize DDR "head_ver": "0x00010001", "resource": { "private": "ddr_init.bin", "pubkey": "keys/rsa_public_key.der", // 签名相关 "pbp": "d211.pbp", }, "signature": { "algo": "rsa,2048", "privkey": "keys/rsa_private_key.der", // 签名相关 }, }, "pbp_ext.aic": { "head_ver": "0x00010001", "resource": { "pbp": "d211.pbp", "pubkey": "keys/rsa_public_key.der", // 签名相关 "private": "pbp_cfg.bin", }, "signature": { // 签名相关 "algo": "rsa,2048", "privkey": "keys/rsa_private_key.der", }, // combine to use with loader.aic "with_ext": "true", }, "spl.aic": { "head_ver": "0x00010001", "loader": { "file": "u-boot-spl-dtb.bin", "load address": "0x42000000", "entry point": "0x42000100", // 256 byte aic header }, "resource": { "private": "ddr_init.bin", "pubkey": "keys/rsa_public_key.der", // 签名相关 }, "signature": { // 签名相关 "algo": "rsa,2048", "privkey": "keys/rsa_private_key.der", }, }, }, }, }
-
对组件进行加密
在 image_cfg.json 的 “temporary” 或 “pre-process” 对象的最后,添加 “data_crypt” 对象配置。
此处使用的 AES 加密密钥,即为生成密钥章节 中SDK/target/<soc>/<board>/pack/keys/ 文件目录生成的密钥。
在下列示例中,配置了一组需要使用 “data_crypt” 工具进行加密的组件,其中生成u-boot-spl-dtb.aic.enc 组件的配置参数为:-
algo: 加密的算法
-
file: 加密的源文件,此处为前面生成的 u-boot-spl-dtb.aic 文件
-
key: 使用的加密密钥
-
nonce: 使用的加密 Nonce 值
-
tweak: 该值不需要配置,保持为 0 即可
{ "spi-nand": { ... }, "image": { ... }, "info": { // Header information about image ... }, "updater": { // Image writer which is downloaded to RAM by USB/UART ... }, "target": { // Image components which will be burn to device's partitions ... }, "pre-process": { // before v1.0.6 is the name "temporary" "data_crypt": { "u-boot-spl-dtb.aic.enc": { //加密 SPL 分区 "algo": "spienc-aes-128-ecb", "file": "u-boot-spl-dtb.aic", // File to be encrypted "key": "keys/spi_aes.key", // Keys the same in eFuse "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse "tweak": "0", }, "u-boot.itb.enc": { //加密 U-Boot 分区 "algo": "spienc-aes-128-ecb", "file": "u-boot.itb", // File to be encrypted "key": "keys/spi_aes.key", // Keys the same in eFuse "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse "tweak": "0", }, "env.bin.enc": { //加密 env 分区,备份分区使用同一个组件 "algo": "spienc-aes-128-ecb", "file": "env.bin", // File to be encrypted "key": "keys/spi_aes.key", // Keys the same in eFuse "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse "tweak": "0", }, "logo.itb.enc": { //加密 logo 分区 "algo": "spienc-aes-128-ecb", "file": "logo.itb", // File to be encrypted "key": "keys/spi_aes.key", // Keys the same in eFuse "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse "tweak": "0", }, "kernel.itb.enc": { //加密 kernel 分区 "algo": "spienc-aes-128-ecb", "file": "kernel.itb", // File to be encrypted "key": "keys/spi_aes.key", // Keys the same in eFuse "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse "tweak": "0", }, "recovery.itb.enc": { //加密 recovery 分区 "algo": "spienc-aes-128-ecb", "file": "recovery.itb", // File to be encrypted "key": "keys/spi_aes.key", // Keys the same in eFuse "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse "tweak": "0", }, "rootfs*.ubifs.enc": { //加密 rootfs 分区 "algo": "spienc-aes-128-ecb", "file": "rootfs*.ubifs", // File to be encrypted "key": "keys/spi_aes.key", // Keys the same in eFuse "nonce": "keys/spi_nonce.key", // Nonce the same in eFuse "tweak": "0", }, ... }, }, }
对于一个或者多个需要进行加密的组件,都应按照上述方式进行配置。
mk_image.py 工具在读取 image_cfg.json 文件时,逐个处理放在 “data_crypt” 中的配置,生成对应的加密组件,然后再进行打包。
重要:“data_crypt” 字段应放在 “temporary”/”pre-process” 的最后,因为处理 “data_crypt” 时,可能需要依赖前面配置生成的文件,比如 ”aicimage”。
-
-
配置烧录加密组件
在 image_cfg.json 中配置下列参数,打包加密组件,以适配烧录加密固件的要求:
-
updater 中打包的程序,应为非加密程序
updater 中配置的参数,都不是 .enc 结尾的组件
-
target 中打包的程序和数据,应为加密后的程序
target 中配置的参数,都是 .enc 结尾的组件
这是因为:-
SD 卡启动时,首先运行 updater 中的程序,进入烧录模式。此时由于数据是从 SD 卡加载的,不能为加密程序,否则无法正常执行
-
target 中打包的程序是要烧录到 Flash 的数据,如果不加密,则无法起到保护的作用,因此需要打包加密后的组件
{ "spi-nand": { // Device, The name should be the same with string in image:info:media:type ... }, "image": { ... }, "info": { // Header information about image ... }, "updater": { // Image writer which is downloaded to RAM by USB/UART "ddr": { "file": "usbupg-ddr-init.aic", "attr": ["required", "run"], "ram": "0x00103000" }, "env": { "file": "env.bin", "attr": ["required"], "ram": "0x41000000" }, "uboot": { "file": "u-boot.itb", "attr": ["required"], "ram": "0x41100000" }, "logo": { "file": "logo.itb" "attr": ["required"], "ram": "0x42400000" }, "spl": { "file": "u-boot-spl-dtb.aic", "attr": ["required", "run"], "ram": "0x40000000" }, }, "target": { // Image components which will be burn to device's partitions "spl": { "file": "u-boot-spl-dtb.aic.enc", //使用 enc 结尾的加密组件 "attr": ["mtd", "required"], "part": ["spl"] }, "uboot": { "file": "u-boot.itb.enc", //使用 enc 结尾的加密组件 "attr": ["mtd", "required"], "part": ["uboot"] }, "env": { "file": "env.bin.enc", //使用 enc 结尾的加密组件 "attr": ["mtd", "required"], "part": ["env","env_r"] }, "logo": { "file": "logo.itb.enc", //使用 enc 结尾的加密组件 "attr": ["mtd", "required"], "part": ["logo"] }, "kernel": { "file": "kernel.itb.enc", //使用 enc 结尾的加密组件 "attr": ["mtd", "required"], "part": ["kernel"] }, "recovery": { "file": "recovery.itb.enc", //使用 enc 结尾的加密组件 "attr": ["mtd", "required"], "part": ["recovery"] }, "rootfs": { "file": rootfs*.ubifs.enc", //使用 enc 结尾的加密组件 "attr": ["ubi", "required"], "part": ["ubiroot:rootfs"] }, }, "pre-process": { // before v1.0.6 is the name "temporary" ... }, }
-
USB 烧录
直接使用编译生成的 img 文件进行量产烧录即可。
SD 卡量产
-
标准方式
编译生成下列文件后,将其复制到 SD 卡 FAT32 文件系统的根目录中,等待平台重新上电即可进入烧录:
-
bootcfg.txt
- 打包后的 img 文件,例如d211_demo88_nand_page_2k_block_128k_v1.0.0.img
-
在修改 bootcfg.txt 文件后,确保使用 UNIX 格式的换行符,而非 DOS 格式的换行符,即 ‘\n’ 换行,而非 ‘\r\n’ 换行。