跳转至

Hi35xxVxxx 安全启动使用指南

前言

概述

本文档主要是指导使用本安全启动方案的相关人员了解整个安全方案的流程,再通过一定的操作步骤和方法来使用本安全启动方案。主要介绍本安全启动的规格和特性,包括安全启动基本流程和key的层级结构与验签逻辑,及其整个安全启动方案的使用。

说明:

以下描述以Hi3516CV610为例,如无特殊说明,Hi3516CV608的描述与Hi3516CV610一致。

产品版本

与本文档相对应的产品版本如下。

产品名称

产品版本

Hi3516C

V608

Hi3516C

V610

读者对象

本文档(本指南)主要适用于以下工程师:

  • 技术支持工程师
  • 软件开发工程师

符号约定

在本文中可能出现下列标志,它们所代表的含义如下。

符号

说明

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

“须知”不涉及人身伤害。

对正文中重点信息的补充说明。

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

修改记录

文档版本

发布日期

修改说明

00B01

2026-06-30

第1次临时版本发布。

启动特性

安全特性

芯片内置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 代码中多表格函数钩子,实现一个镜像可适配多种板型。

启动方案

非安全启动

图 1 非安全启动流程

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

安全启动

图 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 区都会经过如下的验签链。其中根公钥校验章节和外部公钥对镜像校验章节展示了校验的手段。

图 1 通用验签流

根公钥校验

通过在板端计算根公钥的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 验签时通用的镜像结构

验签链与验签中的角色

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

图 1 公钥验签链

说明:

图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 验签公钥表

名称

属主

验签链上级

验签链下级

位置

tee_hash_flash_root_key

TEE

-

tee_root_pub_key

OTP

ree_hash_flash_root_key

REE

-

ree_root_pub_key

OTP

soc_hash_flash_root_key

SoC Vendor

-

tee_root_pub_key

OTP

tee_root_pub_key

TEE

tee_hash_flash_root_key

gsl_external_public_key(TEE)

boot_image.bin

ree_root_pub_key

REE

ree_hash_flash_root_key

uboot_external_public_key,

gsl_external_public_key(Non-TEE)

boot_image.bin

gsl_external_public_key

TEE

tee_root_pub_key

GSL

teeos_external_public_key

boot_image.bin

uboot_external_public_key

REE

ree_root_pub_key

U-Boot

boot_image.bin

teeos_external_public_key

TEE

gsl_external_public_key

TEE OS

tee_image.bin

公私钥对可使用 RSA3072 或 SM2 算法。

openssl 生成国密(SM2)公私钥对命令示例。

私钥生成:

openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:sm2 -out priv_key_file.pem

公钥生成:

openssl ec -in priv_key_file.pem -pubout -out pub_key_file.pem

openssl 生成 RSA 公私钥对命令示例。

私钥生成:

openssl genrsa -f4 -out priv_key_file.pem 3072

公钥生成:

openssl rsa -in priv_key_file.pem -pubout -out pub_key_file.pem

版本防回滚

在验签过程中,会将签名后的镜像中 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 模块生成。

图 1 KM模块工作机制

镜像制作工具在 PC 端模拟了工作密钥生成过程,并在 PC 端进行加密。镜像解密场景下加扰后的根密钥特指 Obfu_MRK1。

密钥派生材料和加密后的密钥都是存储在镜像里的字段,是公开信息。影响工作密钥的值,但是不影响工作密钥的安全性。

KM 模块生成工作密钥后会直接在硬件中送给 SPACC 模块,软件不可读。SPACC 收到工作密钥后应用 AES 解密算法对镜像解密。

启动镜像制作及烧写

本章介绍了Hi35xxVxx镜像制作步骤、OTP烧写步骤、镜像烧写方法,以及给出了环境变量配置参考值。

本节中所描述的启动镜像包含了,Boot 镜像和 TEE OS 镜像。

建议先阅读启动镜像制作流程后选择性阅读其他章节。如果想使用默认配置快速生成非加密的安全和非安全启动镜像可以直接阅读生成输入镜像、镜像烧写与环境变量配置。关于本节中提及的 OTP 烧写请参考 OTP烧写章节。

启动镜像制作流程

快速启动方案的镜像制作方法与传统的启动方案相同;若要制作非安全启动、安全启动和TEE安全启动的启动镜像,则需要借助“image_tool”镜像制作脚本。本节将阐述Hi35xxVxx各启动方案的镜像制作步骤。

图 1 启动镜像制作流程

启动镜像制作总体流程如图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目录下执行:

make gslboot_build -j

若使用debug版本,则使用下面的命令。

make gslboot_build DEBUG=1 -j

生成的非安全启动镜像位于 boot_image.bin。

或者可以整编boards/dmeb 目录生成完整的系统镜像。

make -j

整编生成Non-TEE安全启动镜像

在boards/dmeb目录下执行:

make SECURE_BOOT_ENABLE=1 gslboot_build -j

如果缺少某一公私钥则会出现如下打印:

enter y to generate a key pair, otherwise, exit.

此时输入 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 目录下,其中公钥用于镜像验签,需要在安全服务器中妥善保存。

如果公私钥对已经存在,可编译完整的系统镜像:

make SECURE_BOOT_ENABLE=1 -j

整编生成TEE安全启动镜像

在boards/dmeb目录下执行:

make TEE_ENABLE=1 gslboot_build -j

如果缺少某一公私钥则会出现如下打印:

enter y to generate a key pair, otherwise, exit.

此时输入 y 将自动生成对应的公私钥对。并继续进行编译。缺少多个 key 的时候需要重复输入。

生成带tee的安全启动镜像boot_image.bin和tee_image.bin。

如果已经存在默认的公私钥对则不会另外生成。生成的公私钥对位于tools/pc/image_tool/pub_private_key 目录下,其中公钥用于镜像验签,需要在安全服务器中妥善保存。

如果公私钥对已经存在,可编译完整的系统镜像:

make TEE_ENABLE=1 -j

生成输入镜像

单步生成输入镜像的方式。如果选择boards/dmeb目录下make gslboot_build生成输出镜像,无需单独生成输入镜像,可略过本章内容。

GSL 编译

boards/dmeb/components/gsl 目录下,执行:

make CHIP=hi35xxvxx

位于 pub/gsl.bin 处生成 gsl.bin 二进制镜像。

注意:

使用国密算法时需要按照如下步骤编译 GSL。

  1. 需要将64字节的国密公钥填写至boards/dmeb/components/gsl/boot/checkup.c 文件的全局数组g_sm_ree_root_public_key[64]中。
  2. 打开gsl/cfg.mk文件中的国密使能宏CFG_SM_SUPPORT=1
  3. 重编gsl,将生成的gsl.bin拷贝至boards/dmeb/tools/pc/image_tool/input目录
  4. 参考 "镜像生成" 小节执行命令重编 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 源码目录下执行

make -j

位于 u-boot-2022.07/u-boot-hi35xxvxx.bin 处生成 U-Boot 二进制镜像。

OP-TEE 编译(可选)

如果需要用到 TEE 环境,需在third_party/optee 源码目录下执行:

make CHIP=hi35xxxx OSDRV_CROSS=xxxx  -j

位于 ./optee_os-3.20.0/out/arm-plat-vendor/core/tee.bin 处生成 TEE OS 二进制镜像。

镜像制作工具image_tool

镜像制作工具是 boards/dmeb/tools/pc/image_tool 目录下接收输入镜像并生成输出镜像的一系列脚本。使用流程见图1。

图 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目录下执行以下步骤:

  1. 拷贝以下文件到input目录。

    • gsl.bin 为 gsl 二进制镜像。
    • reg_info.bin 为boot表格。
    • u-boot-original.bin为 U-Boot 二进制镜像。
  2. 执行快速构建脚本。

    python oem/oem_quick_build.py
    

    生成镜像位于 image/oem/boot_image.bin。

定制化启动镜像制作

配置文件模板生成

执行如下命令可生成配置文件模板:

python oem/oem_main.py gencfg oem/oem_config.json

执行命令之后会产生一段交互,用户可根据使用场景生成配置文件模板。

# 选择安全模式,安全启动或者没有安全启动

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

生成的配置文件参数请参考镜像制作工具配置项进行填写。

镜像生成
python oem/oem_main.py build oem/oem_config.json

生成启动镜像。

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

    setenv bootargs 'mem=32m  console=ttyAMA0,115200 clk_ignore_unused root=ubi0:ubifs rootfstype=ubifs rw ubi.mtd=3 mtdparts=nand:512K(boot),512K(env),4M(kernel),32M(rootfs)';sa
    setenv bootcmd 'nand read 0x41000000 0x100000 0x400000; bootm 0x41000000';sa
    
  • eMMC

    setenv bootargs 'mem=32m console=ttyAMA0,115200 clk_ignore_unused root=/dev/mmcblk0p4 rootfstype=ext4 rw rootwait blkdevparts=mmcblk0:512K(boot),512K(env),4M(kernel),96M(rootfs)';sa
    setenv bootcmd 'mmc read 0 0x41000000 0x800 0x2000; bootm 0x41000000';sa
    

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 章节。

安全模式配置项

配置项

说明

security_mode

是否为安全模式。需要烧写 OTP。

  • "Secure":安全启动
  • "Non-Secure":非安全启动

安全算法选择配置项

配置项

说明

algorithm

安全算法。影响镜像结构,需要烧写 OTP。

"RSA3072+SHA256+AES"

TEE 使能配置项

配置项

说明

start_Flow

是否是 TEE 启动流程,影响验签流,需要烧写 OTP。

  • “TEE”:有 TEE
  • “Non-TEE”:无 TEE

TEE 所有者选择

配置项

说明

TEE_owner

TEE 所有者

  • "OEM"
  • "Vendor"

OEM 信息配置项

OEM_info 字段的子配置项

配置项

说明

oem_msid_ext, mask_oem_msid_ext

Msid 市场区域标识,隔离不同市场区域的镜像。验签场景时使用。4 字节。和 msid OTP 匹配。

校验条件:(msid_otp & mask_oem_msid_ext) != (oem_msid_ext & mask_oem_msid_ext) 时无法成功验签镜像。

防止 A 区域的设备流入 B 区域,在烧写 B 区域的镜像后正常启动。

根公钥区配置项

root_key 字段的子配置项

配置项

说明

REE_root_pub_key, REE_root_private_key

REE 根公私钥对文件路径。验签场景时使用。

  • REE_root_pub_key:REE Boot 验签根公钥
  • REE_root_private_key:REE Boot 验签根私钥

REE_root_pub_key Hash 值需要和 OTP 中的 Hash 值 ree_hash_flash_root_key匹配。

TEE_root_pub_key, TEE_root_private_key

TEE 根公私钥对文件路径。验签场景时使用。

  • TEE_root_pub_key:TEE Boot 验签根公钥
  • TEE_root_private_key:TEE Boot 验签根私钥

TEE_root_pub_key Hash 值需要和 OTP 中的 Hash 值 tee_hash_flash_root_key匹配。

GSL 相关配置项

GSL字段的子配置项包括以下内容。

GSL Key 区配置项

GSL_key_area 字段的子配置项。

配置项

说明

GSL_key_version_ext, mask_GSL_key_version_ext

GSL key 区版本和掩码。验签场景下版本防回滚时使用。

2 字节大小。和 OTP 字段 tee_boot_ver 相关。

每个版本按照 0, 1(0b1), 3(0b11), 7(0b111), 0xf(0b1111)递增,新的版本比老版本多一个 bit。

校验条件:GSL_key_version_ext & mask_GSL_key_version_ext 中高位的个数大于等于 tee_boot_ver & mask_GSL_key_version_ext 中高位的个数。

不需要验签时不烧 OTP 并且设置为 0 即可。

GSL_external_public_key, GSL_external_private_key

GSL 外部公私钥对文件路径。验签场景时使用。

  • GSL_external_public_key:GSL 外部公钥文件路径
  • GSL_external_private_key:GSL 外部私钥文件路径

GSL Info 区配置项

GSL_Info_area 字段的子配置项。

配置项

说明

GSL_code_version_ext, mask_GSL_code_version_ext

GSL Info 版本和掩码。验签场景下版本防回滚时使用。

2 字节大小。和 OTP 字段 tee_boot_ver 相关。

每个版本按照 0, 1(0b1), 3(0b11), 7(0b111), 0xf(0b1111)递增,新的版本比老版本多一个 bit。

校验条件:GSL_code_version_ext& mask_GSL_code_version_ext 中高位的个数大于等于 tee_boot_ver & mask_GSL_code_version_ext 中高位的个数。

不需要验签时不烧 OTP 并且设置为 0 即可。

key_material_gsl

密钥材料,存放在镜像中。GSL 加密场景时使用。

加密安全性不依赖此密钥材料,不需要保证安全性。但是需要保证随机性。

安全服务器上生成的随机数,为 16 字节 16 进制数。

GSL_iv

加密 IV 值。不需要保证安全性但是需要保证随机性。

安全服务器上生成的随机数,为 16 字节 16 进制数。建议通过 openssl rand -hex 16 生成。

GSL_code_enc_flag

GSL 加密标记。

  • 0x3C7896E1,不加密
  • 其他,加密使能

GSL_code_FlashReadClk

选择启动阶段 Flash 接口时钟频率。

加速启动镜像读写,提高启动速度。

GSL code 区配置项

GSL_code_area 字段的子配置项

配置项

说明

GSL_code_file

GSL 二进制文件路径。

REE Boot 相关配置项

REE_boot 字段的子配置项。主要和 U-Boot 相关。

REE Boot Key 区配置项

uboot_key_area 字段的子配置项。

配置项

说明

uboot_key_version_ext, mask_uboot_key_version_ext

U-Boot key 区版本和掩码。验签场景时使用。

4 字节大小。和 OTP 字段 ree_boot_ver 相关。

每个版本按照 0, 1(0b1), 3(0b11), 7(0b111), 0xf(0b1111)递增,新的版本比老版本多一个 bit。

校验条件:uboot_key_version_ext & mask_uboot_key_version_ext 中高位的个数大于等于 ree_boot_ver &mask_uboot_key_version_ext 中高位的个数。

不需要验签时不烧 OTP 并且设置为 0 即可。

uboot_external_public_key, uboot_external_private_key

U-Boot 外部公私钥对文件路径。验签场景时使用。

  • uboot_external_public_key:U-Boot 外部公钥文件路径
  • uboot_external_private_key:U-Boot 外部私钥文件路径

Boot 表格 Info 区配置项

boot_params_Info 字段的子配置项。

配置项

说明

boot_param_version_ext, mask_boot_param_version_ext

boot 表格区版本和掩码。验签场景时使用。

4 字节大小。和 OTP 字段 params_ver 相关。

每个版本按照 0, 1(0b1), 3(0b11), 7(0b111), 0xf(0b1111)递增,新的版本比老版本多一个 bit。

校验条件:boot_param_version_ext & mask_boot_param_version_ext 中高位的个数大于等于 params_ver & mask_boot_param_version_ext 中高位的个数。

不需要验签时不烧 OTP 并且设置为 0 即可。

single_param_size

单个 boot 表格大小,每个表格默认按12K(0x3000)对齐,可根据实际情况调整

boot_param_total_num

所填boot 表格最大数量, 固定为8,无需改写

boot_param_file0

boot 表格0的bin文件路径

boot_param_file1

boot 表格1的bin文件路径

boot_param_file2

boot 表格2的bin文件路径

boot_param_file3

boot 表格3的bin文件路径

boot_param_file4

boot 表格4的bin文件路径

boot_param_file5

boot 表格5的bin文件路径

boot_param_file6

boot 表格6的bin文件路径

boot_param_file7

boot 表格7的bin文件路径

说明:

boot 表格的bin文件路径需要时配置为文件的绝对路径或者input文件夹内部相对路径,不使用此表格可以不配置或者直接配置为空即可。

REE Boot Info 区配置项

uboot_info_area 字段的子配置项。

配置项

说明

uboot_version_ext, mask_uboot_version_ext

U-Boot Info 区版本和掩码。验签场景时使用。

4 字节大小。和 OTP 字段 ree_boot_ver 相关。

每个版本按照 0, 1(0b1), 3(0b11), 7(0b111), 0xf(0b1111)递增,新的版本比老版本多一个 bit。

校验条件:uboot_version_ext & mask_uboot_version_ext 中高位的个数大于等于 ree_boot_ver &mask_uboot_version_ext 中高位的个数。

不需要验签时不烧 OTP 并且设置为 0 即可。

key_material_uboot

密钥材料,存放在镜像中。U-Boot 加密场景时使用。

加密安全性不依赖此密钥材料,不需要保证安全性。但是需要保证随机性。

安全服务器上生成的随机数,为 16 字节 16 进制数。

uboot_iv

加密 IV 值。U-Boot 加密场景时使用。不需要保证安全性但是需要保证随机性。

安全服务器上生成的随机数,为 16 字节 16 进制数。

uboot_code_enc_flag

U-Boot 加密标记。

  • 0x3C7896E1,不加密
  • 其他,加密使能

uboot_entry_point

U-Boot 入口地址。

控制 GSL 搬移 U-Boot 的位置,不能控制 U-Boot 的运行地址。

默认为"0x48700000"。

uboot Code 区配置项

uboot_area 字段的子配置项。

配置项

说明

uboot_code_file

U-Boot 二进制文件路径。

TEE 相关配置项

TEE 字段的子配置项如下。

TEEOS Key 区配置项

TEEOS_key_area 字段的子配置项。

配置项

说明

TEEOS_key_version_ext, mask_TEEOS_key_version_ext

TEE OS key 区版本和掩码。验签场景时使用。

8 字节大小。和 OTP 字段 tee_os_ver 相关。

每个版本按照 0, 1(0b1), 3(0b11), 7(0b111), 0xf(0b1111)递增,新的版本比老版本多一个 bit。

校验条件:TEEOS_key_version_ext & mask_TEEOS_key_version_ext 中高位的个数大于等于 tee_os_ver & mask_TEEOS_key_version_ext 中高位的个数。

不需要验签时不烧 OTP 并且设置为 0 即可。

TEEOS_external_public_key, TEEOS_external_private_key

TEE OS 外部公私钥对文件路径。验签场景时使用。

  • TEEOS_external_public_key:TEE OS 外部公钥文件路径
  • TEEOS_external_private_key:TEE OS 外部私钥文件路径

TEEOS Info 区配置项

TEEOS_info_area 字段的子配置项。

配置项

说明

TEEOS_version_ext, mask_TEEOS_version_ext

TEE OS Info 区版本和掩码。验签场景时使用。

8 字节大小。和 OTP 字段 tee_os_ver 相关。

每个版本按照 0, 1, 2, 3, 4, 递增,新的版本比老版本加1。

校验条件:(1 << TEEOS_version_ext) - 1 & mask_TEEOS_version_ext中高位的个数大于等于 tee_os_ver & mask_TEEOS_version_ext中高位的个数。

不需要验签时不烧 OTP 并且设置为 0 即可。

key_material_TEEOS

密钥材料,存放在镜像中。TEE OS 加密场景时使用。

加密安全性不依赖此密钥材料,不需要保证安全性。但是需要保证随机性。

安全服务器上生成的随机数,为 16 字节 16 进制数。

TEEOS_ATF_iv

加密 IV 值。TEE OS 加密场景时使用。不需要保证安全性但是需要保证随机性。

安全服务器上生成的随机数,为 16 字节 16 进制数。

TEEOS_ATF_enc_flag

TEE OS 加密标记。

  • 0x3C7896E1,不加密
  • 其他,加密使能

TEE OS Code 区配置项

TEEOS_code_area 字段的子配置项。

配置项

说明

TEEOS_code_file

TEE OS 二进制文件路径。

维护模式相关配置项

maintenance_mode 字段的子配置项。

配置项

说明

GSL_key_maintenance_mode

GSL 维护模式标记。

  • 0x3C7896E1,使能。
  • 其他,不使能。

uboot_key_maintenance_mode

U-Boot 维护模式标记。

  • 0x3C7896E1,使能。
  • 其他,不使能。

TEEOS_key_maintenance_mode

TEE OS 维护模式标记。

  • 0x3C7896E1,使能。
  • 其他,不使能。

DIE_ID

芯片唯一标识,长度为16 字节。

芯片出厂时烧写在 OTP 中无法篡改。使用时需从板端读取。

配置文件中按大端序保存 DIE_ID。为公开信息。

加解密配置项

配置项

说明

oem_root_key

需要和 OTP 中 Obfu_MRK1 的值保持一致。安全服务器上生成的随机数,为 16 字节 16 进制数。

安全模拟配置项

SCS_simulate 字段的子配置项。

配置项

说明

REE_verify_simulate

REE 验签模拟模式标记。

  • 0x2A13C812,使能。
  • 其他,不使能。

TEE_verify_simulate

TEE 验签模拟模式标记。

  • 0x2A13C812,使能。
  • 其他,不使能。

GSL_code_enc_flag

GSL code 加解密模拟模式标记。

  • 0x3C7896E1,不使能。
  • 其他,使能。

uboot_code_enc_flag

Uboot code 加解密模拟模式标记。

  • 0x3C7896E1,不使能。
  • 其他,使能。

TEEOS_ATF_enc_flag

TEEOS code和AFT code 加解密模拟模式标记。

  • 0x3C7896E1,不使能。
  • 其他,使能。

内核及文件系统安全启动校验

该方案是基于上述安全启动方案的特性,在U-Boot验签通过后,再通过在U-Boot上实现验签内核的功能。前一阶段系统引导下一阶段系统前,先对待启动系统进行验签,如果验签成功,再启动Linux系统,否则系统启动失败。验签机制可以保证系统镜像的完整性,如果镜像被篡改或损坏,系统将不会被启动。

安全镜像结构

安全镜像由 Key Area、Code Info Area 和原始镜像三部分组成,如图1所示。

图 1 安全镜像结构图

  1. Key Area 保存了 External Public Key和对 Key Area Body 区域的签名,该区域使用 U-Boot 代码中的 Root Public Key进行验签来保证其完整性。
  2. Code Info Area 里保存了原始镜像的hash值和对Code Info Area Body区域的签名,该区域使用Key Area中的 External Public Key 进行验签来保证其完整性。
  3. Code Area 为原始镜像,该区域通过计算其 hash 值,与 Code Info Area 中保存的 hash 值进行比较来保证其完整性。

警告:

reserved4 区域未经过校验,因此无法保证其数据完整性,在该区域中不应该保存任何有效信息。

安全启动流程

本节只描述 U-Boot 校验内核的流程,如图1所示。若存在其他类型的镜像需要校验(如文件系统),可以参照该流程进行设计,本文不进行说明。

图 1 U-Boot 校验内核流程

安全镜像制作指导

说明:

当前的Verify Boot功能支持RSA3072+SHA256,以及SM2+SM3验签。

rsa验签镜像制作

本节提供通过shell命令完成安全镜像制作,以 kernel.bin 镜像为例,最终得到安全镜像 kernel_sign.bin。

建议用户新建一个目录,将编译的镜像ulmage重命名为kernel.bin,拷贝到新建目录下,执行以下命令,用于生成rsa验签镜像。

  1. 生成两个私钥文件

    openssl genrsa -out root_private_key.pem 3072;
    openssl genrsa -out extern_private_key.pem 3072;
    
  2. 制作 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
    
  3. 制作 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
    
  4. 制作最终签名镜像

    cat image_key_area.bin code_info_area.bin kernel.bin > kernel_sign.bin
    

国密sm2+sm3验签镜像制作

本节提供通过python脚本完成安全镜像制作,以 ulmage 镜像为例,最终得到安全镜像 kernel_image.bin。

解压版本SDK包Hi35xxVxxx_SDK_Vx.x.x.x_xxx.tgz后,执行./sdk.unpack。

  1. 编译镜像

    cd boards/dmeb
    make gslboot_build DEBUG=1 -j
    make kernel DEBUG=1 -j
    

    将生成的ulmage拷贝到tools/pc/image_tool/input目录下

  2. 制作安全镜像。

    1. 将boards/dmeb/components/verify_boot_script/目录下的verify_boot_quick_build.py文件拷贝到tools/pc/image_tool/oem目录下。
    2. 服务器中执行以下命令用于生成签名镜像。

      cd tools/pc/image_tool/
      python oem/verify_boot_quick_build.py
      
    3. 如果没有提前放置公私钥,会创建目录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 支持安全启动配置

  1. 编译 U-Boot 时添加 Verify Boot 支持

    在编译 U-Boot 时执行 make ARCH=arm menuconfig 命令进入配置选择页面,依次进入 Product ---> verify boot enable,按 Y 选中保存并退出。

    cd third_party/u-boot/u-boot-2022.07
    cp configs/hi35xxvxxx_debug_defconfig .config
    make ARCH=arm menuconfig  //使能product下的verify boot enable
    cp .config configs/hi35xxvxxx_debug_defconfig   //拷贝.config文件为默认配置文件
    
  2. 在 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 打印出公钥
  3. 重新编译 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;

修改点主要是两个地方:

  1. 将镜像从 flash 读到 ddr 后,需要先使用 verify_boot 命令传入两个参数(镜像名和 ddr 地址),该命令会校验位于该 ddr 地址的镜像的合法性,若校验不通过则系统复位。
  2. 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生成新的安全启动镜像。

图 1 内核及文件系统启动验签流程框图

安全启动验签流程涉及的哈希值计算、非对称RSA加解密,请自行查询相关资料,本文不再进行说明。如果需要进一步开发加解密功能,可了解其它加密算法,例如对称AES加密算法。

附验证信息U-Boot镜像结构

附验证信息的U-Boot镜像结构如图1所示。在U-Boot镜像尾部追加Kernel相关安全信息,再将带Kernel验证信息的U-Boot镜像制作成安全启动镜像。

图 1 附验证信息U-Boot镜像结构

安全Kernel镜像结构

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

图 1 安全Kernel镜像结构图

功能实现

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板为例进行使用说明:

  1. 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场景使用,请按需选择。
  2. 指定单个表格文件路径方法

    例如配置"boot_param_file7": "./input/reg_info.bin",需要将表格文件reg_info.bin放入镜像工具相对路径boards/dmeb/tools/pc/image_tool/input中,编译时会自动编译进入boot_image.bin中,也可以指定为表格文件的绝对路径,请按需配置。

  3. 指定多个表格文件路径方法

    例如同时配置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中;也可以指定为表格文件的绝对路径,请按需设置。

  4. 总体示例

    如在镜像表格文件配置项中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 维护模式镜像制作

如图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部分

错误码

含义

排查方向

3

检测启动介质或检测uart、usb失败

1.该错误码对应串口打印信息“no device”

2.说明没有检测到 eMMC、FLASH、SD等启动介质,且没有选择UART、USB烧写方式,请检查拨码是否正确

5

UART下载镜像失败

请确认gsl代码大小是否增加,应小于64KB

6

UART下载镜像失败

请确认镜像gsl info区相关字段是否存在异常

7

SD下载镜像失败

请检查SD格式化工具是否为mkdosfs

8

SD下载GSL CODE失败

请检查SD格式化工具是否为mkdosfs

9

USB下载镜像失败

请确认gsl代码大小是否增加,应小于64KB

10

USB下载镜像失败

请确认镜像gsl info区相关字段是否存在异常

11

FLASH介质启动,查找镜像位置失败

请确认备份镜像是否烧写正确

12

FLASH下载镜像失败

请检查FLASH介质及其相关硬件环境

51

fmc提频失败,按24Mhz启动

请检查镜像工具提频相关参数是否正确

52

fmc提频失败,按24Mhz启动

请检查FLASH介质及其相关硬件环境

53

fmc提频失败,按24Mhz启动

请检查镜像工具提频相关参数是否正确

54

FLASH下载GSL CODE失败

1.FMC提频场景:请确认FLASH器件是否支持75Mhz

2.FMC非提频场景(默认不提频):请检查FLASH介质及其相关硬件环境

13

EMMC介质启动,查找镜像位置失败

请确认备份镜像是否烧写正确

14

EMMC下载镜像失败

请检查eMMC介质及其相关硬件环境

55

EMMC下载GSL CODE失败

请检查eMMC介质及其相关硬件环境

56

下载GSL CODE失败

请参考eMMC、FLASH下载失败错误码

15

下载镜像失败

请参考eMMC、FLASH、SD、UART、USB下载失败错误码

42

GSL KEY区校验失败

1.请检查gsl key区数据签名结果是否正确

2.请检查gsl key区数据字段是否正确

50

GSL INFO区校验失败

1.请检查gsl info区数据签名结果是否正确

2.请检查gsl info区数据字段是否正确

60

GSL CODE校验失败

1.如果为加密场景,请先检查gsl code区加密结果是否正确

2.请检查gsl code区hash结果是否正确

GSL部分

错误码

含义

排查方向

62

栈保护检查报错

-

63

检测启动介质或检测uart、usb失败

说明没有检测到eMMC、FLASH、 SD等启动介质,且没有选择UART、USB烧写方式,请检查启动类型寄存器(0x1102031c)参数是否OK

64

SDIO设备状态检查错误

请检查SD卡设备是否存在异常

65

从uart下载uboot key与boot表格失败

请检查boot表格(DDR 表格)长度是否超过15KB

66

从USB下载uboot key与boot表格失败

请检查boot表格(DDR 表格)长度是否超过15KB

67

uboot key区与boot表格数据长度错误

请检查镜像param info区相关字段是否存在异常

68

uboot info区与uboot code区数据长度错误

请检查镜像uboot info区相关字段是否存在异常

101

boot表格数量参数错误

请检查镜像param info区boot 表格数量字段是否存在异常

102

boot表格长度参数错误

请检查镜像param info区boot 表格长度字段是否存在异常

104

REE boot key区数据错误

  1. 请检查REE boot key区签名结果是否正常
  2. 请检查REE boot key区数据字段是否正常

105

param info区校验错误

  1. 请检查param info区签名结果是否正常
  2. 请检查param info区数据字段是否正常

106

param data区(DDR 表格)校验错误

请检查param data区hash结果是否正确

111

从uart下载uboot info与uboot code失败

  1. 请检查boot表格(DDR表格)是否存在异常
  2. 请检查镜像uboot code区是否有增加,应小于1M

112

从usb下载uboot info与uboot code失败

  1. 请检查boot表格(DDR表格)是否存在异常
  2. 请检查镜像uboot code区是否有增加,应小于1M

113

uboot info区校验错误

  1. 请检查uboot info区数据签名结果是否正确
  2. 请检查uboot info区数据字段是否正确

114

uboot code区校验错误

  1. 如果为加密场景,请先检查uboot code区加密结果是否正确
  2. 请检查uboot code区hash结果是否正确

115

TEE key区校验错误

  1. 请检查TEE key区数据签名结果是否正确
  2. 请检查TEE key区数据字段是否正确

116

TEE info区校验错误

  1. 请检查TEE info区数据签名结果是否正确
  2. 请检查TEE info区数据字段是否正确

118

TEEOS code区校验错误

  1. 如果为加密场景,请先检查TEEOS code区加密结果是否正确
  2. 请检查TEEOS code区hash结果是否正确

缩略语

A

AES

Advanced Encryption Standard

ATF

Arm Trust Firmware

C

CPU

Central Processing Unit

G

GSL

Secure Bootloader

J

JTAG

Joint Test Action Group

K

KeyLadder

A structured multi-level key mechanism that ensures secure transmission of control words.

M

MCipher

Multi-channel Cipher module

MSID

MarketSegmentID.

O

OS

Operating System

OEM

Original Equipment Manufacturer

OTP

One Time Programmable

R

REE

Rich Execution Environment

RKP

Root Key Process

S

SCS

Secure Chipset Startup

SMC

Secure Monitor Call

T

TEE

Trusted Execution Environment

TZASC

Trustzone Address Space Controller