实战经验 | 移植 SBSFU 到 STM32G070 的过程

关键词:sbsfu,移植
目录预览
1、前言
2、基于stm32g070和stm32g071的sbsfu 实现差异
3、开始移植
4、测试安全保护特性
5、后述
01
前言
客户使用 stm32g070rbt6 给海外用户开发产品,由于当地新需求,产品需要增加安全启动的功能。但是由于 x-cube-sbsfu 包提供的示例中,只有基于 stm32g071 的示例。客户因此询问该怎么移植。本文将讲解这个移植过程。
02
基于stm32g070和stm32g071的sbsfu 实现差异
在正式讲解之前,我们首先来看一看 stm32g070 和 stm32g071 的 sbsfu 实现差异。
stm32g070 是一个 value line 产品,首先,我们要意识到,有一些安全特性,相比于stm32g071,它是没有的,比如:pcrop,boot_lock 和 secure user memory。那么,缺少了这些安全特性的 stm32g070,是否还能实现安全启动的功能呢 ? 答案是肯定的。我们先来看 pcrop,boot_lock,以及 secure user memory 在 stm32g071 上的 sbsfu 实现中所扮演的角色是什么?
图1.stm32g0 的 sbsfu 安全实现
如上图,在 stm32g071 中,在安全启动的实现中,boot_lock 用来参与实现唯一启动入口,secure user memory 则用来参与实现信任根。pcrop 在安全固件升级实现中用来与mpu 配合实现密钥的安全存储,同时在安全升级过程中涉及到一些密钥的加解密操作,借助于secure user memory 和 mpu 的功能, 将 app 与 sbsfu 本身实现完美隔离。
图2.stm32g0 内存安全映射(运行 sbsfu 时)
回到当前问题,一旦 boot_lock,pcrop,以及 secure user memory 缺少的情况下,这些功能还能实现吗?
我们再来看下对于安全启动而言, 它需要实现哪些基本功能? 
1> 不可更改不可绕过的一段启动代码 
2> 每次复位必先执行安全启动代码 
3> 验证系统配置的完整性 
    • 时钟配置 
    • 寄存器配置 
    • 存储器保护设置, …. 
4> 启动信任根服务 
    • 通过密码学算法与密钥,校验 app 的完整性与合法性(来源可信,未经篡改)
这里需要注意地是,上面提到的某一项安全属性也只是参与实现某一项功能,比如boot_lock,它只是”参与”实现了唯一启动入口这个功能。从图 1 可知, 除了boot_lock,还有 rdp,那么在缺少 boot_lock 的情况下,rdp 是否也可以实现唯一入口启动的功能。很明显,在 rdp2 时,mcu 的入口是唯一的。也就是说,没有 boot_lock的参与下,rdp2 一样可以实现安全启动对唯一入口启动的需求。rdp2+wrp 就可以实现安全启动的前两条基本要求。而第三条基本要求,完全是 sbsfu 内的纯软件实现。第四条要求,通过 rdp2+wrp+mpu 也可以实现。其实, 在缺少了 pcrop,boot_lock 和secure user memory 后,stm32g070 的安全特性其实跟 stm32f4 差不多,我们不妨来看下stm32f4 是如何来实现 sbsfu 功能的。
图3.stm32f4 的 sbsfu 安全实现
如上图所示,在 stm32f4 中,借助于 rdpl2,wrp,mpu 就实现了 sbsfu 的全部功能。
图4.stm32f4 的 sbsfu 内存映射
到这里,我们完全可以确信,在缺少了 boot_lock,pcrop 和 secure user memory这些安全特性之后,stm32g070 完全可以按照 stm32f4 实现 sbsfu 的方式来进行!
在确立了大方向后, 我们接下来看具体如何实现。
03
开始移植
第一步 : 确保原始工程运行正常 
从 st 官网上下载最新了 sbsfu 包(v2.6.1),打开stm32cubeexpansion_sbsfu_v2.6.1projectsnucleo-g071rbapplications2_images目录,其下有三个工程,2_images_secorebin(后续简称 secorebin 工程),2_images_sbsfu(后续简称 sbsfu 工程),2_images_userapp(后续简称 userapp 工程)。使用对应 ide 按顺序依次编译, 然后将 sbsfu 工程生成的 bin 文件烧录到 nucleo-g071rb板内,打开 tera term 串口终端, 通过 tera term 烧录 app 进去。目的是首先确认原始工程一切运行正常。接下来就开始修改了。
第二步 : 将与 boot_lock, pcrop, secure user memory 相关的宏全部关闭 
打开 sbsfu 工程的 app_sfu.h 头文件,找到并关闭下面三个宏 :
重新依次编译 sbcorebin,sbsfu,userapp 三个工程,并重新测试通过。
至此, nucleo-g071rb 板上运行的是移除了 boot_lock, pcrop,secure user memory 三个安全特性后的 sbsfu 程序,这个原理上与 stm32g070 上原则上是一致的。接下来就是要移植到 nucleo-g070rb 板上了,剩下的就只有 stm32g070 与 stm32g071 的非安全特性方面的差异了。
第三步 : 移植到 stm32g070rb 
首先得准备下一块 nucleo-g070rb 板。接着将三个工程 sbcorebin,sbsfu,userapp 的 device 修改成目标 mcu stm32g070rb,然后将三个工程的 c++预定义宏stm32g071xx 修改成 stm32g070xx。
以 keil 为例 :
图5.device 选择 stm32g070rbtx
图6.c++编译宏修改
stm32cubeide 工程的 device 配置比较难修改,因为它原本是灰色的,不允许修改。但我们使用 ue 打开.cproject 一样可以强制修改 :
打开对应的.cproject 文件,搜索关键字 g071,将以下几处替换成 g070(修改两处) :
图7.stm32cubeide 下的 device 修改
修改完后,打开 stm32cubeide 工程,在其 mcu 和 board 的配置也会有相应的变化:
图8.stm32cubeide 的 mcu 配置
由此可见,在 stm32cubeide 工程的 mcu 配置也可以做相应的修改了。这是一个小技巧。
至此,三个工程的工程配置都做完了相应修改。接下来的就是代码方面的修改了。
首先 stm32g070 的时钟树是没有 pllq 输出的,因此,在 sbsfu 和 userapp 这两个工程内找到 systemclock_config()函数,注释掉 pllq 的设置,如下所示 :
原先 stm32g071 的工程中的打印信息是通过 lpuart1 对应的 pa2,pa3 打印的,换成nucleo-g070rb 板后,其引脚虽仍然是 pa2,pa3 引脚用来串口打印,但是 stm32g070中是没有 lpuart1 这个外设的,需要换成 usart2,因此,其对应的代码修改如下 :
在 sbsfu 工程中, 打开 sfu_low_level.h 头文件 , 和 userapp 工程的 com.h 头文件中:
如上红色部分即为修改处。
至此,代码部分全部修改完成。重新按顺序依次编译 sbcorebin,sbsfu,userapp 三个工程,将 sbsfu 工程首先烧录到 nucleo-g070rb 板,然后通过串口终端,按提示,用 ymodern 协议将 userapp 对应的.sfu 文件烧录进去。整个流程都可以正常运行的。这说明软件框架基本已经 ok。接下来运行下 app 中各种安全测试。
04
测试安全保护特性
当程序跳入到 app 后,显示如下界面
图9.测试主界面
当选择 2 test protection :secure user memory 时,结果会出错 :
图10.测试保护
很明显,这里需要修改下,因为 stm32g070 是没有 secure user memory 的。查看其对应代码:
原来 userapp 是测试直接读取保存在 secorebin 内的密钥数据, 测试是否能读出。结果发现是可以的,因此,保护效果是出问题了。
首先我们修改下此函数,由于 stm32g070 中 secure user memory 是不存在的, 此函数叫 test_protections_runsecusermem_code()已经不再合适, 依照 stm32f4 的sbsfu 实现,将此函数换成 test_protections_runse_code()函数:
同样的尝试读取密钥:
图11.userapp 尝试读取密钥
测试结果可想而知, 肯定是可以读取的。于是得查看下为什么可以。
仔细查看图 2 的 stm32g071 的 sbsfu 原来实现中,se key 是通过 pcrop+secure user memory 来保护的,现在换成 stm32g070,原本 secure user memory 用来作隔离机制, 现在换成了 mpu, 而原本保护 se key 的 pcrop 在 g070 中压根就不存在,于是 se key 只剩下 mpu 来保护,因此,我们接下来得着重分析 mpu 对 se key 的保护。
为了方便调试,我们首先得将除 mpu 以外的所有保护通通关闭,只剩下 mpu 保护。于是在 sbsfu 工程中,在 app_sfu.h 头文件中,将以下宏通通注释掉:
然后开始调试。在调试过程中,发现程序在从 sbsfu 跳转到 userapp 之前,在代码中特意将 mpu 关闭:
如在 sfu_low_level_security.c 源文件中的内存函数 sfu_ll_secu_activatesecuser()中有这么一行代码:
这就是为什么 userapp 中仍然可以直接读取密钥的原因了。很明显,接下来我们需要将 sekey 用 mpu 保护起来。但在这之前,我们得首先弄清楚,当程序跳转到 userapp 后,flash 和ram 该如何设置 mpu 保护?
在 um2262 中, 有提到当程序跳转到 userapp 后 flash 和 ram 的状态:
图12.userapp 运行时的 flash 和 ram 状态
从上图可以看出,原本 secure user memory 保护的区域,我们得使用 mpu 来替代实现相应功能,包含 sbsfu 整个代码和 slot#1 内的 header 信息。这也就是在代码跳转到 userapp之前需要做的事情。而黄色对应的 sram 区别已经擦除,当程序跳转到 userapp 后其实已经没必要再保护。
于是在跳转到 userapp 的内存函数中配置 mpu:
注意这里是一个内存函数,它所调用的所有子函数也都是内存函数。在这个函数中我们将sbsfu 所在的 64k flash,再加上 2k 的 active slot 的 header 信息保护起来。内存 ram 我们并没有配置保护,因为跳转到 userapp 后它就完全开放,且内容已经清空。
对应的, 我们在 userapp 中增加对 header 的测试函数 :
重新烧录程序,当程序运行后,选择 2 进行 protection 测试,然后再选择 2,测试访问sbsfu 所有的 64k 区域:
图13.测试 sbsfu 的 64k 代码区
发现会一直卡住, 这说明 mpu 对整个 sbsfu 64k 区域的保护已经生效。同样的,选择’3’测试 header 所在区域:
图14.测试 header 对应的 2k 区域
发现程序读取 0x0801 0000 地址时会一直卡住,这说明 mpu 对 header 的保护也已经生效。然后再测试了下其它选项,包含下载新固件,还有其它默认的一些安全特性,基本都是ok 的。这说明整个程序基本已经 ok。
最后再恢复之前注释掉的除 mpu 之后的保护。
05
后述
本文旨在通过一个相对容易的移植, 让读者对 sbsfu 的移植过程有一个大概了解以起到参考和示范作用。
完整内容请点击“阅读原文”下载原文档。
原文标题:实战经验 | 移植 sbsfu 到 stm32g070 的过程
文章出处:【微信公众号:stm32单片机】欢迎添加关注!文章转载请注明出处。

新日本无线用于车载电子的GNSS射频前端模块NJG1159PHH-A宣布量产
多种感知功能的拟人化灵巧手,将进一步协助机器人进一步开拓市场
窥探日本制造技术创新史的兴衰
预计2021年AMOLED产能相比2018年翻倍,三星成最大受益者
机器人助阵“双11“,10亿件也不在话下
实战经验 | 移植 SBSFU 到 STM32G070 的过程
智能疏散系统的优势有哪些
无人机反制枪能针对哪些小型飞行器
华硕双十一钜惠来袭,4K新品PA279CV显示器广受欢迎
UWB强势来袭 无线通信技术百花齐放
华为星闪技术网络架构怎么样 雷柏科技星闪技术应用
关于光刻技术浅述
dxDAO实验的成功对DAO和一般的软件治理意味着什么
ELF 1技术贴|开发板底板电源电路讲解
可调开关电源常见故障及检修过程
SMT工艺材料简介
退耦不好负载电容过大等对集成运放电路影响有多大?
美的的库卡:工业机器人企业的百年历史与近年市场分析
优必选今日在港交所上市
未来黑科技Futurus推出最新科技 全方位赋能全球车企自动驾驶技术