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

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

[复制链接]
STMCU小助手 发布时间:2023-12-11 14:02
01前言
" z# `' }' ^. e) P. X5 Q' e客户使用 STM32G070RBT6 给海外用户开发产品,由于当地新需求,产品需要增加安全启动的功能。但是由于 X-Cube-SBSFU 包提供的示例中,只有基于 STM32G071 的示例。客户因此询问该怎么移植。本文将讲解这个移植过程。
* O0 R; c# J, n) p' ^4 J
, i% e; Q- Z7 H. V# R* A

5 ^- l! {' S0 l, `6 ?02基于STM32G070和STM32G071的SBSFU 实现差异
: q* x+ }( L% i' \) J* v在正式讲解之前,我们首先来看一看 STM32G070 和 STM32G071 的 SBSFU 实现差异。 . x) \  b' f# l4 h
6 ?/ W% G) {: B5 X; p, U
STM32G070 是一个 value line 产品,首先,我们要意识到,有一些安全特性,相比于STM32G071,它是没有的,比如:PCROP,BOOT_LOCK 和 Secure User Memory。那么,缺少了这些安全特性的 STM32G070,是否还能实现安全启动的功能呢 ? 答案是肯定的。我们先来看 PCROP,BOOT_LOCK,以及 Secure User Memory 在 STM32G071 上的 SBSFU 实现中所扮演的角色是什么?- ]' S/ u- u# Z. \. \2 K  e
7 |: k( p0 r* w! ~
微信图片_20231211140158.jpg

4 q; a( n7 q& U; x4 I$ H( }
$ _% O  O9 A8 g1 B, O
图1.STM32G0 的 SBSFU 安全实现

0 a4 H8 V2 U/ U1 S7 W. o: F( T* I

& z' q5 y) Y6 |, O1 f: Z如上图,在 STM32G071 中,在安全启动的实现中,BOOT_LOCK 用来参与实现唯一启动入口,Secure User Memory 则用来参与实现信任根。PCROP 在安全固件升级实现中用来与MPU 配合实现密钥的安全存储,同时在安全升级过程中涉及到一些密钥的加解密操作,借助于Secure User Memory 和 MPU 的功能, 将 App 与 SBSFU 本身实现完美隔离。
9 S9 J* U/ e  f! U/ F
3 \/ c+ N5 |3 M' K+ {* k- S: {
微信图片_20231211140155.jpg
" Z3 f2 X4 s: y
图2.STM32G0 内存安全映射(运行 SBSFU 时)

* W/ ^: z! f; S- z* A; v0 O4 F

; w0 Q& R* t3 d回到当前问题,一旦 BOOT_LOCK,PCROP,以及 Secure User Memory 缺少的情况下,这些功能还能实现吗?
! M& o4 Y, m5 Q5 K$ `! q, r' K$ p6 f! ~$ ]. E
我们再来看下对于安全启动而言, 它需要实现哪些基本功能?
4 ?: V9 l. h( Q; {0 V  e7 m# |1> 不可更改不可绕过的一段启动代码8 ^. C  s" M1 @$ V  H
2> 每次复位必先执行安全启动代码
& g3 ]* y1 S; U3> 验证系统配置的完整性
$ I+ D7 ?  e" U+ J    • 时钟配置5 B' S/ {- v& m! n  c* X
    • 寄存器配置
7 E- }: u1 Z( l) p3 t  y    • 存储器保护设置, ….
, R" c7 a) @. k4> 启动信任根服务
+ F" Q% S4 p+ C4 D- b  K0 L    • 通过密码学算法与密钥,校验 App 的完整性与合法性(来源可信,未经篡改) ; S. _; L4 |7 H4 M8 L! E

4 ?- h; S$ a, E4 C( X0 l1 L8 b6 a这里需要注意地是,上面提到的某一项安全属性也只是参与实现某一项功能,比如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 功能的。* R' v& ?( H: I3 X5 f

2 A+ a2 b; k; A3 I9 }3 i
微信图片_20231211140151.jpg

3 S% c* a2 S9 h) J* Y
图3.STM32F4 的 SBSFU 安全实现

; L5 n. |9 y' M( [. s) X# `: v
* D! W& d/ b  R3 G4 E
如上图所示,在 STM32F4 中,借助于 RDPL2,WRP,MPU 就实现了 SBSFU 的全部功能。
% v- [, I6 Y% X% F4 `. Y
. G' G. I( a- [- K) M+ _- K
微信图片_20231211140148.jpg

7 b" @$ t4 T+ `/ X4 c. S, a
图4.STM32F4 的 SBSFU 内存映射

9 v# ?) T6 u5 ]" |! R; [

3 n7 y! z3 e! a: B* b, y5 C+ L到这里,我们完全可以确信,在缺少了 BOOT_LOCK,PCROP 和 Secure User Memory这些安全特性之后,STM32G070 完全可以按照 STM32F4 实现 SBSFU 的方式来进行! 6 s/ ], @8 a7 }

! }  i- n6 E3 N$ r' Q/ V  y在确立了大方向后, 我们接下来看具体如何实现。! x# \2 {$ y. X: c( U; O0 y& ~
9 |7 o" x/ K9 D
03开始移植
9 o; `2 B7 @0 v第一步 : 确保原始工程运行正常
! s" E+ {$ l) \3 Q4 e从 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 进去。目的是首先确认原始工程一切运行正常。接下来就开始修改了。 $ S. E. G3 Q3 z8 _
5 Y) ?4 M6 K7 M$ y
第二步 : 将与 BOOT_LOCK, PCROP, Secure User Memory 相关的宏全部关闭" p0 ]2 r# `0 _% g. g/ `2 [
打开 SBSFU 工程的 app_sfu.h 头文件,找到并关闭下面三个宏 :4 B( J5 ]0 m; J( Y4 ~
0 K, @1 ~2 s. R! R
微信图片_20231211140145.jpg
# |6 z4 {" t1 u8 Q" P3 a

: w8 ~2 w. ?6 i6 N5 @重新依次编译 SBCoreBin,SBSFU,UserApp 三个工程,并重新测试通过。
" R1 S0 ]/ k: c8 x$ F4 `: F' m- L) U- N( r, O& H
至此, NUCLEO-G071RB 板上运行的是移除了 BOOT_LOCK, PCROP,Secure User Memory 三个安全特性后的 SBSFU 程序,这个原理上与 STM32G070 上原则上是一致的。接下来就是要移植到 NUCLEO-G070RB 板上了,剩下的就只有 STM32G070 与 STM32G071 的非安全特性方面的差异了。 4 d3 g  a) U: \, h! h

6 U" a5 i; I3 ]; ~* o1 {7 H% \第三步 : 移植到 STM32G070RB
3 N' w! {. v" C7 P% p  N首先得准备下一块 NUCLEO-G070RB 板。接着将三个工程 SBCoreBin,SBSFU,UserApp 的 device 修改成目标 MCU STM32G070RB,然后将三个工程的 C++预定义宏STM32G071xx 修改成 STM32G070xx。 3 o! f& S; A+ A8 h. a$ o, Q2 `
8 i) D6 Q1 g& {; Y! E2 i8 C& O
以 Keil 为例 :" ?/ a/ t2 l/ v& D$ M' l
微信图片_20231211140142.jpg

- j; p+ L2 [4 _; H% g
图5.device 选择 STM32G070RBTx
  B, Y# }3 B( n" o

8 [/ k$ O1 M* T0 a! \$ r7 }9 D
微信图片_20231211140139.jpg

0 i+ E6 r2 Z' \
图6.C++编译宏修改

: G# d! m) K' C+ u  D9 T

: B6 C% x  m2 `# ?' YSTM32CubeIDE 工程的 device 配置比较难修改,因为它原本是灰色的,不允许修改。但我们使用 UE 打开.cproject 一样可以强制修改 :
. ~/ j$ ]# ~5 p& E: d5 o, b1 d# V' \! C+ ^4 g8 N) [5 e( s
打开对应的.cproject 文件,搜索关键字 G071,将以下几处替换成 G070(修改两处) :+ U/ V4 P' y0 Q2 T( w  ^+ R

6 f7 Z' X/ `, Q
微信图片_20231211140136.jpg

) N8 d+ }: A5 h2 S) W& I/ G
图7.STM32CubeIDE 下的 device 修改

3 F+ G% O8 Z; D9 F

* V5 W! l4 f+ b8 J& B修改完后,打开 STM32CubeIDE 工程,在其 MCU 和 Board 的配置也会有相应的变化:  ~3 ~) \7 @4 u: A, X  b5 \

: C$ Y! _( N+ C! g, {2 C/ Q
微信图片_20231211140132.jpg

  I" F# x# \0 \( H/ o: R  E
图8.STM32CubeIDE 的 MCU 配置

# I5 ~- V! O2 y5 T' H8 c

( P/ N2 C( P, }- w5 J/ `由此可见,在 STM32CubeIDE 工程的 MCU 配置也可以做相应的修改了。这是一个小技巧。
& @# f* G0 D) N1 u  J6 \& T
2 J5 k( h. h9 V- Q' c/ P4 S. K% R至此,三个工程的工程配置都做完了相应修改。接下来的就是代码方面的修改了。
1 p2 y: Z9 a0 M! W

% X9 x1 g; q7 s& G首先 STM32G070 的时钟树是没有 PLLQ 输出的,因此,在 SBSFU 和 UserApp 这两个工程内找到 SystemClock_Config()函数,注释掉 PLLQ 的设置,如下所示 :3 l2 `# H  N. K- a
) H) U+ `+ @7 b4 _5 U9 u/ N* \% j
微信图片_20231211140129.jpg ) Q* I( H; E+ B1 D' `1 L
6 v+ r1 a6 z" t% ?
原先 STM32G071 的工程中的打印信息是通过 LPUART1 对应的 PA2,PA3 打印的,换成NUCLEO-G070RB 板后,其引脚虽仍然是 PA2,PA3 引脚用来串口打印,但是 STM32G070中是没有 LPUART1 这个外设的,需要换成 USART2,因此,其对应的代码修改如下 :5 [4 q% ]& s/ o4 H4 o$ @: C4 {
1 G. P0 {3 C" i0 M1 g' C" |. e3 K
在 SBSFU 工程中, 打开 sfu_low_level.h 头文件 , 和 UserApp 工程的 com.h 头文件中:
) E0 G$ i* d+ Z9 G' _1 g
( h+ Y( F; `) J- x, c' q
微信图片_20231211140125.jpg * @; V: \( }/ m7 f; Y* U$ i: J
微信图片_20231211140121.jpg
3 q: U! e. c6 f0 F% }- t; |$ r- C+ @+ d6 ^- ?9 U5 C
如上红色部分即为修改处。 / L" B4 {. x1 X4 H2 f

5 _2 B! C: u4 Y5 E1 S2 Q" f至此,代码部分全部修改完成。重新按顺序依次编译 SBCoreBin,SBSFU,UserApp 三个工程,将 SBSFU 工程首先烧录到 NUCLEO-G070RB 板,然后通过串口终端,按提示,用 YModern 协议将 UserApp 对应的.sfu 文件烧录进去。整个流程都可以正常运行的。这说明软件框架基本已经 OK。接下来运行下 APP 中各种安全测试。
* f% @% ~2 O5 ]* q; d) d& o
2 o5 K: ~. _7 ?( T9 q: H# r
! N  C: a- k; k, b9 u" F
04测试安全保护特性$ u, N  i2 ]9 a) i! ~/ m% u3 ^+ R
当程序跳入到 APP 后,显示如下界面
' H9 q6 {9 i) Y8 z' i+ r5 F- J- i0 r+ N' T' ^0 A
微信图片_20231211140118.jpg

+ l* B4 K, t2 ^$ _/ H/ [- o
图9.测试主界面

" o6 U, v( g+ x% z  c

& N) J) U% f; f5 J7 s* q7 @4 p7 G% }$ `: E7 H- P
当选择 2 Test Protection :Secure User Memory 时,结果会出错 :
7 u8 H5 f$ T, J" ^
6 g2 f! i9 b% Z2 w& {" C
微信图片_20231211140114.jpg
: x0 ~1 b5 _9 L" \: G( [' f2 K
图10.测试保护
3 I9 Z6 h1 S: d' \4 h
3 x4 X7 O! D- i% k, x
很明显,这里需要修改下,因为 STM32G070 是没有 Secure User Memory 的。查看其对应代码:
8 F" H( w9 {, k3 O2 W% C# U7 o! q& D$ F  q: J6 P( ^
微信图片_20231211140111.jpg : e  `6 E8 m" R: b* o
微信图片_20231211140108.jpg
  B+ W2 g6 q+ ?0 R6 S* R
5 H1 L. b* x& O. ~2 }原来 UserApp 是测试直接读取保存在 SECoreBin 内的密钥数据, 测试是否能读出。结果发现是可以的,因此,保护效果是出问题了。( _2 F2 v- Y# d
, U; c  K# [0 J4 U, }& B1 Z6 R
首先我们修改下此函数,由于 STM32G070 中 Secure User Memory 是不存在的, 此函数叫 TEST_PROTECTIONS_RunSecUserMem_CODE()已经不再合适, 依照 STM32F4 的SBSFU 实现,将此函数换成 TEST_PROTECTIONS_RunSE_CODE()函数:
$ J1 C% `' r, e) f0 P& ]' H
. }3 p) ]* Q2 ]3 I: d" \
微信图片_20231211140041.jpg 8 ?4 i5 [) m% B  q, w

( ?' [5 J/ b  X; r同样的尝试读取密钥:
7 }2 l, \# K9 i9 l4 r. D/ v: k2 G9 @8 d+ F! G" j
微信图片_20231211140036.jpg
6 q' R2 G+ ~/ R
图11.UserApp 尝试读取密钥

+ x( |3 u; ~- h4 a9 k0 W+ |

7 e/ T- V# g1 {: w" ]% a
测试结果可想而知, 肯定是可以读取的。于是得查看下为什么可以。
. {+ Q6 R* w, n9 s! _4 X/ R
7 X+ M" n1 L% b/ `* w仔细查看图 2 的 STM32G071 的 SBSFU 原来实现中,SE Key 是通过 PCROP+Secure User Memory 来保护的,现在换成 STM32G070,原本 Secure User Memory 用来作隔离机制, 现在换成了 MPU, 而原本保护 SE Key 的 PCROP 在 G070 中压根就不存在,于是 SE Key 只剩下 MPU 来保护,因此,我们接下来得着重分析 MPU 对 SE Key 的保护。 5 U3 ]. g; C, B; \( A
9 b( O3 ^# O+ s& W/ k
为了方便调试,我们首先得将除 MPU 以外的所有保护通通关闭,只剩下 MPU 保护。于是在 SBSFU 工程中,在 app_sfu.h 头文件中,将以下宏通通注释掉:
9 Z, M( n  n" p; F2 l9 h. `9 b* K
5 q2 ^% \' C; `+ e- j
微信图片_20231211135943.jpg
& n* k' L( M8 }" Y" x2 ~
微信图片_20231211135940.jpg
' j. T5 y( x0 x' L" U# p8 a" U' z' J
然后开始调试。在调试过程中,发现程序在从 SBSFU 跳转到 UserApp 之前,在代码中特意将 MPU 关闭:
& Z7 B6 ?2 n$ k3 a+ N4 c8 q9 u) u
" X0 |; _3 e$ X% ~% j如在 sfu_low_level_security.c 源文件中的内存函数 SFU_LL_SECU_ActivateSecUser()中有这么一行代码:4 Q) c) X& _% y- e
8 w3 o3 N2 I4 ^7 {! R8 d4 l
微信图片_20231211135937.jpg $ N  j) l$ p6 Z; }2 |# E( ?& J- ?& I1 f
8 |1 G. G6 S$ X1 ]$ X( E0 W, E" E
这就是为什么 UserApp 中仍然可以直接读取密钥的原因了。很明显,接下来我们需要将 SEKey 用 MPU 保护起来。但在这之前,我们得首先弄清楚,当程序跳转到 UserApp 后,Flash 和Ram 该如何设置 MPU 保护?! ]: k( k. G1 n/ j
; G1 B1 g; J' D  y# j7 e
在 UM2262 中, 有提到当程序跳转到 UserApp 后 flash 和 RAM 的状态:8 f8 W* o$ a4 C  X) C" b

+ I9 e  F7 l6 c1 W/ N2 l# z( a# g% K
微信图片_20231211135933.jpg
1 O. X' M/ d4 y, H5 t. R# k8 W$ q
图12.UserApp 运行时的 flash 和 RAM 状态
5 P0 W9 Z' ?# j4 u/ \+ l* [9 A

8 D: V# q+ D; N, D# P从上图可以看出,原本 Secure User Memory 保护的区域,我们得使用 MPU 来替代实现相应功能,包含 SBSFU 整个代码和 Slot#1 内的 header 信息。这也就是在代码跳转到 UserApp之前需要做的事情。而黄色对应的 SRAM 区别已经擦除,当程序跳转到 UserApp 后其实已经没必要再保护。, b; |& S$ q1 i' z8 y1 I
, @4 D& I% v( S% c  x
于是在跳转到 UserApp 的内存函数中配置 MPU:8 h3 f3 @1 E; w% U1 t: B! L+ F
. @  A& e5 l5 {/ \; V- |
微信图片_20231211135929.jpg , j5 U$ r4 d5 @; [! k" P
微信图片_20231211135926.jpg
! t, a" \7 p( s+ D, p* x; N( Z, ?& R! m
微信图片_20231211135923.jpg / u/ t, ~' c5 a1 o

# N! @5 j1 @/ f- p2 A注意这里是一个内存函数,它所调用的所有子函数也都是内存函数。在这个函数中我们将SBSFU 所在的 64K Flash,再加上 2K 的 Active Slot 的 header 信息保护起来。内存 RAM 我们并没有配置保护,因为跳转到 UserApp 后它就完全开放,且内容已经清空。
6 s2 @  b( d+ G& c4 d+ \  [% Z5 k
/ {9 t" C% l3 ^- m5 Y9 ]6 D% D对应的, 我们在 UserApp 中增加对 Header 的测试函数 :
  T  t4 @+ l) c% X' m( ]2 Z% ]4 s0 i( ^; y9 ~9 L  L6 Q) m2 j
微信图片_20231211135920.jpg - u) x* a, N# D+ ~* l
/ s6 D2 Z! c8 B& E) @! g
重新烧录程序,当程序运行后,选择 2 进行 protection 测试,然后再选择 2,测试访问SBSFU 所有的 64K 区域:. v& x0 H0 ~( ?6 q% d7 Z4 X

0 p+ W! Z! D( Q3 U) m( G2 {7 T
2.jpg
! m9 Y/ k% I) ~+ G
图13.测试 SBSFU 的 64K 代码区
$ \: e; n; q, x, K: A

2 T* T+ @5 w4 }" R- ]. u- j) E发现会一直卡住, 这说明 MPU 对整个 SBSFU 64K 区域的保护已经生效。同样的,选择’3’测试 header 所在区域:
0 B6 {. s: e  O9 u  n. `. c
: p% p+ B3 \6 V* t) j
微信图片_20231211135908.jpg
4 e6 |5 a( q! R: I( [5 [( _7 G
图14.测试 Header 对应的 2K 区域

* B: H5 U* _2 i% R9 u# W( b  |
0 [' X( E1 }/ l7 n6 L
发现程序读取 0x0801 0000 地址时会一直卡住,这说明 MPU 对 header 的保护也已经生效。然后再测试了下其它选项,包含下载新固件,还有其它默认的一些安全特性,基本都是OK 的。这说明整个程序基本已经 OK。
& |4 }' t; [# e
+ Y: t6 M0 f0 k; `最后再恢复之前注释掉的除 MPU 之后的保护。& d+ a0 P- d5 ]0 ?% m! ^( N# j) {

+ b- E' R* q9 |+ E' n- o05后述
4 t2 H# L2 g8 Q9 y! k5 m% V) x; S本文旨在通过一个相对容易的移植, 让读者对 SBSFU 的移植过程有一个大概了解以起到参考和示范作用。
' E" G/ h" i! E$ f) n1 ^8 e/ ]6 D6 t6 E9 G# M
如有侵权请联系删除! l" P. B! o8 R+ J
转载自:STM32单片机
8 B9 N6 r* b8 i* k0 u
  b- m- d* A8 X3 O/ C4 u1 m2 o& N! v! E4 `, i5 x. J
- |  P8 c- Q( T' O& [" x9 h) i
( l! K$ G  y9 }% }
1 收藏 1 评论1 发布时间:2023-12-11 14:02

举报

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

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

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版