5. FIP 签名与加密及 eFuse

本章说明在本仓库中对 fip.bin签名与加密,并配合 eFuse 烧录,使 ROM/BL1 只执行受信任的 FIP。若还需 boot.spinor 内 FIT 的验签或加密,见 FIT 镜像安全启动

所有命令均在 mars 根目录 执行(U-Boot 内 eFuse 命令除外);须先依次执行 source build/envsetup_soc.shdefconfig ,将后者参数换为实际板型名。

5.1. 生成 FIP 用的密钥

只做一次,密钥妥善保存。

KEY_DIR="$(pwd)/my_fip_keys"
mkdir -p "$KEY_DIR"
openssl genrsa -out "${KEY_DIR}/rsa_hash0.pem" -F4 2048
openssl genrsa -out "${KEY_DIR}/bl_priv.pem" -F4 2048
head -c 16 /dev/random > "${KEY_DIR}/loader_ek.key"
head -c 16 /dev/random > "${KEY_DIR}/bl_ek.key"
chmod 600 "${KEY_DIR}"/*.pem "${KEY_DIR}"/*.key 2>/dev/null || true

得到:rsa_hash0.pembl_priv.pemloader_ek.keybl_ek.key

5.2. 打开 FSBL 安全启动并编译

  • menuconfig 中:FIP setting → 勾选 Add secure boot support to FSBL → 保存退出。

或直接在板级 defconfig 中加入:

CONFIG_FSBL_SECURE_BOOT_SUPPORT=y

执行 build_all 完成编译。完成后在 install/ 下对应板型的 soc_* 子目录中可得到 fip.bin 等(具体以板级配置为准)。

注解

若启用内核 FIT 安全启动,还需按 FIT 镜像安全启动 配置内核与 U-Boot,并与本章 build_all 在同一套配置下完成。

5.3. 对 FIP 做签名与加密

在 mars 根目录执行(将 KEY_DIRFIP_INFIP_OUT 换成实际路径与板子输出目录):

KEY_DIR="$(pwd)/my_fip_keys"
FIP_IN=install/soc_cv1842hp_wevb_0014a_spinor/fip.bin
FIP_OUT=install/soc_cv1842hp_wevb_0014a_spinor/fip_enc.bin
python3 fsbl/plat/cvitek/cv184x/common/fipsign.py sign-enc \
         --root-priv="${KEY_DIR}/rsa_hash0.pem" \
         --bl-priv="${KEY_DIR}/bl_priv.pem" \
         --ldr-ek="${KEY_DIR}/loader_ek.key" \
         --bl-ek="${KEY_DIR}/bl_ek.key" \
         "$FIP_IN" "$FIP_OUT"

得到形如 install/soc_xxx/fip_enc.bin 的输出(xxx 为板型目录名)。仅签名不加密时可改用 sign 子命令,参数见 fipsign.py --help

5.4. 获取 eFuse 要烧写的值(开发机)

5.4.1. HASH0_PUBLIC(64 位十六进制)

需安装 PyCryptodome:

python3 -c "
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
key = RSA.import_key(open('my_fip_keys/rsa_hash0.pem').read())
n = key.n.to_bytes(256, 'big')
print(SHA256.new(n).digest().hex())
"

5.4.2. LOADER_EK(32 位十六进制)

xxd -p -c 256 my_fip_keys/loader_ek.key | tr -d '\n'

5.5. 烧写 eFuse(U-Boot 中,一次性、不可逆)

将占位符替换为上一节得到的值后,在 U-Boot 中按顺序执行:

efusew HASH0_PUBLIC <64位十六进制>
efusew LOADER_EK <32位十六进制>
efusew LOCK_WRITE_LOADER_EK  01
efusew LOCK_WRITE_HASH0_PUBLIC  01
efusew SECUREBOOT 02

顺序以芯片与厂商文档为准;锁与 SECUREBOOT 烧写后即生效,无法撤销

注解

注意事项

eFuse 烧写为不可逆行为,执行前请确认镜像与密钥规划已核对无误。

5.6. 烧录镜像(eFuse 烧写完成之后)

  • FIP 分区:将 fip_enc.bin 作为实际烧写内容,按原 fip.bin 用法并 改名为 fip.bin 后烧录。勿使用未签名的原始 fip.binfip_spl.bin

  • 其它分区:与平时一致,例如 boot.spinor → BOOT,rootfs.spinor → ROOTFS,data.spinor → DATA,yoc.bin → 2nd 等。

  • 顺序:先完成 eFuse 烧录,再烧录镜像及各分区。若先烧加密 FIP 再烧 eFuse,可能无法启动,需用未加密的 fip.bin 重烧 FIP 等方式恢复。

5.7. 流程简表(FIP 侧)

阶段

步骤

内容

准备

0

(可选)FIT 安全启动见 FIT 镜像安全启动

密钥

1

生成 FIP 密钥目录 my_fip_keys

配置与编译

2

menuconfig 打开 FSBL Add secure boot support;build_all

签名加密

3

fipsign.py sign-enc 得到 fip_enc.bin

eFuse 取值

4

开发机计算 HASH0_PUBLIC;读取 LOADER_EK

eFuse 烧录

5

U-Boot 中 efusew(HASH0_PUBLIC、LOADER_EK、LOCK、SECUREBOOT)

分区烧录

6

以 fip_enc.bin 替换原 fip.bin 并仍命名为 fip.bin 后烧 FIP;其它分区照旧

5.8. FIP 密钥一览(my_fip_keys/)

文件

用途

rsa_hash0.pem

签署 FSBL(BL2)的 RSA 私钥;其公钥哈希烧入 eFuse HASH0_PUBLIC

bl_priv.pem

签署 Monitor/U-Boot 的 RSA 私钥

loader_ek.key

加密 FSBL 的 AES 密钥(16 字节);烧入 eFuse LOADER_EK

bl_ek.key

加密 Monitor/U-Boot 的 AES 密钥(16 字节)

5.9. 与 FIT 的关系

  • FIT:保护 boot.spinor,由 U-Boot 验签或解密,见 FIT 镜像安全启动

  • FIP:保护 fip.bin,由 ROM/BL1 验签与解密。

两者可同时使用:先完成 FIT 侧打包与烧录策略,再对 fip.binsign-enc;烧录时用 fip_enc.bin 替换并改名为 fip.bin 写 FIP 分区,BOOT 分区写已签名或加密的 boot.spinor