01 前言
本文引用地址:本文档通过一个动手实验, 详细演示了如何在 STM32H563 上运行一个 OEMiROT 的功能. 旨在针对那些 OEM 想自己实现一个基于 STM32H563 上的 iROT 功能而又不知如何开始的开发者.
02 准备工作
开发板 : NUCLEO-H563ZI
软件包 : STM32Cube_FW_H5_V1.1.0
工具:
• STM32CubeProgrammer v2.14.0
• Tera Term 串口终端显示
• Trust Package Creator(安装 STM32CubeProgrammer 时一并安装, 注意勾选)
IDE: STM32CubeIDE v1.13.0
03 烧录 OEMiROT 固件并运行
3.1. 脚本环境配置板编程基础
本动手实验基于 STM32CubeH5 固件包, 此包必须位于一个没有中文且没有空格的路径下, 于是我们将此包拷贝到 C:workspace 目录, 在此包路径 STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIROT_Provisioning 目录下有一个 env.bat 文件, 用文本编辑器(如记事本)打开此文件:
检查上面两行, STM32CubeProgrammer_CLI.exe, 以及 STM32TrustedPackageCreator_CLI.exe 这两个工具的安装路径是否跟你电脑中的安装路径符 合, 如果不符, 则需要进行相应的修改.
3.2. 运行 OEMiROT 预配置(provisioning)脚本
再进入到 cube 包下的目录 STM32Cube_FW_H5_V1.1.0ProjectsNUCLEOH563ZIROT_ProvisioningOEMiROT 目录下, 有一个名为 provisioning.bat 的脚本, 双击运行它:
如上图, 系统会自动打开一个 DOS 命令终端窗口, 在此动手实验过程中, 如无特别说明, 此窗口将一直保持, 我们将通过此窗口的提示信息进行每一步的操作.
如上图, 信息提示我们打开TrustedPackageCreator 工具, 生成 OEMiROT_Config.obk 文件.
3.3. 生成 OEMiROT_Config.obk
打开 TrustedPackageCreator 工具:
如上图, 在最左边 ①处点击 “H5”, 然后在②处选项”OBKey”, 接下来在③处选择STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIROT_ProvisioningOEMiROTConfig 目录下的 OEMiRoT_Config.xml 文件, 此文件为生成 OEMiROT 对应 obk 文件的配置文档. 然后下面会显示 3 个密钥对, 从上到下分别为 :
• OEMiRoT_Authentication_S.pem: Secure APP 对应的认证密钥(使用公钥)
• OEMiRoT_Authentication_NS.pem: Non Secure APP 对应的认证密钥(使用公钥)
• OEMiRoT_Encryption.pem : Secure APP+Non Secure APP 固件加密密钥对应的解包密钥(使用私钥)
这三个密钥其实都是成对的, 即公钥私钥对. 位于 Keys 目录下. STM32CubeH5 包下已经自带了默认的密钥对, 如果你不想使用默认的, 则可以点击上图中的4中的 “Regenerate” 重新生成这三个密钥对. 一旦重新生成, 则需要注意保存这三个密钥对.
接下来就要生成 OEMiROT 对应的 obk 文件了, 在右边的输出路径下, 选择一个路径, 比如Binary 目录. 最后点击生成. 则将在 Binary 目录下生成 OEMiRoT_Config.obk 文件.
3.4. 生成 DA 对应的 obk 文件
回到脚本终端窗口, 输入回车键 :
如上图, 提示你通过 TPC 工具生成 DA_Config.obk 文件. 有关如何生成 DA_Config.obk 文件,之前已有其它文档讲述, 且 STM32CubeH5 包下STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIROT_ProvisioningDABinary 此目录中已经有现存的 DA 对应的 obk 文件, 其对应的私钥和证书分别位于上一级目录下的 Keys 目录和 Certificates 目录下, 这些文件均可直接使用, 所以这里不再重复讲述它们的生成过程.
直接按下回车键..
3.5. 编译 OEMiROT_Boot 工程
如上图, 提示用户打开 OEMiROT_Boot 工程并编译.
于是用 STM32CubeIDE 打开工程, 路径为: STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIApplicationsROTOEMiROT_BootSTM32CubeIDE 目录下, 编译过后,会在工程下的 Binary 目录下生成 OEMiROT_Boot.bin 文件.
再回到终端窗口按下回车键…
3.6. 编译 OEMiROT_Appli_TrustZone 工程
用 STM32CubeIDE 打开工程: STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIApplicationsROTOEMiROT_Appli_TrustZoneSTM32CubeIDE
此工程下有两个子工程 :
如上图所示, 先编译 Secure 工程, 再编译 NonSecure 工程. 编译通过后, postbuild 脚本会在Binary 目录下生成原始 bin 文件和加密后的固件.
原始 bin 文件是用来初始安装的, 而加密后的固件是用来做升级的. 加密和签名过程正是postbuild 脚本来实现的, 其对应的固件加密密钥是此次编译过程中脚本随机产生的密钥. 此密钥会通过 3.3 节中所产生的 OEMiRoT_Encryption.pem 对应的公钥来进行打包并放入 header 中.而签名所用的私钥并正是 3.3 节中所产生的 OEMiRoT_Authentication_S.pem 私钥, 它对应Secure 工程签名, OEMiRoT_Authentication_NS.pem 则对应 Non Secure 工程签名.
3.7. 手动生成加密且签名的映像文件(可选)
除了通过 postbuild 脚本来自动生成固件加密且签名的映像文件外, 你也可以通过手动的方式来生成它.如下图, 我们可通过 TPC 手动将原始 bin 文件加密且签名.
如上图, 打开 TPC, 左边①处选择 “H5”, 然后在②处选择”Image Gen”, 在③处输入配置文件 : STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIROT_ProvisioningOEMiROTImages OEMiROT_S_Code_Image.xml. 然后在Firmware area size 处保持默认的 0x6000, version :1.0.0, Firmware binary input file 处导入S App 生成的明文固件映像. Image Out File 处即可生成的加密且签名的固件。加密的密钥是随机的, 它通过打包进 header 中, 如之前描述. 这就是手动生成加密且签名的固件映像方法. 由于App 工程的 postbuild 脚本会自动完成, 所以, 这一步骤并不是必须的.
此外需要注意地是, 在 STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIROT_ProvisioningOEMiROTImages 目录下还有其它几个用来手动生成加密签名映像的配置文件, 如下图所示 :
通过这几个文件名, 顾名思义, 分别对应着 Secure App 的固件, 数据, NonSecure App 的固件,数据映像, 如果需要手动生成这四种加密且签名的映像文件, 则通过 TPC 手动导入对应的 xml配置文件. 在 Firmware binary input file 输入原始 bin 文件, 在 Image Out File 处输入导出文件, 然后点击 Generate Image, 生成最终的加密且签名的映像文件(如rot_tz_s_app_enc_sign.hex, 或者 rot_tz_ns_app_enc_sign.hex).
3.8. 生成加密签名的数据映像(可选)
回到终端窗口按下回车键, 如下所示 :
提示我们通过 TPC 手动生成加密数据映像. 工程中默认是未定义任何 Data image 的(flash_layout.h 头文件):
因此, 此步骤默认我们是可以跳过. 如果工程中此宏修改成 1, 则需要手动通过 TPC 来生成加密的数据映像. 方法类似于 3.6 节的手动生成环节, 只不过配置文件换成 xxx_Data_Image.xml.
这一步骤, 我们直接在终端窗口中按下回车键…
接下来再次提示生成 NS APP 对应的 Data Image, 同理, 在工程中默认宏中是没有配置的, 因此直接按下回车键…
3.9. 预配置(provisioning)
在做预配置之前, 提示你是否已将 BOOT0 引脚拉低. 确认 NUCLEO-H563ZI 板上的 BOOT0引脚没有连到 VDD(CN4 的 BOT0 引脚未接任何东西即可). 确认后按下回车键…
如上图, 这此过程中, 脚本会自动烧录 boot, S APP, NS APP 三个 bin 文件, 以及配置 option bytes, 接下来提示你输入芯片最终的 product state, 这里我们输入”CLOSED”…(千万别设置为 LOCKED 状态!)
如上图所示, 在此过程中, 脚本会先将芯片的 product state 切换到 provisioning 状态, 然后再做预配置, 这里会预配置 OEMiROT 的 obk 文件,以及 DA 的 obk 文件, 然后最终将芯片的product state 设置为你上一步输入的最终芯片状态. 最后系统提供已完成. 到这一步, 脚本的整个流程结束. 接下来, 我们验证下烧录后的芯片是否工作正常.
3.10.检查程序运行状态
打开 Tera Term, 设置串口波特率为 115200 bps, 然后复位板子, 查看打印信息…
如上图所示, 当打印信息显示 User App #A 时, 表示 NS APP 已经运行成功, 所有程序运行结果均正常!
04 固件更新
接下来, 我们将演示通过 NS APP 触发程序跳转到内置的 bootloader 中, 并通过串口下载新的加密固件, 复位后并安装它.
4.1. 修改代码, 并重新编译工程
打开 NS APP 的工程, 在 main.c 文件中将 NS APP 的版本号从 “A”改成”B”:
然后重新编译 NS APP 工程.
Postbuild 脚本将重新生成 S APP 和 NS APP 的加密固件 :
如上图所示, 这四个文件均将重新生成.
接下来我们将升级 APP 固件.
4.2. 跳转到 loader 程序
在串口终端中我们输入”1”:
如上图所示, 输入 1 后, 程序跳转到芯片内置的 bootloader 中.
断开 Tera Term 的串口连接 :
4.3. 通过 STM32CubeProgrammer 下载新固件
打开 STM32CubeProgrammer, 并通过串口模式连接芯片:
将新生成 NS APP 的加密后的固件 rot_tz_ns_app_enc_sign.hex 拖入到STM32CubeProgrammer 中 :
如上图点击下载.
同样的, 也可以将 S APP 的加密固件 rot_tz_s_app_enc_sign.hex 拖入STM32CubeProgrammer 中并下载 :
下载成功后, 断开 STM32CubeProgrammer 的串口连接, 并使 Tera Term 重新连接串口 , 然后再重启 NUCLEO-H563ZI 板, 于是可以看到如下打印信息 :
如上图所示, NS APP 的版本打印信息从 “A”已经改成”B”了, 这说明固件(加密且签名的)已经更新成功.
05 还原
5.1. DA 回退
打开 STM32CubeProgrammer, 采用 ST-Link 模式, 在未连接的情况下,在左边选择盾牌图标, 然后再选择”DA”选项卡, 再点 Discover 按键….
界面变成如下所示 :
如上图所示, 第一个红框内输入 DA 私钥文件 :
STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIROT_ProvisioningDAKeyskey_1_root.pem,
第二个红模式内输入证书 : STM32Cube_FW_H5_V1.1.0ProjectsNUCLEO-H563ZIROT_ProvisioningDACertificates cert_root.b64
然后击点 continue 按键, 然后界面变成如下所示 :
如上图所示, 在左边选择”Full Regression”, 然后再点击 Execute 按键…
然后如上图所示, DA 回退成功. 此时,查看 option bytes 值 , product state 已经变成Open(0xED), TZEN 依然使能(TZEN=0xB4) :
5.2. 关闭 trustzone
如果需要也可以将 TZEN 关闭(TZEN=0xC3, 可直接修改, 这点与U5必须伴随 RDP回退操作不同), 这样芯片就完成恢复成原始状态了.