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

信息安全专题 | 安全存储(2)STM32WB的用户密钥存储 (CKS)

[复制链接]
STMCU-管管 发布时间:2021-6-15 15:50
我们都知道STM32WB是双核多协议无线微控制器,即主频为64 MHz的 Arm®Cortex®‐M4内核(应用处理器)和主频为32 MHz的Arm®Cortex®‐M0+内核(网络处理器),支持Bluetooth™ 5和IEEE 802.15.4无线标准。双核的好处是可以优化对资源的安全使用,保证和RF协议栈相关处理的实时性,并可同时提供电源管理的灵活性。& o- l' j$ l8 X+ u  U+ \4 g2 Z

& ?8 L9 Q. a; y) D4 Y9 g/ y: @STM32WB的信息安全是以双核隔离为基础的。
" z/ a, t  @: {% w9 Z! e9 Y
0 u0 u& n6 v5 C1 C1 J- OSTM32WB双核架构和双核间的隔离机制
% j3 @8 C- R9 a( q, s( n6 H7 L' @
11.png

; K0 `2 u! F. J6 d# O9 Q$ C3 S7 E8 g7 `$ e9 d) [0 g  k( q+ k
! C8 Z6 i7 ?  w9 b( M+ I
6 l7 |9 }! @! M! z1 _, `4 ^
调试端口访问:6 ]+ _- k! i7 X4 I

. s* ?6 J. ]: A& U, J
# g; H1 `- H' `+ r# B7 s1 n
出厂的芯片缺省关闭CM0+一侧的调试端口访问,即使在RDP0的状态下也只能调试CM4内核。
+ q" I$ g$ I# m# ]6 c  |
8 w& l2 w+ s2 Q# I+ s, u8 DOption Byte:
4 [5 ~: P1 }3 `5 O- s6 f* m! w
3 t. j; W5 {- ?- m/ D, S5 n
! O$ @4 Q: d- X7 w$ s. A/ N2 [
OptionByte中包含双核隔离相关的安全设置,例如CM0+才能访问的Flash区间等等。这些OptionByte受到保护,无法随意被修改。缺省出厂芯片已经使能CM0+的保护,相关的一些OptionByte设置无法通过调试端口或CM4进行修改。
0 x1 |1 Q* U1 ?7 I, K
! J) g& L& }% {2 b片上Flash:
# T' U9 J* q! @) j+ [3 S( `4 g" S5 `, ?9 |6 P
8 K. k* G/ f* Z4 V1 u. w3 X
Flash的一部分只能由CM0+访问,CM4无法对该部分Flash进行读、写、擦。
3 ~3 l; N' R5 o$ S' g* W) H/ ^+ R" M) S" I5 M! S; M
片上SRAM:3 ]' f$ m0 \- |, u
5 P" o+ }5 [' Y) j! Z5 b7 r5 Q

) G* Z9 a4 d1 w7 d8 m7 uSRAM的一部分只能由CM0+访问,CM4无法对该部分SRAM进行读、写。0 L/ _9 C9 Z! w9 |
' m3 z2 j6 n9 l1 v9 c
CRYPTO硬件资源:如AES,TRNG,PKA. T% f0 @. b, A  u9 Z* _: W
0 `: Q4 {* U$ v0 P0 e) b, Q1 [

" T. V; s+ {; X8 \系统上电复位时,缺省CRYPTO相关的硬件CM4可以使用。CM0+内核可以通过修改SystemConfig相应的寄存器使得这些硬件资源只能由CM0+内核进行控制,也称为把这些硬件资源配置成Secure访问模式。其中当AES1被配置为Secure时,CM4内核无法访问密钥寄存器,但是依旧可以访问AES1的其他寄存器使用AES1硬件单元进行加解密操作。
( V! |$ {( \: G) G0 S' H$ ]
0 k4 p$ D! v. }6 b
CKS (Customer Key Storage)

/ o9 p. p; g* P$ `0 e
0 f) U+ j' j  cAES算法是应用程序中经常用到的一种保障数据机密性和完整性的方法,例如用于隐私数据的加密存储、加密通信等。其中,密钥作为最敏感的信息也需要受到保护。( M8 ~% D. N! j& E+ Z  |: ?+ h. b
6 Q, Y0 I) P2 D) |' n/ V' V

+ B% \5 l" r2 S' A# g8 L+ R# ySTM32WB的CKS功能提供在MCU上的密钥安全存储和安全使用方法 :3 c. ^0 L8 \# _$ F# x- q

$ m+ d2 g+ ~/ i( u$ h$ K

4 \+ L0 M7 c& a3 U( |! U; E1 ?3 [: H存储在片上安全Flash的密钥无法通过调试端口获取(即使在RDP0条件下)& D& @: v" l* m+ V+ {. \$ v
0 V, L, x  A9 Y$ U
' r+ [, h, U4 c' C9 c6 t# G* h/ |2 H
运行在CM4内核的应用程序代码也无法获得片上安全Flash中存储的密钥,避免软件漏洞带来的风险 5 d  J5 s# b6 r1 o

# M/ l; [4 q0 K. |

* ]# @$ O6 s# A- K应用程序代码依旧能够通过CKS和AES1硬件模块使用存储的密钥进行加解密操作 ; c; n5 A& Z8 v+ @1 n; U
; }/ ~5 O: ]+ L( B0 H/ ~, p
" O: m6 X. ?  ~" ~) r
CKS能够存储多组密钥,应用程序代码可以通过密钥索引来指定AES运算所使用的密钥
: P2 B' L0 D: k8 P
12.png

$ ^. R5 k9 d2 Q3 D1 C- \
用户密钥存储

$ X- ~. u& Q# ?- v+ M2 E5 x* p* ?' n2 q: {+ u% x

) e& E3 t/ W1 F5 @$ @用户密钥存储在"安全"Flash区域,用户代码和调试端口不可访问
- D, N: I  Q5 A" m6 L) b$ V7 U9 g2 F* r
# H4 C# o  M0 l% `
CKS最多可以存储100个用户应用密钥(用于AES运算)
1 [* H1 l# o( E5 P9 q) U' K- b, r' Y, T
6 k/ U9 J! Q+ k+ d, W" b  S  j
允许存储128位或者256位的AES密钥 7 J1 M; l) g5 v

; f# V1 y* D& g9 b& u9 R9 v对密钥的操作只能通过用户代码调用FUS接口完成   ~, F! f  z2 D  W! g- B9 u% q
3 d) F* V, `+ a' h) `
9 e+ I6 p* C* o7 X
把密钥写到“安全”Flash区域,需要安全的操作环境 " {3 d6 j  c- q
13.png

+ l( g+ i2 W. E5 q( D; X' q) r& ?6 {% m" d' v# ^& q' T
用户密钥的写入 (Key Provisioning)

: X( r: e. @3 l2 J9 t- R( G5 ]/ F

, |# }  l+ r& z. p
8 k$ @4 c5 u$ w
可以通过用户代码完成,也可以通过CubeProgrammer的GUI或者命令行完成 % ?2 P" v0 p! G
写入应用密钥的明文//simple key,需要安全的操作环境
0 _/ u- A! i* o$ S3 J+ [5 ^. e
% P: `7 u* M9 ~8 t& q  L( {! M

" g% L& s3 [7 X  q0 w# C% ^" H2 t写入应用密钥的密文//encrypted key,无需安全的操作环境
* S  a9 P( r$ f( m$ a- t8 b! b9 m5 d2 |7 H

5 G3 I5 d- C- _6 P. m基于AES-128 GCM
1 H- Y# J, R$ s: y9 ?2 Y
5 Q$ _6 T* N! E3 e3 n* F

/ {7 }& s, |! i* N+ D# X* W, u写入用于解密encrypted key的密钥的明文//master key,需要安全的操作环境 9 O; {; [' M  J7 S! U

& \! O/ l/ J+ F4 j9 O; |/ S该操作在手册中用“write”或“load”表示
9 S/ B$ s) O$ |* c( U
14.png
( u; M/ [; t' z' g
7 ~$ }' L$ {/ r" ^4 A* T

; h, z* h$ `* B
用户密钥的写入通过应用代码实现
/ W* ?! M0 N8 H9 m  m7 d: y

5 v- ^9 r2 R! r7 ~! q6 m5 u' t: \# j% y; G" P  j, r  p
参考例程:
% k5 z4 _* U: Z& L1 f% _STM32Cube_FW_WB_Vxxx\Projects\P-NUCLEO-WB55.Nucleo\Applications\CKS\
. X3 |6 j! R$ n7 h) {2 A0 Z9 d- d" \* E- m$ p
+ r, f  M* R8 l% p* d" Z6 N
给CKS_param赋值
5 x( z& z6 b& f2 |4 Z. M+ D) `
  1. typedef PACKED_STRUCT{
    1 }# t# d- K  h3 {; P
  2. uint8_t KeyType;
    % x) R$ s* C7 j- V
  3. uint8_t KeySize;# ~/ ^* l  Z, a
  4. uint8_t KeyData[32 + 12];
    $ L1 B8 C2 g  w. ]/ ^, J
  5. } SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t;
    # ]. A9 X- U5 C% [) `% m2 z
  6. SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t CKS_param;
    4 @( a, y9 a8 L' }7 [0 @8 o9 z/ e
  7. CKS_param.KeyType = …;  I! M9 H# h! z" L
  8. CKS_param.KeySize = …;3 \- y% F# w1 {& \$ b
  9. memcpy(CKS_param.KeyData, pKeySimple_128, 16)
复制代码

$ n2 A/ c0 e8 M调用FUS服务:SHCI_C2_FUS_StoreUsrKey
/ u; L& V5 F7 ^" |: ?8 h输入:CKS_param结构体
+ z1 g9 P6 H9 l" J$ q
' Z. d1 Z% S# d6 A
# M0 ]1 X6 R1 _4 Y9 @$ o
输出:芯片为该密钥分配的索引; Q' s' f: `7 h8 ]( S

, X2 n3 \( p6 T0 I- j2 w' F2 o

  1. - R+ G! h( ]5 i  `/ e
  2. SHCI_C2_FUS_StoreUsrKey (&CKS_param, &key_simple_128_idx );
复制代码
15.png

* B/ E# {, H. F1 z  Q& A0 C* K5 X7 m" F0 o4 U- J$ \

- |$ b$ m5 `) s, q7 _- `) r6 r! }0 l
用户密钥的写入使用STM32CubeProgrammer GUI实现

( E, p: f' S" z0 R! {+ p* {3 O7 j1 B9 v8 M0 y6 z

% k7 U5 _1 e. o2 R1 D! N5 [" `

  L* o2 G; c6 h9 s* A- _. r" m8 W" PSTM32CubeProgrammer 从2.4版本开始支持 8 z" y4 o- l0 U: G
芯片切换到系统 Bootloader 启动运行DFU,
5 i4 U& l1 Q  r  r. {: U3 V; d" _# d( Z2 t% S
3 A- C5 i4 t) b% ]
STM32CubeProgrammer 以USB方式连接芯片
' S9 ?! S+ x/ x6 n5 T
16.png

. k+ @0 z' v1 v5 l2 x. U; B步骤:选择KEY文件 ——> 指定KEY类型 ——> 写入KEY2 a/ p4 a! P( G& z& z4 H
17.png
" D9 f" j& p- o$ H: A7 @

7 y; _4 D4 t4 G4 `  A
& m; K2 N8 P* y( |
注意:GUI界面没有返回为该密钥分配的索引,需要用户自己记录
  E; I3 S+ A( Z3 V9 d
- m3 Y# f7 J4 L0 O
* ?& M6 C( v7 ]( h8 M& v
应用密钥的装载和使用

; F$ m/ _8 I) L) J. LLoad:AES1的密钥装载 8 g  Y  S% t7 H. L, ?5 N- R: t) H
SHCI_C2_FUS_LoadUsrKey (key_simple_128_idx)
- Z: g" I- K* L7 k# I该操作会把AES1密钥寄存器配置成Secure : t; f% T, h6 l/ B' B3 \# F& _
SAES1@SYSCFG_SIPCR
1 K& k' Z+ ^% ?  J4 v5 p只能由运行在CM0+上的FUS来配置
; c* C) ]5 F6 X5 @& h, r运行在CM4上的用户代码可以读取其状态 6 t! {6 A# @8 E7 h
安全状态和AES1时钟是否使能没有关系) Q4 N0 ~! {) s7 n& Z* s
18.png

) e8 }7 N& z7 x* z: [% K8 I6 f. r7 z9 B' W  Y3 u/ [
/ \/ X; H  [5 Y+ q, Q# v
使用步骤 6 S$ ?6 d( m8 U9 A1 k$ k

. k" V) o( V8 x
( m6 c: o$ G6 B8 q- Z. P, ^" f
Step1:AES1模块初始化 " q1 u5 \7 d) @2 Y
5 H. ?8 [# d5 y0 k4 ?& r/ y

! P1 j6 E  t/ E$ h初始化结构体的pKey,设置为空指针即可 6 i9 S! \  q: [; J
! z  p2 A0 _( A" F& ^4 v
0 H) Y0 l5 a9 \0 e! S& D. C% v- Q
使能AES1时钟
4 ^$ f5 }) c  r1 y+ S9 b* A- E

1 f% e" a& ?5 _- @Step2:密钥装载 . D# b! Q* B2 |7 @

1 \9 C( x+ |9 k5 R' M
! x% U2 Q+ H  T4 j* u- }
要在AES1模块disable1的时候 (EN=0) 7 \4 z, S) |  X9 o2 r0 N& D% Y
* g1 E3 i" o" a( M2 ~# a( @5 A
& N) W  X- T, C4 g
Step3:使用AES1做加解密8 _7 d( t9 d- d+ |; x: ]5 P
( K) ]% e/ T: c$ n. q% ]
  1. hcryp1.Init.DataType = CRYP_DATATYPE_8B;
    1 `$ _% h! d3 k3 J, H  D
  2. hcryp1.Init.KeySize = CRYP_KEYSIZE_128B;
    . j8 j) c0 Q/ Q( h3 m6 F8 J. H
  3. hcryp1.Init.Algorithm = CRYP_AES_CBC;* k6 n  S& C- G
  4. /* Key will be provided by CKS service */
    * `  h* Q$ W% t6 u8 |
  5. hcryp1.Init.pKey = NULL;
    8 ]8 z( R( a5 I' C' _" e9 J4 H6 \
  6. hcryp1.Init.pInitVect = AESIV;
    / q+ \1 [& e5 M. b4 P: g0 o
  7. HAL_CRYP_Init (&hcryp1);
    / R' N7 p& _' k+ o$ u8 D0 M( O
  8. SHCI_C2_FUS_LoadUsrKey (key_simple_128_idx);. Q! [0 Q( I1 {) `. A9 k& p  A
  9. HAL_CRYP_Encrypt(&hcryp1, Plaintext, size, EncryptedBuf, timeout)
复制代码
应用密钥的使用

( J! A0 ~  B: m
2 V! N$ n: ]' b6 L2 ULock:
+ _% |  D/ b0 q) g5 p, D
5 ^+ b& k4 f* D0 o
$ s3 W2 P) d& l; a4 b( e
·SHCI_C2_FUS_LockUsrKey (key_simple_128_idx)
& l; ~9 ]5 E, I& c. b4 u, y·对某个key lock之后,将无法再对该key进行 Load操作,再次Load该Key时FUS API返回 错误代码0xFF;但是不影响已经在AES1密 钥寄存器中的key
& q; P* a+ n. N% J' g. b6 h·对该key load的禁止操作,会一直生效直到 下次系统复位: `" R& ^# A. ^/ q! J# x& F

* v: P( E' C% G  K注意事项:关于后续更新 2 \6 m0 }# r8 a) k& l. _  {* }# {

' D% N3 x! t7 v/ j6 {
7 v6 |$ D5 J4 h; k$ E
·为了避免有效密钥一直存在于AES1密钥寄存 器中,建议使用完毕后Load一个dummy key 或者disable AES1
" s: h$ K5 V( b) G0 Z7 X·后续FUS版本(从 STM32CUbeWB1.11开始)会增加API:Unload/ c. j  X7 p( A, g8 z5 z& T: f
·早期出厂芯片预装的FUS版本较老,在FUS 升级的时候,通过CSK存储在芯片里的用户 key会被擦除 ' X+ _4 c+ s" B. B% l* E2 ]
·从FUS1.1.1.1或者FUS1.2.0开始,再做FUS升 级,不会影响到已经存在的用户key 应用密钥的使用& F  h) m$ k* r/ Z: z- y+ p) T7 \

; D3 ?2 c3 S: x2 o

# l& z5 h: G7 Q- W; a, q0 M
小结

9 g, f$ ]$ Q+ E; a* Q2 @
19.png
8 X& l3 B8 I- _
. A  ?" q( G' _+ i6 `3 l4 @
' \! ?) ^" W9 Z3 u! h" f- i) A
使用CKS对AES密钥进行保护,与传统的直接将AES密钥存储在Flash中的做法有明显的优势:6 y* I; t- h2 ~, F

9 N/ o! q; A* s

8 K/ \8 D) s: T3 [CKS存储的密钥数据无法通过调试端口获取,已经存储的密钥数据,即使在RDP为0的情况下也不能通过调试端口访问。
9 Y9 `! f6 H1 L& f8 |( s; C4 L& f# n8 ^" Q

$ E/ N- Q3 K4 ]7 ~; T密钥使用过程中应用程序代码虽然可以使用密钥进行加解密操作,但是始终无法直接获取密钥数据本身,降低了软件漏洞可能带来的风险。4 ]0 e/ v+ T* p# t9 V

9 b1 X* e6 ]. J7 A" g+ b! o

9 N# e5 E" ~" H( ~  W- t
4 r3 X$ S  `- y5 ]( m+ n+ y8 t1 |% k' i9 ^
; J/ ?$ ^) `, g; G4 _

' E  R7 \' Q/ a" A" F. v
4 d3 U- ?4 X, b* {/ O2 p
赞 收藏 评论1 发布时间:2021-6-15 15:50

举报

1个回答
ghost110 回答时间:2021-7-5 15:16:12
详实、详尽、详细。学无止境!
  I' c+ ?* y6 V

所属标签

相似技术帖

官网相关资源

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