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

信息安全专题 | Crypto算法库使用技巧 —— 基于STM32 AES GCM应用提示

[复制链接]
STMCU-管管 发布时间:2021-8-25 10:31
信息安全专题 | Crypto算法库使用技巧 —— 基于STM32 AES GCM应用提示: Z8 z9 U/ o& c9 E3 |1 D; a. n

: J! |0 d0 K; Z: y
% W4 T" ~' G4 I* G6 J2 y
引言

+ F1 t3 @% x+ a* \- @7 |X-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。: Z! D5 ~0 t/ [1 d' Z! _
) e$ N! J$ m6 ^1 w. _7 A$ @- \  ~1 x

3 ~) {/ r0 V) M: ^关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。' ?% a# @7 U' f1 c9 U; V. D' a

; c5 b3 ~3 I& T3 q
问题描述
# h- c8 F: |6 a+ m1 O. |" J8 ^

& H& r5 ^$ Y- U3 D, W( ^7 t- Q客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算法完成该任务。下载的固件通过 AES-GCM 进行加密,并带 TAG 可以用于验证固件来源的合法性。在项目的代码中使用 X-Cube-Cryptolib 进行 AES-GCM 运算。上位机使用 cryptopp820 加密库对固件目标 bin 文件进行加密,然后在 MCU 上通过X-Cube- Cryptolib 加密库进行 AES-GCM128 解密,解密数据没有问题,但是 TAG 数据总是无法校验通过。: J2 W4 _0 T  i9 ^7 r

, f* F3 J4 s; V  `1 n% i, _
问题分析与定位
3 a( f' |( u/ Z3 Z* T" j
正常情况下,当调用 AES_GCM_Decrypt_Finish(P_pAESGCMctx, NULL, P_pOutputSize);执行后,AESctx.mFlags 结果会提示是否通过校验。如果校验成功,该值应该等于 0x22,而运行结果中看到的却是 0x12。
5 U5 q- `* D- N1 _' D/ \! g1 A& [. _+ h& \! ^$ k( V/ c2 H
! {% ]1 J% T) h" B  @; D! r, {( e# I
确认库函数使用方法% F8 l- M# I. L  l
将调用 AES-GCM 功能的代码放在 X-Cube-Cryptolib 中一个简单的测试程序的环境进行测试,查看是否有该问题,结果发现测试程序中 AES-GCM 校验是可以成功的,但是集成到客户应用中时就无法成功。那我们接下来重点研究应用程序环境。/ c* H2 {2 T$ r! Q# @8 j) ~. {9 ?
0 c# [* y9 c& ^* k2 D8 Z

# o& {1 M; A, F; S# d应用程序环境
- J* {. e, y$ g! J% Q  X$ ^应用程序使用了 FreeRTOS,基于 IAR 编译环境。* |3 e! k/ C7 `- E: I& j
/ [3 ^  t) w8 V1 S7 [6 ~; D. F
' N5 M& z& Y- {/ J5 }
查看库文件的使用5 {. x& C, d7 z0 l. b
确认使用了正确的库文件。. e6 o/ A1 z& w8 a+ Q% K
; M$ s+ ~% w, l& A- w
+ G+ ~1 k- ^1 H7 M. k
确认是否存在多线程访问1 m- I, K  Z. r% @1 O7 s( l
AES-GCM 的函数会在几个线程中调用,而且确认不会出现同时调用的情况,不存在 raise condition 的问题。
& X6 I* p0 _, K; t/ f* s9 s7 ?
& ^( a9 \3 i- k" J; {" I

2 Q& _0 G6 c3 ]* e% V' s查看内存使用情况
0 T2 w  s* z# q4 e$ \# O最初怀疑是否因为任务栈溢出造成,于是查看内存使用情况。) `/ s3 v9 {2 j6 Y8 Y
IAR stack size: 0x4800
) c9 U" ^% N# w* S+ q) _4 wIAR heap size: 0x4000
7 Q: S* t  l6 K& k0 ?( Z) A4 _FreeRTOS heap size: 85KB
+ n5 i+ O( k" [  C- v- J; m/ g执行AES 运算的线程 stack size: 2560B# @# G& |/ M# S; I
- X2 M; T5 v- A
2 ]. c1 r! F/ l' k6 Z2 _, \# E- p
通过 FreeRTOS 的 uxTaskGetStackHighWaterMark() 函数查看该线程还有 500 字节左右剩余空间。6 I( ^' q9 v3 K$ j

, a, a3 X7 P3 C+ b+ u1 A6 b8 {# }

8 m' ~+ v) a) C( u. v5 jAESGCMctx_stt 结构的大小有 2360 字节,AES-GCM 加解密函数需要的 stack 大小大概在 450 字节左右,但是应用代码中将该变量定义为全局变量,以便可以在几个不同的线程中使用,这样可以确认线程栈大小没有问题,不存在 stack overflow 的问题。
3 x3 i/ D, r6 `7 c
; `! G0 I8 U6 h. Y6 S- s9 Q

2 U6 e) g) I3 @6 ]' u& @查看生成代码的.map 文件
/ [0 s+ z( z( V通过比较,所有 cryptolib 中的 symbol 在 map 中的大小都正常,唯一有问题的是 AESGCMctx_stt 结构变量的大小。. k* R$ V! g  m
应用代码.map:AESctx 0x2002f1f4 0x8f8 Data Gb AES_GCM_Decrypt.o [1]2 @3 ]% s. L. \9 q
正常测试代码 .map:AESctx 0x20002e64 0x938 Data Gb AES_GCM.o [1]6 ^0 d& i8 D- L( k5 _0 d) w$ X/ _7 G8 j- G

% U8 r7 B% H- c* M

; s$ o8 j* M6 |( M/ j$ F' H4 Z% ]5 z验证不过的问题应该和这个结构的数据有直接关系,接下来研究是什么造成了这个不同。
1 E* x+ I* H5 D7 E
0 p3 ?6 {& C6 S& H: J3 X  g
+ ?$ H. k+ `% _, g8 T4 W; B$ B
查看项目使用的 crypto 库头文件# T1 @0 X1 P. w, ]$ y" W
经检查,INCLUDE_AES192 和 INCLUDE_AES256 两个宏定义在 config.h 的定义中被注释掉,这将导致 aes_gcm.h 中 AESGCMctx_stt 数据结构的成员变量 uint32_t amExpKey[CRL_AES_MAX_EXPKEY_SIZE];的大小发生变化,因为CRL_AES_MAX_EXPKEY_SIZE 的定义根据INCLUDE_AES128/192/256 是否定义会有所不同。0 H6 K# s1 ^" _

7 ~. z9 A0 \3 t0 {
& V. L9 Y" t% G; A
//#define INCLUDE_DES ((uint16_t)0x0001) /*!< DES functions are included in the library. */
. q- h2 s$ u6 y+ y/ H" X4 f/ k" \; H/ [//#define INCLUDE_TDES ((uint16_t)0x0002) /*!< TripleDES (TDES) functions are included in the library. */
: s) I, m& p; P5 O3 s#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
9 J/ P" g8 A4 x# |//#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */
2 w8 }6 y4 b1 b% Z+ H" P//#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */# n- W, f# x, x9 R! Z
//#define INCLUDE_ARC4 ((uint16_t)0x0020) /*!< ARC4 functions are included in the library. */" W2 [: a1 B1 W, j) W9 m
//#define INCLUDE_CHACHA ((uint16_t)0x0040) /*!< ChaCha functions are included in the library. */4 {2 m7 ^% [" Z  R
//#define INCLUDE_CHACHA20POLY1305 ((uint16_t)0x0080) /*!< oly1305- AES functions are included in the library */0 j1 w, t1 R, x  _/ ^( a8 B% ?0 ^. e

8 s& u$ W/ A5 O% G4 j3 P2 O$ I

3 q; ?9 I* F6 P4 v! m5 z
问题解决
' y  r- \; m& G, V6 ~3 y7 b

6 d: F+ ?  B) r. I  l( X将 config.h 里面被注释掉的两行定义打开,重新编译,此时 TAG 验证能够正常通过。
% B- f1 ^1 h- Q! B2 q  O#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */8 d% F+ p8 c) Y
#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */
" H3 |7 f1 X3 Y. y8 B- e* ^6 B1 x#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */
' R4 J- c1 v$ _1 C
小结
" `4 b* B* t0 l. u
简言之,如果使用 X-Cube-Cryptolib 库的话,作为用户就不要改动 config.h 的内容, 不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。  z, l! [( C5 H% _* B: ~
" x+ H6 C% V+ F8 Z7 j  t
赞 收藏 评论0 发布时间:2021-8-25 10:31

举报

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