方案 V1
本节介绍了 SPI Flash 防抄板方案 V1 的详细配置说明,适用于 D12x/ D13x,本节以 D13x 开发板为例。
本方案通过使用 D13x 的 SPIENC 总线加密功能以及安全启动功能来实现防抄板,结合实际使用的需求,提供对应的软件方案。
SPI ENC 功能对应的 eFuse 烧录信息
- 
                            
SECURE 区域中的 SPI_ENC_EN 位。
 - 
                            
SECURE 区域中的 SECURE_BOOT_EN 位。
 - 
                            
SPI_ENC KEY 区域中的密钥内容。
 - 
                            
SPI_ENC NONCE 区域中的密钥内容。
 - 
                            
DIS RD/DIS WR 区域中,关于 SPI_ENC KEY/ NONCE 的读写禁止位。
 - 
                            
DIS WR 区域中,关于 ROTPK 的读写禁止位
 - 
                            
SECURE 区域中的 JTAG_LOCK 位 (可选,关闭 JTAG 更安全)。
 
相关信息可参考芯片用户手册 > 安全 > SID 章节。
| 用途 | 位数 | 地址 | 禁止位 | 禁写 | 禁读 | 归属 | 备注 | 
|---|---|---|---|---|---|---|---|
| DIS RD | 64 | 0~7 | 0~1 | V | CSTM | eFuse 读禁止配置区域 | |
| DIS WR | 64 | 8~F | 2~3 | eFuse 写禁止配置区域 | |||
| BROM | 64 | 30~37 | 12~13 | V | CSTM | BROM 参数配置区域 | |
| SECURE | 64 | 38~3F | 14~15 | V | CSTM | 安全和调试功能开关 | |
| ROTPK | 128 | 40~4F | 16~19 | V | CSTM | 安全,RSA 公钥的 MD5 Hash 值 | |
| SPI_ENC KEY | 128 | A0~AF | 40~43 | V | V | CSTM | 安全,连接到 SPI_ENC,对称密钥 | 
| SPI_ENC NONCE | 64 | B0~B7 | 44~45 | V | V | CSTM | 安全,连接到 SPI_ENC,随机数 | 
| 比特位 | 名称 | 描述 | 
|---|---|---|
| 31:25 | - | - | 
| 24 | PBP_ENC_EN | BROM 读取使用,使能 PBP 程序加密功能 | 
| 23:20 | - | - | 
| 19 | SPI_ENC_EN | BROM 读取使用,使能 SPI 总线数据加密功能 | 
| 18 | - | - | 
| 17 | ENCRYPT_BOOT_EN | BROM 读取使用,使能固件加密启动功能 | 
| 16 | SECURE_BOOT_EN | BROM 读取使用,使能安全启动功能 | 
| 15:1 | - | - | 
| 0 | JTAG_LOCK | 逻辑组合后连接到 CPU 屏蔽 TDO,关闭 JTAG 调试功能,在安全方案中烧录为 1 | 
烧录 eFuse
- 
                        
Key 的加工在编译时完成
 - 
                        
eFuse 的烧录在 BootLoader 中完成
 - 
                        
AIC 固件包支持两级 BootLoader, 即一个烧录用,一个为量产用
 
生成密钥
使用 SPIENC 加密功能,需要将一个 32 位的 AES 密钥和一个 16 位的 Nonce 值烧录到芯片 eFuse 中,同时在制作加密镜像时也需要使用上述值。因此,使用过程中,确保上述值保持不变且已妥善管理,以免泄露。
本节描述了生成 eFuse 烧录程序的详细流程。在示例方案中,提供了设置 AES/ NONCE 密钥的输入 txt 文件和一个用于生成及更新密钥的脚本:
- 
                        
SDK/target/d13x/demo88-nor/pack/keys/set_aes_key.txt:设置加密密钥,32 Byte
 - 
                        
SDK/target/d13x/demo88-nor/pack/keys/set_nonce.txt:设置加密的 NONCE 参数, 16 Byte
 - 
                        
SDK/target/d13x/demo88-nor/pack/keys/gen_spienc_key.bat :Windows 上执行编译时,使用该脚本。
脚本通用,可以直接从示例方案中复制。
 - 
                        
SDK/target/d13x/demo88-nor/pack/keys/gen_spienc_key.sh: Linux 上执行编译时,使用该脚本
脚本通用,可以直接从示例方案中复制。
 
根据下列步骤流程,生成密钥:
- 
                    
准备初始密钥文件 set_aes_key.txt 和 set_nonce.txt。
set_aes_key.txt 和 set_nonce.txt 文件中有一个初始密钥,需要手动修改其中的HEX密钥内容。cat set_aes_key.txt 0123456789abcdef0123456789abcdef cat set_nonce.txt 0123456789abcdef - 
                    确保已经安装 OpenSSL。如未安装,可执行以下命令进行安装:
sudo apt-get install openssl
 - 进入开发板根目录:
cd SDK/target/<soc>/<board>/pack/keys/
例如:
cd SDK/target/d13x/demo88-nand/pack/keys/
 - 
                    使用下列命令运行脚本生成所需的密钥文件和头文件:
- 在 Linux
                                环境下:
./gen_spienc_key.sh
 - 在 Windows
                                环境下:
gen_spienc_key.bat 
生成的文件如下所示:- 
                                
AES 密钥 spi_aes.key
 - 
                                
AES 对应的 C 语言头文件 spi_aes_key.h
 
- 
                                
spi_nonce.key
 - 
                                
rotpk.bin
 - 
                                
rsa_private_key.der
 - 
                                
rsa_private_key.pem
 - 
                                
rsa_public_key.der
 - 
                                
rsa_public_key.pem
 
 - 在 Linux
                                环境下:
 将 spi_aes_key.h 文件复制粘贴至下列目录中,供编译烧录 eFuse 的程序时使用:
spi_aes.key 和其它文件则保留在 SDK/target/<SoC>/<board>/pack/keys/,用于 mk_image.py 生成加密固件时使用,例如 SDK/target/d13x/demo88-nand/pack/keys/
重要: 生成的密钥务必妥善保管,以免丢失或者泄露。目录下有 set_aes_key.txt 和 set_nonce.txt,里面有一个初始秘钥, 用户需要手动修改 txt 中的 HEX 秘钥内容,然后再运行脚本更新秘钥。
编译程序
按照以下步骤配置和编译程序,并生成烧录固件。
- 
                        进入 SDK 根目录:
cd <SDK_ROOT>
 - 
                        
应用一个项目配置,例如:
scons --apply-def=d13x_demo88-nand_baremetal_bootloader_defconfig
 - 
                            执行下列命令打开 menuconfig 菜单:
scons --menuconfig
 - 
                            分别勾选或者确认已勾选下列参数:
AIC_USING_SID EFUSE_WRITE_SUPPORT AIC_SID_BURN_SPIENC_KEY_TEST AIC_USING_SPIENC AICUPG_FIRMWARE_SECURITY
参数对应的界面配置具体如下:
Board options ---> [*] Using Spienc [*] Enc qspi0 (0) set qspi0 tweak [*] Using Efuse/SID SID Parameter ---> [*] support efuse write (64) set efuse max word Bootloader options ---> [*] Upgrading ---> [*] Secure transfer firmware and burnDrivers options ---> Drivers examples ---> [*] Enable SID burn spienc key command - 打开 BootLoader 的 eFuse DEBUG 模式:重要: DEBUG 模式仅 调试时 使用,用于校对秘钥是否正确。烧录过程会将秘钥写入 eFuse 中,但不会禁用其读写功能,秘钥还可以通过 CPU 读取出来。在确认秘钥都正确后,需关闭该配置禁用 eFuse 对应读写权限。确保量产时关闭 DEBUG 模式。
AIC_SID_BURN_DEBUG_MODE对应配置项:Drivers options ---> Drivers examples ---> [*] Enable SID burn spienc key command [*] Enable SID debug mode - 
                            
添加代码调用命令烧写 eFuse:
SDK 默认不调用烧录 eFuse 命令,需要手动添加。
- 
                                    
application/baremetal/bootloader/main.c:
在console_set_usrname之后,添加上一个命令执行代码console_run_cmd(“efuse_spienc”);,如下所示。application/baremetal/bootloader/main.c: int main(void) { console_init(); console_set_usrname("aic"); int result = console_run_cmd("efuse_spienc"); // 加上此句,examples_bare/test-efuse/efuse_burn_spienc_key_cmd.c ... } - 
                                    
bsp/examples_bare/test-efuse/efuse_burn_spienc_key_cmd.c:
如果不需要关闭 JTAG,可以将 burn_jtag_lock_bit() 相关的调用注释掉。
 
 - 
                                    
 - 
                            编译程序 BootLoader:
scons # build BootLoader
 - 
                            编译程序 APP 并且生成烧录固件:
scons --apply-def=d13x_demo88-nand_rt-thread_helloworld_defconfig
scons
编译结果会保存至 SDK/output/<SoC name>_<board name_rt-thread_helloworld/images 目录。例如,SDK/output/d13x_demo88-nor_rt-thread_helloworld/images
 
AiBurn 烧录
使用 AiBurn 烧录生成的镜像,可选择分区烧录只烧录 BootLoader。详情可查看 AiBurn 使用指南。
SD 卡烧录
- 准备一张 SD 卡,确保该卡只有一个分区,并且格式化为 FAT32/ exFAT 文件系统。
 - 将编译输出目录下的文件复制到 SD 卡的根目录:
- 
                        
bootcfg.txt
 - 
                        
bootloader.aic
 
 - 
                        
 - 
                将 bootcfg.txt 中的内容修改为:
boot0=bootloader.aic
 - 
                
将该卡插到板卡中,上电运行,即可完成相关 eFuse 的烧录。
 
烧录日志
tinySPL [Built on Feb 27 2025 11:21:57] BROM SPIENC is ENABLED JTAG LOCK is ENABLED SPI ENC KEY: 0x406efde8 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //烧录后的 key 对 CPU 不可见,所以无法读出 SPI ENC Key is read DISABLED SPI ENC Key is write DISABLED
生成量产固件
按照本节流程编译加密的量产固件。
配置 BootLoader
- 进入 SDK
                        根目录:
cd <SDK_ROOT>
 - 在 SDK
                    根目录中执行下列命令:
scons --apply-def=d13x_demo88-nand_rt-thread_bootloader_defconfig
 - 
                        使用以下任意命令,打开 BootLoader 的 menuconfig 菜单:
或bmscons --menuconfig
 - 
                        在配置界面,勾选或确认已勾选下列参数:
AIC_USING_SPIENC AICUPG_FIRMWARE_SECURITY
参数对应的配置界面如下:Board options ---> [*] Using Spienc [*] Enc qspi0 (0) set qspi0 tweak [*] Using Efuse/SID SID Parameter ---> (64) set efuse max word Bootloader options ---> [*] Upgrading ---> [*] Secure transfer firmware and burn重要:编译量产固件时,需将编译烧录 eFuse 程序时的代码修改还原。
 - 
                        在正式发布的固件中,建议将下列参数选项去掉,防止攻击者通过控制台读出 Flash 中的数据,否则可跳过:
AIC_BOOTLOADER_CMD_MTD AIC_MTD_BARE_TEST
参数对应的功能配置界面如下:BootLoader options ---> Commands ---> [ ] mtd read/write Drivers options ---> Drivers examples ---> [ ] Enable MTD driver test command 
配置应用程序
- 进入 SDK
                        根目录:
cd <SDK_ROOT>
 - 在 SDK
                    根目录,执行下列命令:
scons --apply-def=d13x_demo88-nand_rt-thread_bootloader_defconfig
 - 
                    使用以下任意命令,打开 Application 的 menuconfig 菜单:
或bmscons --menuconfig
 - 
                        勾选或确认已勾选下列选项:
AIC_USING_SPIENC
对应的配置界面如下:Board options ---> [*] Using Spienc [*] Enc qspi0 (0) set qspi0 tweak - 
                        
在正式版本的固件中,建议删除 bsp/examples/test-spinor/test_sfud.c bsp/examples/test-spinor/test_fal.c bsp/examples/test-spinand/test_mtd.c 文件中的 sf、 fal 和 mtd_nand 命令命令,防攻击者通过控制台读出 Flash 中的数据,否则可跳过此步。
 
固件签名加密
在 SDK/target/<SoC>/<board>/pack/image_cfg.json 文件中进行配置并生成签名加密固件,例如 SDK/target/d13x/demo88-nand/pack/image_cfg.json。
- 
                    配置生成签名的组件开启了安全启动后,需要对 BootLoader 进行签名。参考签名相关部分的内容进行修改:
{ "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": "d13x.pbp",or }, "signature": { "algo": "rsa,2048", "privkey": "keys/rsa_private_key.der", // 签名相关 }, }, "pbp_ext.aic": { "head_ver": "0x00010001", "resource": { "pbp": "d13x.pbp",or "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", }, "loader.aic": { "head_ver": "0x00010001", "loader": { "file": "bootloader.bin", "load address": "CONFIG_AIC_BOOTLOADER_LOAD_BASE", "entry point": "CONFIG_AIC_BOOTLOADER_TEXT_BASE", // 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", }, }, }, }, } - 生成烧录器量产固件在 SDK 根目录执行
me 或者 scons --menuconfig打开配置界面进行如下配置。Application options ---> [*] Generate burner format image配置完成后进行编译,编译完成后在编译输出目录 (images)/burner下找到烧录器烧录所使用到的镜像,例如 d13x_demo88-nor_page_2k_block_128k_v1.0.0.bin。
 - 对烧录器量产固件进行加密执行下列命令:
tools/scripts/spienc --key spi_aes.key --nonce spi_nonce.key --tweak 0x0 --addr 0x0 --start 0x0 --input d13x_demo88-nor_page_2k_block_128k_v1.0.0.bin --output d13x_demo88-nor_page_2k_block_128k_v1.0.0.bin.enc- 
                                
key: 使用的加密秘钥。
 - 
                                
nonce: 使用的加密 Nonce 值。
 - 
                                
tweak: 该值不需要配置,保持为 0 即可。
 - 
                                
addr: 该值不需要配置,保持为 0 即可。
 - 
                                
start: 该值不需要配置,保持为 0 即可。
 - 
                                
input: 加密的源文件,此处为前面生成的量产烧录器固件 (d13x_demo88-nor_page_2k_block_128k_v1.0.0.bin) 文件。
 - 
                                
output: 加密后的文件,此处为固件 (d13x_demo88-nor_page_2k_block_128k_v1.0.0.bin.enc)文件。
 
注:此处使用的 AES 加密密钥,即为生成密钥章节中SDK/target/<soc>/<board>/pack/keys/ 文件目录生成的密钥。
 - 
                                
 
量产
本节介绍了不同量产方式的操作步骤。
USB 烧录
直接使用编译生成的 img 文件进行量产烧录即可。
SD 卡量产
- 
                        标准方式
编译生成下列文件后,将其复制到 SD 卡 FAT32 文件系统的根目录中,等待平台重新上电即可进入烧录:
- 
                                    
bootcfg.txt
 - 
                                    
打包后的 img 文件,例如 d13x_demo88-nand_v1.0.0.img
 
 - 
                                    
 - 
                        Direct Mode
修改 bootcfg.txt,并且将 bootcfg.txt 和使用到的组件复制到 SD 卡 FAT32 文件系统的根目录,等待平台重新上电即可进入烧录模式。
bootcfg.txt 示例:
boot0=bootloader.aic writetype=spi-nand writeintf=0 write0=bootloader.aic.enc write1=d21x_os.itb.enc,0x40000 write2=rodata.fatfs.enc,0x240000 write3=data.fatfs.enc,0x840000
 
在修改 bootcfg.txt 文件后,确保使用 UNIX 格式的换行符,而非 DOS 格式的换行符,即 ‘\n’ 换行,而非 ‘\r\n’ 换行。
eFuse 与固件合并烧录
将 eFuse 和量产固件分开可以放松对固件的管控,但需要进行两次烧录,同时 eFuse 的固件和量产固件必须要匹配才能生产。为了降低使用难度,可以把 eFuse 和量产固件的烧录合并到同一个固件中进行,但因为该固件包含了要烧录的 Key,需要对该固件进行保护。
实现方法是通过在 eFuse 烧录完成后继续运行,烧录固件,需要配置 BootLoader 宏 AIC_SID_CONTINUE_BOOT_BURN_AFTER。
- 进入 SDK
                    根目录:
cd <SDK_ROOT>
 - 在 SDK
                    根目录中执行下列命令:
scons --apply-def=d21x_demo88-nand_rt-thread_bootloader_defconfig
 - 
                    打开 BootLoader 的 menuconfig 菜单:
scons --menuconfig - 
                    在配置界面,勾选或确认已勾选下列参数:
AIC_USING_SID EFUSE_WRITE_SUPPORT AIC_SID_BURN_SPIENC_KEY_TEST AIC_SID_CONTINUE_BOOT_BURN_AFTER AIC_USING_SPIENC AICUPG_FIRMWARE_SECURITY
参数对应的配置界面如下:
Board options ---> [*] Using Spienc [*] Enc qspi0 (0) set qspi0 tweak [*] Using Efuse/SID SID Parameter ---> [*] support efuse write (64) set efuse max word Bootloader options ---> [*] Upgrading ---> [*] Secure transfer firmware and burnDrivers options ---> Drivers examples ---> [*] Enable SID burn spienc key command [*] Enable SID continue to boot after burning 
