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

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

[复制链接]
STMCU小助手 发布时间:2023-12-11 14:02
01前言
7 V2 z0 |' `  j9 u5 o" ?0 b客户使用 STM32G070RBT6 给海外用户开发产品,由于当地新需求,产品需要增加安全启动的功能。但是由于 X-Cube-SBSFU 包提供的示例中,只有基于 STM32G071 的示例。客户因此询问该怎么移植。本文将讲解这个移植过程。
: K& v$ Y; D5 }( L- w7 m9 g; J) G1 Z3 k! V/ h0 E

& a; ?, D  r; @+ L, B02基于STM32G070和STM32G071的SBSFU 实现差异! \2 V, y( _% ~
在正式讲解之前,我们首先来看一看 STM32G070 和 STM32G071 的 SBSFU 实现差异。
- Y! O6 M5 s( B# L8 @: z+ y0 Q0 p- i; @, p8 o2 r( p  @
STM32G070 是一个 value line 产品,首先,我们要意识到,有一些安全特性,相比于STM32G071,它是没有的,比如:PCROP,BOOT_LOCK 和 Secure User Memory。那么,缺少了这些安全特性的 STM32G070,是否还能实现安全启动的功能呢 ? 答案是肯定的。我们先来看 PCROP,BOOT_LOCK,以及 Secure User Memory 在 STM32G071 上的 SBSFU 实现中所扮演的角色是什么?; l  c; ~# a1 v2 k
1 }9 L( M/ O1 ~
微信图片_20231211140158.jpg
8 c" G* G6 {. c6 A
- H" P, K7 M5 b9 J3 R  J
图1.STM32G0 的 SBSFU 安全实现

, n5 W  R4 G  \) Z
/ t1 ]0 K- a( D
如上图,在 STM32G071 中,在安全启动的实现中,BOOT_LOCK 用来参与实现唯一启动入口,Secure User Memory 则用来参与实现信任根。PCROP 在安全固件升级实现中用来与MPU 配合实现密钥的安全存储,同时在安全升级过程中涉及到一些密钥的加解密操作,借助于Secure User Memory 和 MPU 的功能, 将 App 与 SBSFU 本身实现完美隔离。
! J, X$ V- {: e3 x% K/ w$ q
5 o9 U# O4 i/ e) ]7 ^( M
微信图片_20231211140155.jpg

+ k9 Y( q+ ?, l  q4 b
图2.STM32G0 内存安全映射(运行 SBSFU 时)
0 K1 y7 d  `3 M3 d) X

( |; C2 \" ?- v) B回到当前问题,一旦 BOOT_LOCK,PCROP,以及 Secure User Memory 缺少的情况下,这些功能还能实现吗? 4 u, q* A+ ^9 p" E' N2 p5 \
, J+ z5 i4 \5 t4 o
我们再来看下对于安全启动而言, 它需要实现哪些基本功能?
( E5 K4 z# s3 Q5 o/ m1> 不可更改不可绕过的一段启动代码
% v  G8 _& q" c% R2> 每次复位必先执行安全启动代码
. s0 p4 m1 s* V, i( L$ F# _3> 验证系统配置的完整性
. k$ C; S8 S( z$ m& o% `0 f) s    • 时钟配置" m' A+ G) d2 B# n/ N/ S
    • 寄存器配置; M1 H" U4 F6 o/ [! ~5 Y1 `
    • 存储器保护设置, ….
& `. h3 |) Y/ D4> 启动信任根服务! c" ?; {, b/ s. y
    • 通过密码学算法与密钥,校验 App 的完整性与合法性(来源可信,未经篡改) 3 J' w; i' r' S9 E+ U
0 E( t1 N# }# x( S
这里需要注意地是,上面提到的某一项安全属性也只是参与实现某一项功能,比如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 功能的。0 I3 r' ]* f& S/ s+ ~. h' T
$ e: e) l! F  g( R% S, u
微信图片_20231211140151.jpg
3 ~* W6 l9 S$ ]7 k# S5 h0 o
图3.STM32F4 的 SBSFU 安全实现
6 u. }; i3 b& n2 }
* g# L2 _: L% O" P: |  A( X
如上图所示,在 STM32F4 中,借助于 RDPL2,WRP,MPU 就实现了 SBSFU 的全部功能。
, l3 c  Q- @' H1 G+ t! T. h
' T  q0 H" X  g9 n( S/ N
微信图片_20231211140148.jpg

4 j8 ~. L$ ^/ }7 @: k) W; }
图4.STM32F4 的 SBSFU 内存映射

- V9 V" _, a8 l- W! X7 ~4 O

0 I) [$ G0 P4 t( ?* A到这里,我们完全可以确信,在缺少了 BOOT_LOCK,PCROP 和 Secure User Memory这些安全特性之后,STM32G070 完全可以按照 STM32F4 实现 SBSFU 的方式来进行!
$ Y( E' J9 G# V) m, n  u4 J6 f
  Y0 t) M7 o! g, [7 i在确立了大方向后, 我们接下来看具体如何实现。  P8 j8 \9 [# C+ I1 K, S5 z
  B( ~( E9 }% a3 k2 j  e
03开始移植
" q$ c  F6 i6 J9 {第一步 : 确保原始工程运行正常
+ u, L6 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 进去。目的是首先确认原始工程一切运行正常。接下来就开始修改了。
+ A* y0 ~2 ^- W5 @( ?
+ j: \9 d3 ]9 `/ h  V第二步 : 将与 BOOT_LOCK, PCROP, Secure User Memory 相关的宏全部关闭, t7 e' Q- F  M! l
打开 SBSFU 工程的 app_sfu.h 头文件,找到并关闭下面三个宏 :
. n+ f& e8 ^6 T& D- t9 f: Z  Q8 Q% s
微信图片_20231211140145.jpg
, ]! A/ z" g* p/ z/ f" Z" \

5 L# i/ c: _3 C  A重新依次编译 SBCoreBin,SBSFU,UserApp 三个工程,并重新测试通过。 1 H& r- M  H$ ?+ {+ d+ h# _/ z+ |
' s# U6 f, @% v5 W
至此, NUCLEO-G071RB 板上运行的是移除了 BOOT_LOCK, PCROP,Secure User Memory 三个安全特性后的 SBSFU 程序,这个原理上与 STM32G070 上原则上是一致的。接下来就是要移植到 NUCLEO-G070RB 板上了,剩下的就只有 STM32G070 与 STM32G071 的非安全特性方面的差异了。
7 z, W3 F! M: d
' Z8 d/ Z' q* m2 u6 F6 B/ D第三步 : 移植到 STM32G070RB
+ ~) l/ V: x% s首先得准备下一块 NUCLEO-G070RB 板。接着将三个工程 SBCoreBin,SBSFU,UserApp 的 device 修改成目标 MCU STM32G070RB,然后将三个工程的 C++预定义宏STM32G071xx 修改成 STM32G070xx。 4 _3 i; N0 h/ }3 d7 h& |- |8 z. D+ R

0 s* p, |! y# l: k% u以 Keil 为例 :
8 |( W9 b% Q& P3 F# f& R
微信图片_20231211140142.jpg

  L; A* [( z- k& i
图5.device 选择 STM32G070RBTx

$ d9 D3 t& o$ d( @1 B+ f0 y) n

  H9 W, a7 ]) i, `) i
微信图片_20231211140139.jpg

9 o! ?0 B- F) U" a) ~3 O
图6.C++编译宏修改

$ I3 d2 I) R1 P' H

3 G  H7 B, F8 T4 [+ }+ GSTM32CubeIDE 工程的 device 配置比较难修改,因为它原本是灰色的,不允许修改。但我们使用 UE 打开.cproject 一样可以强制修改 :
; C8 c& P+ V- j' `; F4 ?% @( ?5 y( E' N$ _. s3 G
打开对应的.cproject 文件,搜索关键字 G071,将以下几处替换成 G070(修改两处) :
0 O, ]0 Q) E6 [" u. n3 V6 v0 r3 L
微信图片_20231211140136.jpg
. v$ ]: V, I7 J+ a, q5 a
图7.STM32CubeIDE 下的 device 修改
7 k" }5 E8 {# P
0 B) T: G; j1 {+ ^2 B1 T# F" U* {
修改完后,打开 STM32CubeIDE 工程,在其 MCU 和 Board 的配置也会有相应的变化:0 [' W7 B0 M6 D) N1 V/ e- p3 u0 Z
9 X1 d7 I, ]1 `2 Z6 K( Q7 X/ _
微信图片_20231211140132.jpg

! F2 A& m  \0 E, i! v2 @
图8.STM32CubeIDE 的 MCU 配置

6 P; q- x4 V% k  E8 H
+ _6 r: e( M# l0 P3 n! Q
由此可见,在 STM32CubeIDE 工程的 MCU 配置也可以做相应的修改了。这是一个小技巧。
9 u1 n7 ]4 |" H5 C0 e7 v
7 ?% ^2 \4 a" m! h$ o+ M% i至此,三个工程的工程配置都做完了相应修改。接下来的就是代码方面的修改了。' K9 n8 r( Y1 [# O# h5 G

6 f4 z& g6 r2 @, Q首先 STM32G070 的时钟树是没有 PLLQ 输出的,因此,在 SBSFU 和 UserApp 这两个工程内找到 SystemClock_Config()函数,注释掉 PLLQ 的设置,如下所示 :
. K$ |! ~' I2 V4 z8 z1 r. V' x$ {8 ?0 ~: t
微信图片_20231211140129.jpg ; m8 j7 l1 `, F' ]5 R7 l
0 E! ^/ R9 g/ t, i
原先 STM32G071 的工程中的打印信息是通过 LPUART1 对应的 PA2,PA3 打印的,换成NUCLEO-G070RB 板后,其引脚虽仍然是 PA2,PA3 引脚用来串口打印,但是 STM32G070中是没有 LPUART1 这个外设的,需要换成 USART2,因此,其对应的代码修改如下 :
" T% \9 C1 m  @  T, T0 a! ?

( L" [; z0 s/ E: L0 q' B在 SBSFU 工程中, 打开 sfu_low_level.h 头文件 , 和 UserApp 工程的 com.h 头文件中:
4 `3 a9 E$ ~) ^. Z
, K& \2 ]! a* h+ x8 }2 S
微信图片_20231211140125.jpg 6 B/ ?' n0 H! P% F- N
微信图片_20231211140121.jpg ' O; u( i' ?, ?" k! \5 G2 F

/ ~; @5 q. s( `! b5 F如上红色部分即为修改处。
, ~6 t9 f( |( ?4 d" d! e: L% t+ h1 {: G* v
至此,代码部分全部修改完成。重新按顺序依次编译 SBCoreBin,SBSFU,UserApp 三个工程,将 SBSFU 工程首先烧录到 NUCLEO-G070RB 板,然后通过串口终端,按提示,用 YModern 协议将 UserApp 对应的.sfu 文件烧录进去。整个流程都可以正常运行的。这说明软件框架基本已经 OK。接下来运行下 APP 中各种安全测试。
; q0 J" c- x, j$ Z/ e$ [8 K
/ I; w% |$ P/ f$ ?
* }/ @0 x: q* _2 J- _
04测试安全保护特性& ], o; m' R8 P/ a: E
当程序跳入到 APP 后,显示如下界面
, G+ J/ E% ]( G" ^
& m# y6 q) x( I+ u
微信图片_20231211140118.jpg
3 a  n0 ]. X  P3 j! v2 X
图9.测试主界面
$ _5 K4 `1 J8 V( U* X! h, l* X
: R  \, @/ d5 B9 U' }

) N8 r7 j/ t& p% e) K6 }9 |2 p0 p
当选择 2 Test Protection :Secure User Memory 时,结果会出错 :
- S3 _7 w; v5 k3 W/ O" p- r
  t: V  f" d8 v( [5 k, K
微信图片_20231211140114.jpg

8 \4 M6 C& A8 l& B8 X4 O1 ]: p7 f
图10.测试保护

1 i* C7 k+ g3 {* e! ?
/ `+ Y; b" s* L# c: G' V! a
很明显,这里需要修改下,因为 STM32G070 是没有 Secure User Memory 的。查看其对应代码:+ @* Y" G4 T- b% l# q

9 ~) j! B3 S, x' u2 e
微信图片_20231211140111.jpg 4 _; m( M, i, Y% k! H4 U) ?; X
微信图片_20231211140108.jpg & n; ~6 f2 N) I/ b

9 R. T$ N# H6 o* v  l$ v& O原来 UserApp 是测试直接读取保存在 SECoreBin 内的密钥数据, 测试是否能读出。结果发现是可以的,因此,保护效果是出问题了。
( ^, ]! }8 {9 \6 P9 j
& U: _. s6 \% V
首先我们修改下此函数,由于 STM32G070 中 Secure User Memory 是不存在的, 此函数叫 TEST_PROTECTIONS_RunSecUserMem_CODE()已经不再合适, 依照 STM32F4 的SBSFU 实现,将此函数换成 TEST_PROTECTIONS_RunSE_CODE()函数:& y; F2 l# S% Q7 L, j

  v- X8 n$ D2 R
微信图片_20231211140041.jpg & U. n( N1 y9 \& W: W

1 L/ {0 z: _$ J- a8 @同样的尝试读取密钥:( p$ ^+ b) r9 n" u. ^, O5 H3 _
* y9 r3 G$ _& I. C2 W
微信图片_20231211140036.jpg
- w( M$ w4 x* `3 S  g7 \: R
图11.UserApp 尝试读取密钥

/ h) B% v5 `- m1 z. n+ ^7 j
7 I' G( e+ G+ |
测试结果可想而知, 肯定是可以读取的。于是得查看下为什么可以。
5 U/ J( o5 d! p5 J5 W& |8 Y
& r8 T; S+ `# v" N仔细查看图 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 p0 K. @- @" n1 M) N0 u9 n6 b$ S: U4 u/ H
为了方便调试,我们首先得将除 MPU 以外的所有保护通通关闭,只剩下 MPU 保护。于是在 SBSFU 工程中,在 app_sfu.h 头文件中,将以下宏通通注释掉:2 {* n0 o9 Z$ f/ x0 x- k- o

. p$ m  u: M) g  j- ^8 ], l2 Z
微信图片_20231211135943.jpg
2 e! a5 v, z9 E2 D6 O6 R
微信图片_20231211135940.jpg 0 a# t* J& b8 }' {0 Z. @  g
. R7 k1 b: s- s
然后开始调试。在调试过程中,发现程序在从 SBSFU 跳转到 UserApp 之前,在代码中特意将 MPU 关闭: # x% u9 v  @. P2 d
0 X' @. ^* O$ i5 D. ^3 n; c
如在 sfu_low_level_security.c 源文件中的内存函数 SFU_LL_SECU_ActivateSecUser()中有这么一行代码:$ U  {/ D5 a* Q  x! ^

. a- I* _1 V9 t* ?  ~) Z* g/ F
微信图片_20231211135937.jpg # a( o( A6 I' J- o
; J. P! L8 T4 z6 w; u% w/ I
这就是为什么 UserApp 中仍然可以直接读取密钥的原因了。很明显,接下来我们需要将 SEKey 用 MPU 保护起来。但在这之前,我们得首先弄清楚,当程序跳转到 UserApp 后,Flash 和Ram 该如何设置 MPU 保护?
- C' L7 h: V9 m, Y% ^( k$ l  R+ B$ K9 c" k; [1 _
在 UM2262 中, 有提到当程序跳转到 UserApp 后 flash 和 RAM 的状态:8 ^' `5 h4 M1 ^: {' f4 n; G$ ]
& y4 m3 m1 T1 n8 Q. ~. I
微信图片_20231211135933.jpg
9 ~" n8 Y) E' z# O2 i5 g) p
图12.UserApp 运行时的 flash 和 RAM 状态
! j  b$ U3 M# `, c% U' U  R; H

0 T& j+ x* M1 E) K  J从上图可以看出,原本 Secure User Memory 保护的区域,我们得使用 MPU 来替代实现相应功能,包含 SBSFU 整个代码和 Slot#1 内的 header 信息。这也就是在代码跳转到 UserApp之前需要做的事情。而黄色对应的 SRAM 区别已经擦除,当程序跳转到 UserApp 后其实已经没必要再保护。
- t5 m9 @4 o# a+ `5 a) I0 a

0 e5 q0 W7 u) c2 @6 P- y& X* d于是在跳转到 UserApp 的内存函数中配置 MPU:+ i/ Q1 ]( }* W6 k, Q- z5 S5 ]  R3 L
& ]' K) F. Y% E  U. A
微信图片_20231211135929.jpg
& Z, }5 [7 n* m4 ?0 d* E, a/ i8 a
微信图片_20231211135926.jpg
% g4 P8 Q. @. ^; \  n, f: _% c. _! B- X8 g* f
微信图片_20231211135923.jpg
, Y8 [: t6 o) i' ^
. F4 Z2 e7 @: _% H3 l, B" ~8 K( p) A注意这里是一个内存函数,它所调用的所有子函数也都是内存函数。在这个函数中我们将SBSFU 所在的 64K Flash,再加上 2K 的 Active Slot 的 header 信息保护起来。内存 RAM 我们并没有配置保护,因为跳转到 UserApp 后它就完全开放,且内容已经清空。
+ ^- {* l, |+ }9 b, V3 t% h5 _: R) o# T& K1 z1 X3 z8 U
对应的, 我们在 UserApp 中增加对 Header 的测试函数 :
- A- P# h* c1 V8 n8 L0 |+ ~! p( W8 X# B' C: S; Q( c& Y
微信图片_20231211135920.jpg 1 C# [' g6 a8 S6 h2 r% ^

* n" o$ d1 _7 i! H1 f1 `/ r重新烧录程序,当程序运行后,选择 2 进行 protection 测试,然后再选择 2,测试访问SBSFU 所有的 64K 区域:
1 F: |+ k, Q) H5 J) T1 Z8 T( j. c6 Q7 m9 X& k
2.jpg

5 G0 u2 p, \1 M8 }
图13.测试 SBSFU 的 64K 代码区
: t/ h3 U9 j: b, {6 W3 `5 T

9 R5 ?( K! W- h  B$ A8 a. ~1 O3 @发现会一直卡住, 这说明 MPU 对整个 SBSFU 64K 区域的保护已经生效。同样的,选择’3’测试 header 所在区域:
; }) g4 M: U2 {8 B. W- m2 Q2 G. w0 e) R& Q
微信图片_20231211135908.jpg
( Z" I1 N9 V% ^- R9 B7 D' w9 N9 R) c
图14.测试 Header 对应的 2K 区域
6 H$ c& T6 T2 W/ Z3 ~& {1 c

. _- F* g" o/ c/ l# O8 H. o发现程序读取 0x0801 0000 地址时会一直卡住,这说明 MPU 对 header 的保护也已经生效。然后再测试了下其它选项,包含下载新固件,还有其它默认的一些安全特性,基本都是OK 的。这说明整个程序基本已经 OK。 , [6 [5 s( m. I) S# K5 e

2 e  Y' L: d9 n1 k4 g' f最后再恢复之前注释掉的除 MPU 之后的保护。7 D" Z/ ]9 k% ], i
' m2 P$ m7 @& p0 @4 A  W
05后述
4 V8 r! {8 r4 |- ]7 `, q本文旨在通过一个相对容易的移植, 让读者对 SBSFU 的移植过程有一个大概了解以起到参考和示范作用。4 c: v+ p8 v) M/ A
. g! C; \' k1 g9 P
如有侵权请联系删除' Y( {$ [# T) e  o% ?% ?
转载自:STM32单片机
/ y9 S: B+ F2 r; X# Y2 g3 o
1 O5 b, X$ K* O5 _
, n$ s! q0 d8 b- X* D" s  ~4 t+ g. `9 I: H9 w# |
; t0 ~3 S3 a: B. P$ ^5 b
1 收藏 1 评论1 发布时间:2023-12-11 14:02

举报

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

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

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