你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32将移植 SBSFU 到 STM32G070过程分享

[复制链接]
STMCU小助手 发布时间:2023-12-11 14:02
01前言: e- Y3 R* c9 W* m5 S8 ^
客户使用 STM32G070RBT6 给海外用户开发产品,由于当地新需求,产品需要增加安全启动的功能。但是由于 X-Cube-SBSFU 包提供的示例中,只有基于 STM32G071 的示例。客户因此询问该怎么移植。本文将讲解这个移植过程。$ i: y# U2 \/ F3 ]: G
+ J  ]7 q$ Y' ~5 v
" A  D" M- E. q& ^. B) C  ?. V
02基于STM32G070和STM32G071的SBSFU 实现差异+ z; U( b( w$ [0 W9 w
在正式讲解之前,我们首先来看一看 STM32G070 和 STM32G071 的 SBSFU 实现差异。 6 C/ c1 u. ^; O7 u7 ?& a& J+ D

7 ~+ L% K- \1 d: Q0 ^STM32G070 是一个 value line 产品,首先,我们要意识到,有一些安全特性,相比于STM32G071,它是没有的,比如:PCROP,BOOT_LOCK 和 Secure User Memory。那么,缺少了这些安全特性的 STM32G070,是否还能实现安全启动的功能呢 ? 答案是肯定的。我们先来看 PCROP,BOOT_LOCK,以及 Secure User Memory 在 STM32G071 上的 SBSFU 实现中所扮演的角色是什么?0 W- x5 P& s9 z; M" a  G( c6 F

' T/ c9 I7 D& u- I. E- w
微信图片_20231211140158.jpg

1 x' G" F7 W0 z! a9 u- U- }" }

+ ]7 V3 z( {- y* G* P
图1.STM32G0 的 SBSFU 安全实现

4 K1 b5 }) Q* W: D% v
4 m# I( L: V6 F
如上图,在 STM32G071 中,在安全启动的实现中,BOOT_LOCK 用来参与实现唯一启动入口,Secure User Memory 则用来参与实现信任根。PCROP 在安全固件升级实现中用来与MPU 配合实现密钥的安全存储,同时在安全升级过程中涉及到一些密钥的加解密操作,借助于Secure User Memory 和 MPU 的功能, 将 App 与 SBSFU 本身实现完美隔离。
6 w, f2 t, m/ T0 m' ~0 D7 f3 J2 y$ A8 x2 K/ r9 Z" `
微信图片_20231211140155.jpg

- B& B; X$ u; y6 t  l+ k
图2.STM32G0 内存安全映射(运行 SBSFU 时)
9 Z& p; @4 _& n  z+ |8 ~

& d, M# ?4 Y' f6 J: |回到当前问题,一旦 BOOT_LOCK,PCROP,以及 Secure User Memory 缺少的情况下,这些功能还能实现吗?
% f  a3 C# u( q0 A# w; M6 F; X' k3 \% o
我们再来看下对于安全启动而言, 它需要实现哪些基本功能?( F# T& x) p- i8 o( e  W
1> 不可更改不可绕过的一段启动代码2 R2 h1 d' z* X7 d/ L$ D. _/ ~
2> 每次复位必先执行安全启动代码9 i$ D* \5 ^0 c0 e
3> 验证系统配置的完整性& P. @+ l2 _9 ]9 R: o+ m
    • 时钟配置
7 l" j4 n( z9 Y: ?    • 寄存器配置
6 [* |. [5 S, d3 k. p2 q1 X/ g    • 存储器保护设置, ….7 H9 Z% V* K7 C* P3 ]+ ^8 F
4> 启动信任根服务8 b7 u9 S# e: Q# b
    • 通过密码学算法与密钥,校验 App 的完整性与合法性(来源可信,未经篡改)
& E8 e" H4 Z) o; t8 l/ L5 x6 ?4 b1 y1 R# g- y8 I
这里需要注意地是,上面提到的某一项安全属性也只是参与实现某一项功能,比如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 功能的。, f/ N, S4 M* I. b! B3 `' n
1 O2 N: [- J! l8 I: Y* R- |
微信图片_20231211140151.jpg

3 k  P0 A8 T3 a: f: H0 s' f3 N
图3.STM32F4 的 SBSFU 安全实现
% d$ K; y) a' Z/ C! w, J

0 _. D% D' |5 C如上图所示,在 STM32F4 中,借助于 RDPL2,WRP,MPU 就实现了 SBSFU 的全部功能。
5 d7 X+ R; g9 x$ w
7 c5 A. N; M  K6 Z6 O
微信图片_20231211140148.jpg
& [7 M. L' i% ^5 M
图4.STM32F4 的 SBSFU 内存映射
) I9 B' S6 Q4 ~+ o. g5 q  {& p+ Y8 k8 ]
, ^* c7 g5 T4 y* @' F; d) A+ j
到这里,我们完全可以确信,在缺少了 BOOT_LOCK,PCROP 和 Secure User Memory这些安全特性之后,STM32G070 完全可以按照 STM32F4 实现 SBSFU 的方式来进行!
: Z6 j* ~% M! I2 m; E6 P
1 W$ M! ?+ _. a& t& R& y, e在确立了大方向后, 我们接下来看具体如何实现。# {. w7 ^5 m" [2 `4 L# Z8 X( I) R
* x! D, I0 Z4 i8 i9 \7 B
03开始移植* U: Q0 q; z, M4 B$ p0 H7 E6 E' ~
第一步 : 确保原始工程运行正常
. w) {" o0 E) w( G! C' U7 m从 ST 官网上下载最新了 SBSFU 包(v2.6.1),打开STM32CubeExpansion_SBSFU_V2.6.1\Projects\NUCLEO-G071RB\Applications\2_Images目录,其下有三个工程,2_Images_SECoreBin(后续简称 SECoreBin 工程),2_Images_SBSFU(后续简称 SBSFU 工程),2_Images_UserApp(后续简称 UserApp 工程)。使用对应 IDE 按顺序依次编译, 然后将 SBSFU 工程生成的 bin 文件烧录到 NUCLEO-G071RB板内,打开 Tera Term 串口终端, 通过 Tera Term 烧录 APP 进去。目的是首先确认原始工程一切运行正常。接下来就开始修改了。 - [1 @; z0 r3 O# f. ^1 Q& h- ?
  b6 D8 ~2 o6 K/ H4 h# u
第二步 : 将与 BOOT_LOCK, PCROP, Secure User Memory 相关的宏全部关闭
4 k' s: M4 ~: c- y9 B4 b. ~; O打开 SBSFU 工程的 app_sfu.h 头文件,找到并关闭下面三个宏 :! n& k: |; v5 @2 ]$ t( K1 g

5 {1 m) l8 o% b6 ^& W
微信图片_20231211140145.jpg

6 |0 N+ Q' w- r7 d. l3 ?: }

0 ~0 }! x; [: h! [" @, \5 ]6 u$ _/ U重新依次编译 SBCoreBin,SBSFU,UserApp 三个工程,并重新测试通过。
+ {8 C% B  s6 F0 Z* N# }9 P
* a8 V+ C1 @* n) v至此, NUCLEO-G071RB 板上运行的是移除了 BOOT_LOCK, PCROP,Secure User Memory 三个安全特性后的 SBSFU 程序,这个原理上与 STM32G070 上原则上是一致的。接下来就是要移植到 NUCLEO-G070RB 板上了,剩下的就只有 STM32G070 与 STM32G071 的非安全特性方面的差异了。
2 ?+ x. `( C9 ^- a0 S  f# y3 [! w4 u# M$ Q* Q# y5 x/ ]5 g9 C
第三步 : 移植到 STM32G070RB, S0 l) {) p* J1 S9 G5 M6 x8 z
首先得准备下一块 NUCLEO-G070RB 板。接着将三个工程 SBCoreBin,SBSFU,UserApp 的 device 修改成目标 MCU STM32G070RB,然后将三个工程的 C++预定义宏STM32G071xx 修改成 STM32G070xx。
& L4 H* `. B4 V" F7 J! H/ q- _
/ k% c4 S% Q6 H( J( Z( K/ r以 Keil 为例 :4 O/ _: Y2 a% F. e
微信图片_20231211140142.jpg

) r1 ~# }7 r  B. Z
图5.device 选择 STM32G070RBTx

, h, [0 }# J8 M- L
$ ]5 s6 _9 ?" D2 p4 R  c
微信图片_20231211140139.jpg
1 |6 l! D' U9 u. Z
图6.C++编译宏修改
, U0 A) U$ z4 A3 K4 C9 M
& \5 M: |9 k& B- F, P: k4 U
STM32CubeIDE 工程的 device 配置比较难修改,因为它原本是灰色的,不允许修改。但我们使用 UE 打开.cproject 一样可以强制修改 :
$ z" z  a6 A. j4 R1 m9 R/ f- ~2 J% P3 k! }9 F2 m/ Y( ?
打开对应的.cproject 文件,搜索关键字 G071,将以下几处替换成 G070(修改两处) :& q4 e3 d' L- S8 @; q  T5 @- T
' t, [6 c8 r3 L5 v8 j, [
微信图片_20231211140136.jpg
, R. n% q5 ?' v' N6 p: E  Z4 l
图7.STM32CubeIDE 下的 device 修改

. m. m$ w( v) A5 M4 N2 N
2 l  M, Z8 Q# J( }, }- X; k4 F
修改完后,打开 STM32CubeIDE 工程,在其 MCU 和 Board 的配置也会有相应的变化:
6 ^* W9 w0 r0 ~; f. Q6 A8 y. Z! J" W; m  A' E7 U
微信图片_20231211140132.jpg
9 M3 i, \/ S& b) H9 v5 W+ s  j! l
图8.STM32CubeIDE 的 MCU 配置

, a" F, Y9 U- h1 u/ l

7 j8 b; p2 t( z  X& j" D9 ~由此可见,在 STM32CubeIDE 工程的 MCU 配置也可以做相应的修改了。这是一个小技巧。
# p% J. q8 C4 O% m
. h# s3 b+ i$ Z: \6 X# t至此,三个工程的工程配置都做完了相应修改。接下来的就是代码方面的修改了。( W8 l7 }6 A6 p  P
3 ?9 I, U- \; O) D! e1 i5 \$ W
首先 STM32G070 的时钟树是没有 PLLQ 输出的,因此,在 SBSFU 和 UserApp 这两个工程内找到 SystemClock_Config()函数,注释掉 PLLQ 的设置,如下所示 :
+ B$ }% r( P; \7 g
& z8 a: g; z! l8 {- z; ], A5 n) M
微信图片_20231211140129.jpg 6 n' b2 o) U7 j) w8 T
# g% H  A6 b$ X! g7 O$ z; |+ X
原先 STM32G071 的工程中的打印信息是通过 LPUART1 对应的 PA2,PA3 打印的,换成NUCLEO-G070RB 板后,其引脚虽仍然是 PA2,PA3 引脚用来串口打印,但是 STM32G070中是没有 LPUART1 这个外设的,需要换成 USART2,因此,其对应的代码修改如下 :* N! R* I/ S% W. B
* d# p( s% J& ?, D
在 SBSFU 工程中, 打开 sfu_low_level.h 头文件 , 和 UserApp 工程的 com.h 头文件中:& K9 [3 b- G, {/ v# d6 _/ L2 Z
7 H& m4 g4 ~; p4 s/ n' r5 |
微信图片_20231211140125.jpg
1 o6 u; y6 F3 A( k 微信图片_20231211140121.jpg 1 D( B6 @( ?6 X5 u

- h+ w7 y% v1 k+ G如上红色部分即为修改处。
4 z/ q9 w: Y/ F) A
, t. B9 j5 w# ?至此,代码部分全部修改完成。重新按顺序依次编译 SBCoreBin,SBSFU,UserApp 三个工程,将 SBSFU 工程首先烧录到 NUCLEO-G070RB 板,然后通过串口终端,按提示,用 YModern 协议将 UserApp 对应的.sfu 文件烧录进去。整个流程都可以正常运行的。这说明软件框架基本已经 OK。接下来运行下 APP 中各种安全测试。
! k" \; s* q, C; w, j4 p3 \
4 [- s, r( w( g  ]6 a1 k  c
4 ^, B! R2 `+ K9 [- I  C
04测试安全保护特性
$ K- ?  Y6 R; d+ [7 c  T当程序跳入到 APP 后,显示如下界面& _7 I5 Q  Z. U# d7 O! V
, @. P( _* e) R
微信图片_20231211140118.jpg

: r7 I, ^. g8 p5 U& T$ R# ~
图9.测试主界面
% Y6 j% w* W( c& y1 K5 O+ g
3 \6 @0 N- \  `( q
2 C  \1 J" b& W/ `2 @
当选择 2 Test Protection :Secure User Memory 时,结果会出错 :
  y& ~5 X8 O/ M# Q1 d
8 u) J' J* Q1 G/ M4 t1 d/ K+ C
微信图片_20231211140114.jpg
9 a  E$ A0 v4 \7 x
图10.测试保护
1 g1 r7 s$ n0 V5 E7 y
! g3 s/ k- D& X5 ~! {
很明显,这里需要修改下,因为 STM32G070 是没有 Secure User Memory 的。查看其对应代码:8 W- G, @- O4 P2 N. {$ y4 F! x$ G
+ D& F) {' W2 J! Q/ s9 r
微信图片_20231211140111.jpg 0 V7 ^+ A8 G7 g: H  n% u2 z
微信图片_20231211140108.jpg
/ D8 z9 ]' s- `( {+ d# p0 M
' N; t: G' ]8 f0 x原来 UserApp 是测试直接读取保存在 SECoreBin 内的密钥数据, 测试是否能读出。结果发现是可以的,因此,保护效果是出问题了。
- ~- d# ?/ s9 ^

2 }; n8 W0 I3 ^  \0 v9 Q7 X首先我们修改下此函数,由于 STM32G070 中 Secure User Memory 是不存在的, 此函数叫 TEST_PROTECTIONS_RunSecUserMem_CODE()已经不再合适, 依照 STM32F4 的SBSFU 实现,将此函数换成 TEST_PROTECTIONS_RunSE_CODE()函数:
4 z7 z# U: n$ Z" b% a
1 L9 z, S, j* \* T$ d% X- U
微信图片_20231211140041.jpg
) M* a" V+ D, k9 W2 G" b9 c% D
. G! W5 H: h1 Y$ u同样的尝试读取密钥:
+ N7 W( w5 R1 z/ y. \8 N5 U' G- ^# }3 e! p, V
微信图片_20231211140036.jpg

1 y% b. D) o% t+ h5 |
图11.UserApp 尝试读取密钥
- N6 @% B4 ?8 d. R1 C# Z2 W
/ x4 V" D7 N4 m$ a* e+ H
测试结果可想而知, 肯定是可以读取的。于是得查看下为什么可以。 5 v, c3 t7 d5 C
: h. D8 h  _" s# G/ S
仔细查看图 2 的 STM32G071 的 SBSFU 原来实现中,SE Key 是通过 PCROP+Secure User Memory 来保护的,现在换成 STM32G070,原本 Secure User Memory 用来作隔离机制, 现在换成了 MPU, 而原本保护 SE Key 的 PCROP 在 G070 中压根就不存在,于是 SE Key 只剩下 MPU 来保护,因此,我们接下来得着重分析 MPU 对 SE Key 的保护。
- L) q6 J( ~0 y7 Y( C! f  X% m" q+ c4 h
为了方便调试,我们首先得将除 MPU 以外的所有保护通通关闭,只剩下 MPU 保护。于是在 SBSFU 工程中,在 app_sfu.h 头文件中,将以下宏通通注释掉:
' W" M5 q3 \5 e9 a6 e0 |+ K! _: O- t" z# q: P" w: d4 V
微信图片_20231211135943.jpg & j) R; J. E! c" D$ n" S
微信图片_20231211135940.jpg 4 c5 E0 \8 k6 y5 H
, ]4 K* x9 J+ j1 T' W
然后开始调试。在调试过程中,发现程序在从 SBSFU 跳转到 UserApp 之前,在代码中特意将 MPU 关闭: & M2 J0 u/ s/ V" `
* U! u& Y' w9 @; d1 [  m* X$ A" D$ n
如在 sfu_low_level_security.c 源文件中的内存函数 SFU_LL_SECU_ActivateSecUser()中有这么一行代码:6 R& ?0 S/ M7 d5 `

4 c1 ~, \, p+ t7 `$ ^' O4 H
微信图片_20231211135937.jpg
; @) l! [4 M* b4 @  p7 ]4 L
" T+ ~4 T1 _8 e$ C) j6 P
这就是为什么 UserApp 中仍然可以直接读取密钥的原因了。很明显,接下来我们需要将 SEKey 用 MPU 保护起来。但在这之前,我们得首先弄清楚,当程序跳转到 UserApp 后,Flash 和Ram 该如何设置 MPU 保护?( m3 M+ H6 D9 ~7 u

7 U0 |8 \' L; [) z6 H9 N在 UM2262 中, 有提到当程序跳转到 UserApp 后 flash 和 RAM 的状态:3 b& `$ y/ v, c" T7 `$ S
6 F% v; W# U; G
微信图片_20231211135933.jpg
" i1 w5 @4 I2 F/ K2 ^
图12.UserApp 运行时的 flash 和 RAM 状态
/ C# t* W5 Q9 H- P( k6 R$ x

) E) ~' |& U& [1 n) {# n& e从上图可以看出,原本 Secure User Memory 保护的区域,我们得使用 MPU 来替代实现相应功能,包含 SBSFU 整个代码和 Slot#1 内的 header 信息。这也就是在代码跳转到 UserApp之前需要做的事情。而黄色对应的 SRAM 区别已经擦除,当程序跳转到 UserApp 后其实已经没必要再保护。
8 _! q: o) g- j) c3 J# u( ?
: N0 K* w1 X: q. T0 n5 z$ M4 d4 P
于是在跳转到 UserApp 的内存函数中配置 MPU:2 v0 n6 s1 k3 D' Z% @8 j# q

. S! W+ E/ U0 Y+ Z
微信图片_20231211135929.jpg
7 w% K& ?' N! J" y/ U8 z( S2 q3 l4 V
微信图片_20231211135926.jpg   f! m: t1 G8 b6 j3 y
6 l$ R" I  x$ {  e- Q, ^
微信图片_20231211135923.jpg
. U" n7 \% A8 ?9 R6 n" Q6 Z6 V8 T0 k
注意这里是一个内存函数,它所调用的所有子函数也都是内存函数。在这个函数中我们将SBSFU 所在的 64K Flash,再加上 2K 的 Active Slot 的 header 信息保护起来。内存 RAM 我们并没有配置保护,因为跳转到 UserApp 后它就完全开放,且内容已经清空。 / {  B/ E' J7 S! \! s$ M- P

  d; x% D7 I; A  j1 S对应的, 我们在 UserApp 中增加对 Header 的测试函数 :* p6 ]/ n$ p" R. t% t# d

5 m# t( N7 g4 t. k; S- X
微信图片_20231211135920.jpg
! v+ I' K0 Y$ ~- l( M: W

4 D, A* t* h2 X# P5 x. _. K& S重新烧录程序,当程序运行后,选择 2 进行 protection 测试,然后再选择 2,测试访问SBSFU 所有的 64K 区域:
5 V3 }* S4 ]( f. d9 E# J! i7 v/ K5 l* i0 U+ v
2.jpg
7 s5 a" d* u3 U! |9 i
图13.测试 SBSFU 的 64K 代码区
- Q  S1 O, Y5 L. H  g. L1 j1 J

4 e. c. Y1 q+ P. i. q. k发现会一直卡住, 这说明 MPU 对整个 SBSFU 64K 区域的保护已经生效。同样的,选择’3’测试 header 所在区域:5 e" u! x- ]) T& T, R
; H  z# u: V$ U" o
微信图片_20231211135908.jpg
8 z, L" D1 p; Q1 G7 V- x' n' @" Z
图14.测试 Header 对应的 2K 区域
9 P' e- x% ^$ @4 ]

2 Q: Q4 p) I' F/ ]/ b发现程序读取 0x0801 0000 地址时会一直卡住,这说明 MPU 对 header 的保护也已经生效。然后再测试了下其它选项,包含下载新固件,还有其它默认的一些安全特性,基本都是OK 的。这说明整个程序基本已经 OK。 ; f0 {% I+ H" ]! H* A+ ~

. Z6 [6 f) F. }5 z: m最后再恢复之前注释掉的除 MPU 之后的保护。3 B, m0 y* A9 c6 |8 ~4 h# D

3 `; o- V4 L% u( L. o4 Z05后述
: d! m8 j! k1 p6 B+ c, c- s  N本文旨在通过一个相对容易的移植, 让读者对 SBSFU 的移植过程有一个大概了解以起到参考和示范作用。& a) t' L6 i6 k* q

3 z8 n7 a3 w9 i3 B- ?, G0 H. p如有侵权请联系删除
6 v1 Y" t( c4 ~转载自:STM32单片机" `5 K  e2 o3 X7 b' N
6 N4 e6 t& Y1 Y; C* U
) h1 F& @  q  y/ }0 l

' r# j) k# f3 l0 ~( f, |
/ w, l- Z$ a8 C5 e
赞 1 收藏 1 评论1 发布时间:2023-12-11 14:02

举报

1个回答
watershade 回答时间:2023-12-13 10:06:30

不明觉厉,SBSFU还真没有涉猎。看来很多东西不知道。

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版