Hi35xxVxxx 安全启动使用指南
前言
本文档主要是指导使用本安全启动方案的相关人员了解整个安全方案的流程,再通过一定的操作步骤和方法来使用本安全启动方案。主要介绍本安全启动的规格和特性,包括安全启动基本流程和key的层级结构与验签逻辑,及其整个安全启动方案的使用。
说明:
以下描述以Hi3516CV610为例,如无特殊说明,Hi3516CV608的描述与Hi3516CV610一致。
与本文档相对应的产品版本如下。
本文档(本指南)主要适用于以下工程师:
- 技术支持工程师
- 软件开发工程师
在本文中可能出现下列标志,它们所代表的含义如下。
启动特性
安全特性
芯片内置OTP资源
OTP是一种特殊的非易失性存储器,允许编程一次,数据永久有效。利用OTP一次性编程的物理特性保存一些不可逆控制开关、硬件根密钥等。其中,密钥区域提供多个对称根密钥Slot,用于存储多个对称根密钥。密钥区域只能一次烧写,自动锁定,且不可回读。状态控制区域和用户自定义区域,可多次烧写,对应比特位只能由0编程为1,已经为1的比特不可更新;如果需要一次烧写后,其内容不可更改,则可在数据写入后,锁定该区域。版本控制区域可多次烧写,所有比特只能由0写为1,不可逆,也不可锁定。
内置密钥管理模块
对于已经烧写进OTP的每一个对称根密钥,密钥管理模块会根据相应的外部输入(密钥派生材料),进行多级派生,生成对应的工作密钥,并将工作密钥直接送到加解密引擎,实现对最终的数据进行加解密运算。整个密钥派生过程都在硬件逻辑内部完成,根密钥、密钥保护密钥、工作密钥都不会在内存中出现,也不能通过软件读取,提升了密钥的安全性。
镜像验签
使用密码学工具保证Flash中的镜像不被篡改。
镜像加密
镜像加密保存在 Flash 中,运行时在板端解密。
版本防回滚
芯片OTP中预留版本控制区域,以便安全启动、安全升级中,实现版本防回滚控制,防止攻击者利用某个有缺陷的历史版本,回退替换新版本对设备进行攻击。
镜像结构统一
安全启动和非安全启动镜像结构统一,适用于产线烧写场景。在没有镜像加密的情况下,可以直接烧写安全镜像到没有烧写 OTP 的裸设备并通过非安全启动流程启动。烧写安全 OTP 后通过安全流程启动。
安全启动涉及较多的密钥和签名,需要附加在最终镜像中。为避免镜像制作和使用过程因多个版本而引入的各种问题,降低使用难度,本启动方案将安全启动、非安全启动的所使用的镜像统一为一种格式。在SoC不使能安全启动的情况下,非加密的安全启动镜像(带有对应的公钥和签名),仍可正常启动。
安全模拟
安全模拟功能仅适用于OEM安全启动调试阶段,防止误烧 OTP 造成芯片不可用。
安全模拟包括两部分功能:一方面是对镜像验签模拟,另一方面是对镜像加解密模拟。
安全验签模拟功能表示仅通过 Flash 镜像中的标识决定是否使能校验。不需要烧写校验使能 OTP,只需烧写校验所需的根公钥Hash。一旦发现 OTP 误烧,安全校验不通过,可以通过重烧非安镜像启动设备。
安全加解密模拟功能表示仅通过 Flash 镜像中的标识决定是否使能加解密。不需要烧写解密使能 OTP,只需烧写校验所需的root key,便可以对镜像加解密进行模拟。
注意:
只有No TEE安全模拟的SoC可以通过重烧非安镜像启动设备。
支持TEE OS安全内核
安全启动方案支持从硬件->可信根->BOOTROM->SecureBootloader(GSL)->TEE OS以及REE侧各部分的可信校验,即TEE信任链和REE信任链分离。
启动阶段Flash提频
加速启动镜像读写,提高启动速度。启动阶段 Flash 接口时钟频率可选。
安全boot镜像备份
在安全启动场景下,支持烧写一个备份 Boot Image。当主 Boot Image 校验失败,引导程序会从启动介质搜寻可用的备份 Boot Image,并引导启动。
多boot表格
支持在镜像中配置多个boot表格,通过修改 GSL 代码中多表格函数钩子,实现一个镜像可适配多种板型。
启动方案
非安全启动

非安全启动,也就是没有验签的启动过程。芯片上电后 GSL 作为一级 bootloader 负责初始化 DDR 并加载 U-Boot。U-Boot 通过命令行加载 Kernel。非安全启动的总体流程如图1所示。
安全启动

安全启动与非安全启动相比多了对 GSL、U-Boot 的验签过程。在有 TEE 的情况下, 由 GSL 对 TEE OS 进行验签。
GSL 的验签由固化在 SoC 里的 BootRom 负责。U-Boot, TEE OS 的验签由 GSL 负责。验签失败则 SoC复位,保证 SoC 不会运行恶意镜像。
使能 TEE 的场景下,GSL 和 TEE OS 都运行在 TEE 环境下。TEE OS 由 GSL 启动,启动完成后,设备回到 U-Boot 环境验签并启动 Linux。
镜像验签与加密
本节中介绍了以下内容:
- 介绍镜像的验签与加解密原理。
- 验签信任链。描述了如何通过 OTP 如何保证镜像不被篡改。
- 密钥派生关系与加解密。根密钥如何派生出各个工作密钥,并用工作密钥解密镜像。
本节中会尽量使用密码学中的概念来描述启动方案中的安全机制。
镜像验签
安全方案中的验签方法结合了非对称验签与哈希机制。
图1展示了通用验签流,对每一个需要验签的 Code 区都会经过如下的验签链。其中根公钥校验章节和外部公钥对镜像校验章节展示了校验的手段。

根公钥校验
通过在板端计算根公钥的Hash值和OTP 中的值比较实现校验。Hash 算法可通过 OTP 选择为 SHA256 。
外部公钥对镜像校验
外部公钥对 Code 区的校验相对复杂。镜像布局和验签关系见图1。需要通过根公钥->Key Area->Code Info->Code这一验签链实现完整的镜像验签。
外部公钥保存在 Key Area里。对 Key Area的验签需要通过根公钥或者已经被校验过的上一级外部公钥实现验签。Key Area 中包含了上一级公私钥对的签名。
外部公钥被验签完成后,使用外部公钥对 Code Info验签。外部公钥的签名被保存在 Code Info 区。
Code Info 中保存了 Code 的 Hash 值,通过比较镜像Code区的 Hash 值和保存在 Code Info 中的 Hash 值可以确保镜像没有被篡改。

验签链与验签中的角色
图1中展示了完整的验签关系。上级公钥经过验签后再去验签下一级。整个验签的过程发生在已经被验签过的 Code 中。

说明:
图1三种颜色分别表示三种角色的验签链。
- 红色表示 TEE Owner 的验签链。
- 黑色表示 REE Owner 的验签链。
- 蓝色表示 SoC vendor 的验签链。
- 在 Non-TEE 时 gsl_external_public_key 被 ree_root_pub_key 验签,用虚线表示。
验签关系中定义了三种角色:
- TEE Owner,REE Owner。TEE Owner 是 GSL,TEE OS 和 TA 的属主;
- REE Owner 是 U-Boot,Linux,RootFS 的属主,当 Non-TEE 时 GSL 也属于 REE。
其中 TEE Owner 和 REE Owner 必须是 OEM。不能有 TEE 验签而 REE 不验签的情况。
本节中所描述的公私钥由以上三种角色派生,并在启动流程中被三种角色所持有的 Hash 或公钥验签。其中公钥用于镜像的验签,保存在镜像中,为公开信息。
需要注意,GSL 在 Non-TEE 时属于 REE,在使能 TEE 时属于 TEE。
- 在 Non-TEE 时 gsl_external_public_key 被 ree_root_pub_key 验签;
- TEE 时 gsl_external_public_key 被 tee_root_pub_key 验签。
表1列出了安全启动所需的公钥。
表 1 验签公钥表
公私钥对可使用 RSA3072 或 SM2 算法。
openssl 生成国密(SM2)公私钥对命令示例。
私钥生成:
公钥生成:
openssl 生成 RSA 公私钥对命令示例。
私钥生成:
公钥生成:
版本防回滚
在验签过程中,会将签名后的镜像中 version 字段和 otp 中的值比较。防止使用有风险的老版本镜像实现恶意攻击。
校验条件: version_ext & mask_version_ext 中高位的个数大于等于 otp_ver & mask_version_ext 中高位的个数。
有些镜像中 key 区和 info 区中有各自的 version 字段,但是都是和同一个 otp 比较。可以通过 key 区的 version mask 把 otp 划分出 key 区校验位域与 info 区校验位域。
例如:
某一 otp 中的 version 占用 8 bit。高 4 bit 分给 key 区的 version,低 4 bit 分给 info 区的 version。
则 key 区 version mask 应该配成 0b11110000。key 区的 version 按照 0b00010000,0b00110000,0b01110000,0b11110000 递增。
info 区的 version mask 应该配成 0b00001111。info 区的 version 按照 0b00000001,0b00000011,0b00000111,0b00001111 递增。
注意:
1、tee code info的版本防回滚检查方式比较特殊,它的version_ext无需和掩码mask_version_ext进行与运算,而是直接给定自然数。如:tee code info区的version_ext给定0x10(自然数为16) 2、tee key area和tee code info的版本防回滚检查共用了一个64bit的otp_ver,当tee key area的掩码mask_version_ext 决定用多少个bit后,剩下的bit均可供tee code info使用。 3、tee key area的version_ext不能超出32bit。
加解密
用于镜像加解密的算法可选为AES。
考虑到实际业务中存在多种加解密场景,出于安全性考虑不同加解密场景会使用不同的密钥。SoC 中提供了一种,只烧写一个 OTP 并生成不同的加解密密钥的方式。实际用于加解密的密钥一般称其为工作密钥,由芯片内部的 KM 模块生成。

镜像制作工具在 PC 端模拟了工作密钥生成过程,并在 PC 端进行加密。镜像解密场景下加扰后的根密钥特指 Obfu_MRK1。
密钥派生材料和加密后的密钥都是存储在镜像里的字段,是公开信息。影响工作密钥的值,但是不影响工作密钥的安全性。
KM 模块生成工作密钥后会直接在硬件中送给 SPACC 模块,软件不可读。SPACC 收到工作密钥后应用 AES 解密算法对镜像解密。
启动镜像制作及烧写
本章介绍了Hi35xxVxx镜像制作步骤、OTP烧写步骤、镜像烧写方法,以及给出了环境变量配置参考值。
本节中所描述的启动镜像包含了,Boot 镜像和 TEE OS 镜像。
- 启动镜像制作流程中简要介绍了启动镜像的制作流程,并描述了启动镜像制作过程中的组件及用途。
- 整编生成启动镜像中介绍了一种简化的整编生成 TEE 安全启动镜像与非安全启动镜像的方式。
- 生成输入镜像介绍了镜像生成过程中所用到的输入镜像及生成方式。
- 镜像制作工具image_tool介绍了镜像制作工具的使用方法。其中包含如何使用默认的配置项和快速镜像构建脚本生成启动镜像。
- 镜像烧写与环境变量配置介绍了镜像烧写与环境变量配置。
建议先阅读启动镜像制作流程后选择性阅读其他章节。如果想使用默认配置快速生成非加密的安全和非安全启动镜像可以直接阅读生成输入镜像、镜像烧写与环境变量配置。关于本节中提及的 OTP 烧写请参考 OTP烧写章节。
启动镜像制作流程
快速启动方案的镜像制作方法与传统的启动方案相同;若要制作非安全启动、安全启动和TEE安全启动的启动镜像,则需要借助“image_tool”镜像制作脚本。本节将阐述Hi35xxVxx各启动方案的镜像制作步骤。

启动镜像制作总体流程如图1所示。黄底色字体表示需要客户参与或执行的动作。其中并非所有过程都需要考虑。
非安全启动
对于非安全启动。用户只需关注图1中:
- 第 1 步“生成原始镜像”;
- 第 5 步“生成启动镜像”;
- 第 9 步“烧写镜像”。
安全启动
对于有验签的安全启动,除非安全启动中的步骤外,需要注意图1中:
- 第 1 步“生成原始镜像”;
- 第 2 步,生成公私钥对;
- 第 5 步“生成启动镜像”;
- 第 8 步,烧录公钥哈希到 OTP。其中的烧录脚本由镜像制作工具在生成镜像的同时生成;
- 第 9 步“烧写镜像”。
对于有加密的安全启动镜像需关注图1中:
- 第 1 步“生成原始镜像”;
- 第 2 步,生成公私钥对;
- 第 3 步,生成根密钥;
- 第 4 步,生成密钥派生材料;
- 第 5 步“生成启动镜像”;
- 第 7 步,烧录根密钥;
- 第 8 步,烧录公钥哈希到 OTP。其中的烧录脚本由镜像制作工具在生成镜像的同时生成;
- 第 9 步“烧写镜像”。
建议:镜像加密必须做验签,否则可能会存在网络安全风险。
镜像制作工具生成的启动镜像
不同场景下镜像制作工具需要生成的启动镜像不同。
生成的 Non-TEE 启动镜像
boot_image.bin 是 GSL 和 U-Boot 打包后的安全启动镜像。
生成的 TEE 安全启动镜像
- boot_image.bin 是 GSL 和 U-Boot 打包后的安全启动镜像。
- 对于存在 TEE 的场景, tee_image.bin 包含 tee.bin(TEE OS 的镜像)。
原始镜像
- gsl.bin:GSL 镜像;
- reg_info.bin:Boot 表格,在安全方案里称其为Params Area;
- tee.bin(可选):TEE OS 的镜像,有TEE场景时需要;
- u-boot-original.bin:U-Boot 镜像。
验签公私钥
验签过程中用到的公私钥对列表见验签链与验签中的角色。镜像制作工具接受 pem 文件格式的公私钥。公私钥对生成方式请参考外部公钥对镜像校验。
根密钥
根密钥在安全启动里特指 Obfu_MDRK1,需要烧写到 SoC 中的 OTP 里,并且需要和配置文件中 oem_root_key 字段保持一致。 Obfu_MRK1 和 MRK1一 一对应但是并不相等。Obfu 前缀表示加扰的意思。目前各个OEM厂商所使用的加扰方法相同,加扰起不到保护作用。板端解密用到的 MRK1 烧写在 OTP 中,烧写方法请见《Hi35xxVxxx 安全子系统使用说明》"OTP" 章节。
建议在安全服务器上使用 openssl rand -hex 16 命令生成。并保存在安全服务器上。
和上面提到的公私钥不同,加解密用的是对称密钥。
密钥派生材料
密钥材料是镜像中涉及密钥派生字段的统称,这些字段和根密钥一起派生对镜像加解密的密钥(一般称其为工作密钥)。
KM 模块
加解密密钥管理模块,向 SPACC 模块配置加解密密钥。具体请见《Hi35xxVxxx 安全子系统使用说明》。
SPACC 模块
支持以下安全特性:
- 对称加解密算法
- HASH 算法和非对称加解密算法
- 验签算法
具体请见《Hi35xxVxxx 安全子系统使用说明》。
整编生成启动镜像
本节中介绍了一种整编生成启动镜像的方式。
整编生成非安全启动镜像
在boards/dmeb目录下执行:
若使用debug版本,则使用下面的命令。
生成的非安全启动镜像位于 boot_image.bin。
或者可以整编boards/dmeb 目录生成完整的系统镜像。
整编生成Non-TEE安全启动镜像
在boards/dmeb目录下执行:
如果缺少某一公私钥则会出现如下打印:
此时输入 y 将自动生成对应的公私钥对。并继续进行编译。缺少多个 key 的时候需要重复输入。
生成安全启动镜像boot_image.bin。
并自动生成需要烧写的 OTP all_merge_uboot_otp_cmd.txt。
生成的公钥区哈希值位于 tools/pc/image_tool/oem/tmp/ 目录下的 oem_ree_root_public_key_area_checksum.txt 文件。
如果已经存在默认的公私钥对则不会另外生成。生成的公私钥对位于tools/pc/image_tool/pub_private_key 目录下,其中公钥用于镜像验签,需要在安全服务器中妥善保存。
如果公私钥对已经存在,可编译完整的系统镜像:
整编生成TEE安全启动镜像
在boards/dmeb目录下执行:
如果缺少某一公私钥则会出现如下打印:
此时输入 y 将自动生成对应的公私钥对。并继续进行编译。缺少多个 key 的时候需要重复输入。
生成带tee的安全启动镜像boot_image.bin和tee_image.bin。
如果已经存在默认的公私钥对则不会另外生成。生成的公私钥对位于tools/pc/image_tool/pub_private_key 目录下,其中公钥用于镜像验签,需要在安全服务器中妥善保存。
如果公私钥对已经存在,可编译完整的系统镜像:
生成输入镜像
单步生成输入镜像的方式。如果选择boards/dmeb目录下make gslboot_build生成输出镜像,无需单独生成输入镜像,可略过本章内容。
GSL 编译
boards/dmeb/components/gsl 目录下,执行:
位于 pub/gsl.bin 处生成 gsl.bin 二进制镜像。
注意:
使用国密算法时需要按照如下步骤编译 GSL。
- 需要将64字节的国密公钥填写至boards/dmeb/components/gsl/boot/checkup.c 文件的全局数组g_sm_ree_root_public_key[64]中。
- 打开gsl/cfg.mk文件中的国密使能宏CFG_SM_SUPPORT=1
- 重编gsl,将生成的gsl.bin拷贝至boards/dmeb/tools/pc/image_tool/input目录
- 参考 "镜像生成" 小节执行命令重编 boot 镜像。python oem/oem_main.py build oem/quick_build_sm_secure_boot_config.json 使用如下命令查看公钥,其中第一个字节不需要填写,只需填写后面64字节 openssl ec -in ree_root_pub_key.pem -pubin -noout -text
Boot表格生成
需要用Windows系统进入boards/dmeb/tools/pc/boot_tools/目录,打开对应单板的Excel文件,选择main标签,点击“Generate reg bin file”按钮,生成对应平台的Boot表格文件reg_info.bin。
U-Boot 编译
third_party/u-boot 源码目录下执行
位于 u-boot-2022.07/u-boot-hi35xxvxx.bin 处生成 U-Boot 二进制镜像。
OP-TEE 编译(可选)
如果需要用到 TEE 环境,需在third_party/optee 源码目录下执行:
位于 ./optee_os-3.20.0/out/arm-plat-vendor/core/tee.bin 处生成 TEE OS 二进制镜像。
镜像制作工具image_tool
镜像制作工具是 boards/dmeb/tools/pc/image_tool 目录下接收输入镜像并生成输出镜像的一系列脚本。使用流程见图1。

除了生成镜像功能,其还承担了生成配置文件模板的功能。镜像制作工具的配置文件使用 .json。
如果客户第一次执行,需要执行第1步生成配置文件与第2步生成镜像。如果已经存在配置文件则可直接执行第2步。
镜像制作工具文件结构
.
├── common
├── input
├── oem
│ ├── oem_main.py
│ ├── oem_quick_build.py
│ ├── oem_quick_build_tee.py
│ ├── oem_quick_build_secure_boot.py
│ └── tool
├── README_CN.md
├── README_EN.md
- common:目录为工具函数集合;
- input:目录用来保存输入镜像;
- oem:为 oem 用到的脚本目录。oem_quick_build.py 脚本用于生成非安镜像。oem_quick_build_tee.py 用于生成带 tee 的启动镜像。oem_quick_build_secure_boot.py 用于生成 Non-TEE 的安全启动镜像。
输出镜像路径在配置文件中。
快速制作镜像
本节描述了如何使用默认的配置文件快速生成启动镜像,无需单独生成模板。
快速制作非安全启动镜像
在 boards/dmeb/tools/pc/image_tool目录下执行以下步骤:
-
拷贝以下文件到input目录。
- gsl.bin 为 gsl 二进制镜像。
- reg_info.bin 为boot表格。
- u-boot-original.bin为 U-Boot 二进制镜像。
-
执行快速构建脚本。
生成镜像位于 image/oem/boot_image.bin。
定制化启动镜像制作
配置文件模板生成
执行如下命令可生成配置文件模板:
执行命令之后会产生一段交互,用户可根据使用场景生成配置文件模板。
# 选择安全模式,安全启动或者没有安全启动
Security Mode:
0.Non-Secure
1.Secure
# 是否使能 TEE
Start Flow:
0.Non-TEE
1.TEE
# GSL 是否加密
Encrypt GSL Code:
0.No
1.YES
# UBOOT 是否加密
Encrypt Boot Code:
0.No
1.YES
# TEE OS 是否加密
Encrypt ATF_TEE_Code:
0.No
1.YES
# 加密和验签算法
algorithm:
0.RSA3072+SHA256+AES
生成的配置文件参数请参考镜像制作工具配置项进行填写。
镜像生成
生成启动镜像。
oem/oem_config.json 为镜像工具配置文件,如果已经存在无需再次生成。
注意:
相比于非国密json文件,国密镜像制作的json文件需要多填写国密公私钥字段"REE_root_pub_key_sm"和"REE_root_private_key_sm"
镜像烧写与环境变量配置
镜像烧写
本节以SPI NOR存储介质为例,介绍如何使用ToolPlatform工具烧写启动镜像。
选用其它存储介质(SPI NAND、eMMC)时,文件系统的类型和烧写长度与SPI NOR不同,其余镜像的大小和烧写布局与SPI NOR相同。
非安全启动和Non-TEE安全启动
非安全启动和Non-TEE安全启动的镜像烧写布局如图1所示。
图 1 非安全启动和Non-TEE安全启动ToolPlatform烧写分区参考图

如果在boards/dmeb目录下进行整编则会生成默认的分区模板,可以直接选用上图中名为 nor_burn_table.xml 文件中的分区表模板。
TEE安全启动
暂不支持。
单板环境变量配置参考
本节基于镜像烧写的镜像布局,提供SPI NOR、SPI NAND和eMMC作为启动介质时的环境变量配置示例。如果已经烧写整编生成的 env.bin 分区,则无需额外配置环境变量。默认的 U-Boot 环境变量位于 tools/pc/uboot_env/env_text/hi3516cv610/ 目录下,Hi3516CV608 环境变量位于 tools/pc/uboot_env/env_text/hi3516cv608/ 目录下。
非安全启动和Non-TEE安全启动模式
-
SPI NOR
setenv bootargs 'mem=32m earlycon=pl011,0x11040000 console=ttyAMA0,115200 clk_ignore_unused initcall_debug rw root=/dev/mtdblock3 rootfstype=jffs2 clk_ignore_unused initcall_debug mtdparts=sfc:512K(boot),512K(env),4M(kernel),10M(rootfs)';sa setenv bootcmd 'sf probe 0; sf read 0x41000000 0x100000 0x400000; bootm 0x41000000';sa -
SPI NAND和并口NAND
-
eMMC
OTP 配置与烧写
OTP 说明
OTP 模块的使用与字段说明与偏移,请参考《Hi35xxVxxx安全子系统使用说明》的 OTP 章节。
OTP烧写
使用寄存器读写命令烧写 OTP
以下命令为烧写偏移为 0xe0 的 Obfu_rusk 字段的示例,请不要直接执行。
mw 命令为 U-Boot 下的直接读写寄存器命令,请客户自行替换为对应平台的寄存器读写命令。
OTP write cmd:
mw 0x101e1038 0x1
mw 0x101e1004 0xe0 // 字段OTP起始地址
mw 0x101e1008 0xxx // 烧写的值
mw 0x101e1000 0x5
…… // 字段OTP其他地址烧写
mw 0x101e1038 0x1
mw 0x101e1004 0xef // 字段OTP结束地址
mw 0x101e1008 0xxx // 烧写的值
mw 0x101e1000 0x5
mw 0x101e1038 0x3 // 结束
// OTP烧写命令输入结束后,可以通过回读指令,对烧写命令执行是否成功进行判断。
OTP read cmd:
mw 0x101e1038 0x1
mw 0x101e1004 0xe0 // 需要读取的OTP地址
mw 0x101e1000 0x3
md 0x101e100C 0x1
mw 0x101e1038 0x3
寄存器回读:
mw 0x101e1038 0x1
mw 0x101e1004 0xe0 // 需要读取的OTP地址
mw 0x101e1000 0x3
md 0x101e100C 0x1
mw 0x101e1038 0x3
使用安全子系统 API 烧写 OTP
请见《Hi35xxVxxx 安全子系统使用说明》文档中 OTP 章节的描述实现 OTP 烧写程序。
不同场景下的 OTP 烧写
OTP 模块的使用与字段详细说明与偏移,请参考《Hi35xxVxxx安全子系统使用说明》中 OTP 章节。OTP 烧写请参考 “OTP烧写“ 小节。
Non-TEE 验签(安全启动)需要烧写的 OTP 字段
- ree_verify_enable:REE 校验使能
- ree_hash_flash_root_key:ree root key 哈希值
- msid(可选):区分市场区域时烧写。
- params_ver(可选):Boot表防回滚。
- ree_boot_ver(可选):Boot Code防回滚。
- scs_alg_sel(可选):安全算法选择。
TEE 使能时需要烧写的 OTP
- soc_tee_enable:SoC TEE 使能,否则整个芯片不区分 TEE 与 REE 环境
- ree_verify_enable:REE 校验使能,不能有 TEE 验签而 REE 不验签的情况
- tee_verify_enable:TEE 校验使能
- tee_hash_flash_root_key:tee root key 哈希值
- ree_hash_flash_root_key:ree root key 哈希值
- tee_boot_ver(可选):GSL 防回滚。
- tee_os_ver(可选):TEE OS 防回滚。
- params_ver(可选):Boot表防回滚。
- ree_boot_ver(可选):Boot Code防回滚。
- msid(可选):区分市场区域时烧写。
- obfu_rusk(可选):安全存储场景烧写。
- scs_alg_sel(可选):安全算法选择。
镜像加密时需要烧写的 OTP
在验签 OTP 基础上需要额外烧写以下 OTP。
- ree_dec_enable:REE 解密使能
- obfu_mrk1:obfu_mrk1 加扰后的根密钥
- tee_dec_enable(可选):TEE 解密使能
须知:
obfu_mrk1和oem_rootkey0表示同一个OTP。
安全模拟时需要烧写的 OTP
需要注意,Non-TEE 安全启动时才能进行安全模拟。
验签安全模拟时不烧写 ree_verify_enable,其他 OTP和Non-TEE 验签(安全启动)镜像的场景相同。
加解密安全模拟时不烧写 ree_dec_enable,仅烧写 obfu_mrk1 时可以对镜像加密进行模拟。
- ree_hash_flash_root_key:ree root key 哈希值。
- obfu_mrk1(可选):obfu_mrk1 加扰后的根密钥,需要对镜像加解密进行模拟时需要烧写。
- msid(可选):区分市场区域时烧写。
- params_ver(可选):Boot表防回滚。
- ree_boot_ver(可选):Boot Code防回滚。
- scs_alg_sel(可选):安全算法选择。
镜像制作工具配置项
本节对镜像制作工具配置文件中各个配置项进行描述。请在已经生成配置文件模板的情况下参考本节中的描述填写配置项。本节中的文件路径以boards/dmeb/tools/pc/image_tool 为工作目录。配置项模板生成请参考配置文件模板生成。本章中提到的 OTP 字段,请参考《Hi35xxVxxx安全子系统使用说明》中OTP 章节。
安全模式配置项
|
安全算法选择配置项
TEE 使能配置项
|
TEE 所有者选择
|
OEM 信息配置项
OEM_info 字段的子配置项
Msid 市场区域标识,隔离不同市场区域的镜像。验签场景时使用。4 字节。和 msid OTP 匹配。 校验条件:(msid_otp & mask_oem_msid_ext) != (oem_msid_ext & mask_oem_msid_ext) 时无法成功验签镜像。 |
根公钥区配置项
root_key 字段的子配置项
GSL 相关配置项
GSL字段的子配置项包括以下内容。
GSL Key 区配置项
GSL_key_area 字段的子配置项。
GSL Info 区配置项
GSL_Info_area 字段的子配置项。
GSL code 区配置项
GSL_code_area 字段的子配置项
REE Boot 相关配置项
REE_boot 字段的子配置项。主要和 U-Boot 相关。
REE Boot Key 区配置项
uboot_key_area 字段的子配置项。
Boot 表格 Info 区配置项
boot_params_Info 字段的子配置项。
说明:
boot 表格的bin文件路径需要时配置为文件的绝对路径或者input文件夹内部相对路径,不使用此表格可以不配置或者直接配置为空即可。
REE Boot Info 区配置项
uboot_info_area 字段的子配置项。
uboot Code 区配置项
uboot_area 字段的子配置项。
TEE 相关配置项
TEE 字段的子配置项如下。
TEEOS Key 区配置项
TEEOS_key_area 字段的子配置项。
TEEOS Info 区配置项
TEEOS_info_area 字段的子配置项。
TEE OS Code 区配置项
TEEOS_code_area 字段的子配置项。
维护模式相关配置项
maintenance_mode 字段的子配置项。
|
|
|
|
|
|
加解密配置项
安全模拟配置项
SCS_simulate 字段的子配置项。
|
|
|
|
|
|
|
|
TEEOS code和AFT code 加解密模拟模式标记。
|
内核及文件系统安全启动校验
该方案是基于上述安全启动方案的特性,在U-Boot验签通过后,再通过在U-Boot上实现验签内核的功能。前一阶段系统引导下一阶段系统前,先对待启动系统进行验签,如果验签成功,再启动Linux系统,否则系统启动失败。验签机制可以保证系统镜像的完整性,如果镜像被篡改或损坏,系统将不会被启动。
安全镜像结构
安全镜像由 Key Area、Code Info Area 和原始镜像三部分组成,如图1所示。

- Key Area 保存了 External Public Key和对 Key Area Body 区域的签名,该区域使用 U-Boot 代码中的 Root Public Key进行验签来保证其完整性。
- Code Info Area 里保存了原始镜像的hash值和对Code Info Area Body区域的签名,该区域使用Key Area中的 External Public Key 进行验签来保证其完整性。
- Code Area 为原始镜像,该区域通过计算其 hash 值,与 Code Info Area 中保存的 hash 值进行比较来保证其完整性。
警告:
reserved4 区域未经过校验,因此无法保证其数据完整性,在该区域中不应该保存任何有效信息。
安全启动流程
本节只描述 U-Boot 校验内核的流程,如图1所示。若存在其他类型的镜像需要校验(如文件系统),可以参照该流程进行设计,本文不进行说明。

安全镜像制作指导
说明:
当前的Verify Boot功能支持RSA3072+SHA256,以及SM2+SM3验签。
rsa验签镜像制作
本节提供通过shell命令完成安全镜像制作,以 kernel.bin 镜像为例,最终得到安全镜像 kernel_sign.bin。
建议用户新建一个目录,将编译的镜像ulmage重命名为kernel.bin,拷贝到新建目录下,执行以下命令,用于生成rsa验签镜像。
-
生成两个私钥文件
-
制作 Key Area 镜像
dd if=/dev/zero of=image_key_area_1.bin count=252 bs=1 openssl rsa -in extern_private_key.pem -modulus -noout | sed 's/Modulus=//'| xxd -r -p > modulus.bin echo "00010001"| xxd -r -p > exponent.bin cat image_key_area_1.bin modulus.bin exponent.bin > image_key_area_body.bin openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sign root_private_key.pem -out image_key_area_signature.bin image_key_area_body.bin cat image_key_area_body.bin image_key_area_signature.bin > image_key_area.bin -
制作 Code Info Area 镜像
dd if=/dev/zero of=code_info_area_1.bin count=36 bs=1 printf "%08x" $(wc -c < kernel.bin) | sed -r 's/(..)(..)(..)(..)/\4\3\2\1/g' | xxd -r -ps > code_area_len.bin sha256sum kernel.bin | awk '{printf $1}' | xxd -r -ps > code_area_hash.bin dd if=/dev/zero of=code_info_area_2.bin count=184 bs=1 cat code_info_area_1.bin code_area_len.bin code_area_hash.bin code_info_area_2.bin > code_info_area_body.bin openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sign extern_private_key.pem -out code_info_area_signature.bin code_info_area_body.bin dd if=/dev/zero of=sig_code_info_ext.bin count=384 bs=1 cat code_info_area_body.bin code_info_area_signature.bin sig_code_info_ext.bin > code_info_area.bin -
制作最终签名镜像
国密sm2+sm3验签镜像制作
本节提供通过python脚本完成安全镜像制作,以 ulmage 镜像为例,最终得到安全镜像 kernel_image.bin。
解压版本SDK包Hi35xxVxxx_SDK_Vx.x.x.x_xxx.tgz后,执行./sdk.unpack。
-
编译镜像
将生成的ulmage拷贝到tools/pc/image_tool/input目录下
-
制作安全镜像。
- 将boards/dmeb/components/verify_boot_script/目录下的verify_boot_quick_build.py文件拷贝到tools/pc/image_tool/oem目录下。
-
服务器中执行以下命令用于生成签名镜像。
-
如果没有提前放置公私钥,会创建目录pub_private_key,并生成以下公钥对和私钥对。
kernel_external_pub_key.pem kernel_external_private_key.pem kernel_root_pub_key.pem kernel_root_private_key.pem签名加密后的kernel镜像是image_tool/image/oem/kernel_image.bin
执行xxd -i oem/tmp/kernel_external_pubkey.bin 打印出公钥,此公钥需要填入verify_boot.c的g_root_pub_key中。
U-Boot 支持安全启动配置
-
编译 U-Boot 时添加 Verify Boot 支持
在编译 U-Boot 时执行 make ARCH=arm menuconfig 命令进入配置选择页面,依次进入 Product ---> verify boot enable,按 Y 选中保存并退出。
-
在 U-Boot 代码中填入 Root Public Key 公钥
修改 Hi35xxVxxx_SDK_Vx.x.x.x/open_source/u-boot/u-boot-2022.07/product/verify_boot/verify_boot.c 文件,非国密安全启动将 root_private_key.pem 中的公钥对(N,E)填入 g_root_pub_key 数组;国密安全启动将kernel_external_pubkey.bin公钥填入g_root_pub_key 数组。
说明: - 可使用 openssl rsa -in root_private_key.pem -modulus -noout | sed 's/Modulus=//'| xxd -r -p > modulus.bin 从私钥中导出 N,E 的值固定为 4 Bytes 的 {0x00, 0x01, 0x00, 0x01},打印N的命令为xxd -i modulus.bin
- RSA算法支持二级校验,保证Key Area和Code Info Area区域的完整性,Key Area验签需要开启宏CONFIG_VERIFY_KEY_AREA_SUPPORT,开启目录:Hi3511CV100_SDK_Vx.x.x.x/open_source/u-boot/u-boot-2022.07/product/verify_boot/Makefile
- 国密算法只支持一级校验,保证Code Info Area区域的完整性,执行xxd -i oem/tmp/kernel_external_pubkey.bin 打印出公钥
-
重新编译 U-Boot 即可。
上述步骤编译的 U-Boot 镜像会增加一条 verify_boot 命令,需要修改 bootcmd 才能最终开启安全启动功能。
bootcmd 修改参考如下(以 kernel 镜像为例,flash 介质为 spi nor,其位于 flash 1M 偏移,大小为 4M):
不开启安全启动时,bootcmd 命令为:sf probe 0; sf read 0x41000000 0x100000 0x400000; bootm 0x41000000;
开启安全启动后,bootcmd 命令应该修改为:sf probe 0; sf read 0x41000000 0x100000 0x400000; verify_boot kernel 0x41000000; bootm 0x41000800;
修改点主要是两个地方:
- 将镜像从 flash 读到 ddr 后,需要先使用 verify_boot 命令传入两个参数(镜像名和 ddr 地址),该命令会校验位于该 ddr 地址的镜像的合法性,若校验不通过则系统复位。
- bootm 启动地址需要增加 0x800 的偏移,因为支持安全启动后,镜像会增加 0x800 的镜像头信息。
警告:
调试时可以在 U-Boot 命令行中修改 bootcmd 命令,但在量产版本中不允许启动时进入 U-Boot 命令行,必须将 bootcmd命令在 U-Boot 编译时配置好。
内核及文件系统安全启动验签方案参考
该参考方案是基于上述安全启动方案的特性,在U-Boot验签通过后,再通过在U-Boot上实现验签内核的功能。前一阶段系统引导下一阶段系统前,先对待启动系统进行验签,如果验签成功,再启动Linux系统,否则系统启动失败。验签机制可以保证系统镜像的完整性,如果镜像被篡改或损坏,系统将不会被启动。
安全启动流程
本文中描述的只涉及BOOTROM验签后启动U-Boot,U-Boot验签后启动Kernel,如图1所示。其它文件系统等的验签流程,以及相关数据加解密保护可参照这种模式进行设计开发,本文不进行说明。
方案在制作非安全的U-Boot原始镜像先使其镜像大小16字节对齐,对齐之后再往Boot原始镜像上追加内核的安全验签公钥Key的信息等信息至镜像尾部,再通过“启动镜像制作流程”对追加信息后U-Boot生成新的安全启动镜像。

安全启动验签流程涉及的哈希值计算、非对称RSA加解密,请自行查询相关资料,本文不再进行说明。如果需要进一步开发加解密功能,可了解其它加密算法,例如对称AES加密算法。
附验证信息U-Boot镜像结构
附验证信息的U-Boot镜像结构如图1所示。在U-Boot镜像尾部追加Kernel相关安全信息,再将带Kernel验证信息的U-Boot镜像制作成安全启动镜像。

安全Kernel镜像结构
安全Kernel镜像由头部信息、Kernel镜像和签名信息等组成,如图1所示。在原有Kernel镜像结构进行拼接,其中Kernel镜像为压缩镜像。Kernel验签使用的RSA公钥信息保存在U-Boot原始镜像中,随安全镜像一起整合成安全启动镜像。

功能实现
U-Boot验签Kernel部分功能实现请参考《安全子系统 API 参考》文档“RSA签名及验签使用流程”章节调用相应API接口实现。
安全Boot 镜像备份功能
Boot 镜像备份指的是在介质中存放两个Boot 镜像,其中从0地址开始的第一个Boot分区为主分区,第二个Boot分区为备份分区,当主Boot 镜像校验失败(包括key、gsl、uboot区域)后,便软复位从介质中搜寻备份分区起始地址标志,匹配成功后重新从备份分区启动。
如需使用安全 Boot 镜像备份功能,请先烧写安全 Boot备份启动对应的OTP。OTP定义详见《Hi35xxVxxx 安全子系统使用说明》的OTP章节中“boot_backup_enable”字段。
注意:
- 仅支持备份1个 安全Boot Image,且备份Boot Image需放置在主Boot Image之后。
- 当存储介质为Flash时,备份镜像最大SIZE:512KB;当存储介质为emmc时,备份镜像最大SIZE:2M。
- 烧写的备份 Boot Image 起始地址要求64K对齐。
- 当存储介质为spi nand时,第一个block不能擦除或者损坏。
多Boot表格功能
在镜像制作工具中配置多个boot表格(见 Boot 表格 Info 区配置项)。并修改 gsl/boot/board_type.c代码中多表格函数钩子get_board_param_index() 实现一个镜像适配多种板型。
下面以demo板为例进行使用说明:
- boot_param_file0-7为镜像脚本工具中.json文件配置项,位于配置文件boards/dmeb/tools/pc/image_tool/oem/quick_build_config.json中,即SDK版本包默认编译的非安场景配置文件;另外同级目录下的quick_build_secure_boot_config.json为安全non-TEE场景使用,quick_build_tee_config.json为安全TEE场景使用,请按需选择。
-
指定单个表格文件路径方法
例如配置"boot_param_file7": "./input/reg_info.bin",需要将表格文件reg_info.bin放入镜像工具相对路径boards/dmeb/tools/pc/image_tool/input中,编译时会自动编译进入boot_image.bin中,也可以指定为表格文件的绝对路径,请按需配置。
-
指定多个表格文件路径方法
例如同时配置3个表格:"boot_param_file0": "./input/reg_info0.bin","boot_param_file3": "./input/reg_info3.bin","boot_param_file7": "./input/reg_info7.bin",编译时reg_info0.bin、reg_info3.bin,reg_info7.bin 3个表格都会自动编译进入boot_image.bin中;也可以指定为表格文件的绝对路径,请按需设置。
-
总体示例
如在镜像表格文件配置项中boot_param_file0和boot_param_file7给定了boot表格路径,当配置get_board_param_index()的返回值为0,则启动时会选择boot_param_file0对应的boot表格,当配置get_board_param_index()的返回值为7,则启动时会选择boot_param_file7对应的boot表格。
注意:
- boot表格个数最大不超过8个,boot表格bin文件大小最大不超过15KB。
- 以上json文件修改只能修改规定预留区域,即双引号内预留的填充区,不能删除或增加行数,否则会存在编译表格镜像与拨码不匹配问题。
维护模式
维护模式适用于海思需要在OEM设备上调试安全设备的情况。该设备已经被OEM烧写了根公钥,避免每次重烧镜像都需要 OEM 重新签名。调试 key 和 DIE_ID(每个芯片有唯一的 DIE_ID) 绑定,保证调试 key无法在设备间共用。调试结束后 OEM 重烧 OTP 使海思调试 key 失效。此模式可以解决在调试场景下海思和 OEM 之间互信的问题。

如图1所示。海思会根据实际情况提供 GSL,U-Boot,TEE OS 的调试外部公钥。
OEM 拿到调试外部公钥后使用镜像制作工具生成维护模式镜像。启用维护模式需要参考维护模式相关配置项 中的描述,打开对应选项。镜像中的 DIE ID,维护模式标记,KEY 区版本,海思调试公钥被一起验签,海思无法篡改。
结束调试后,OEM 根据实际情况来烧写以下 OTP失效海思调试公钥:
- tee_boot_ver:对应 GSL 外部公钥
- ree_boot_ver:对应 U-Boot 外部公钥
- tee_os_ver:对应 TEE OS 外部公钥
失效原理请参考版本防回滚,OTP 烧写请参考《Hi35xxVxxx 安全子系统使用说明》。
注意:开启第三方验签的设备无法使用维护模式。
错误码
BOOTROM部分
GSL部分
缩略语
A structured multi-level key mechanism that ensures secure transmission of control words. |
|




