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

工程师笔记 | Crypto算法库使用技巧 —— 基于STM32 AES GCM应用提示

[复制链接]
STMCU小助手 发布时间:2021-9-7 16:48

3 K* I  E: |% Z
引言

' z% `2 D" ^- l
' e$ M1 Z7 Q0 n+ [4 e+ z8 U: |$ x1 L! ^& X5 c. D7 c% b% g
X-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。' z* q  z0 t8 P- [
5 E/ ]! B+ ~: q  {$ C/ M  H

- w7 Z, S6 U9 K关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。9 r1 v7 q3 i: K' F) c+ Z
; M/ a5 B% o* C) D7 {1 J
问题描述
0 k+ r# ^/ e0 I; x' _3 k& N
. s3 u3 \1 U* h* w( j! _8 J7 d% y

1 E# `, F- d' n客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算法完成该任务。下载的固件通过 AES-GCM 进行加密,并带 TAG 可以用于验证固件来源的合法性。在项目的代码中使用 X-Cube-Cryptolib 进行 AES-GCM 运算。上位机使用 cryptopp820 加密库对固件目标 bin 文件进行加密,然后在 MCU 上通过X-Cube- Cryptolib 加密库进行 AES-GCM128 解密,解密数据没有问题,但是 TAG 数据总是无法校验通过。
& S1 o/ N7 t( u7 [
( p' q+ }6 n, K5 ]' N' f
问题分析与定位
: _) J4 y  c9 A! x( E

8 {, J$ s9 i4 Y$ o
9 A; i$ T" i! G  f1 S- {正常情况下,当调用 AES_GCM_Decrypt_Finish(P_pAESGCMctx, NULL, P_pOutputSize);执行后,AESctx.mFlags 结果会提示是否通过校验。如果校验成功,该值应该等于 0x22,而运行结果中看到的却是 0x12。# R$ v% D+ g0 X2 X% d

7 p& o6 ?: a) C- |! B4 v& }确认库函数使用方法
, Z6 U( A# o4 c# E3 L8 ]1 P将调用 AES-GCM 功能的代码放在 X-Cube-Cryptolib 中一个简单的测试程序的环境进行测试,查看是否有该问题,结果发现测试程序中 AES-GCM 校验是可以成功的,但是集成到客户应用中时就无法成功。那我们接下来重点研究应用程序环境。- }& I( ~( r& m5 J. V- {5 o
# E( p- U4 c% _& I+ K- w) U
应用程序环境
' n' ]: U/ {" G  k# ]) C应用程序使用了 FreeRTOS,基于 IAR 编译环境。
; T( F# a$ b  o' x9 u  b% V/ p& T8 C2 {' R* T0 I5 Q$ k& g
查看库文件的使用& G2 G: Q1 ?& ?$ N# ~
确认使用了正确的库文件。
9 h' ]7 i/ W) A9 Q
* Z/ v- O* A' j! s" R% n
确认是否存在多线程访问
0 \' w4 \0 q5 s6 j/ iAES-GCM 的函数会在几个线程中调用,而且确认不会出现同时调用的情况,不存在 raise condition 的问题。
8 c6 W4 L! h' Y1 M; s( z
8 |& l! M/ l: {
查看内存使用情况1 g" E, ^8 I: d3 C, j1 f# D& J# g7 w
最初怀疑是否因为任务栈溢出造成,于是查看内存使用情况。: r4 ?* N$ z: W% v8 G( r) o6 _) Q
IAR stack size: 0x4800  D4 r6 f" F0 }
IAR heap size: 0x4000
/ q, H: a0 P% a) ]* cFreeRTOS heap size: 85KB" I- k' E. D  L% c" d  m4 E! Y
执行AES 运算的线程 stack size: 2560B" n) Z/ x8 e% w1 p3 o

8 `$ k% Y9 A4 r: Q/ B9 r通过 FreeRTOS 的 uxTaskGetStackHighWaterMark() 函数查看该线程还有 500 字节左右剩余空间。
3 Y+ H9 h9 i8 F
- _- w9 I. T! f$ H0 J( S4 MAESGCMctx_stt 结构的大小有 2360 字节,AES-GCM 加解密函数需要的 stack 大小大概在 450 字节左右,但是应用代码中将该变量定义为全局变量,以便可以在几个不同的线程中使用,这样可以确认线程栈大小没有问题,不存在 stack overflow 的问题。: p! B) u( B5 Y/ _5 f% a
& C5 E- J. v! r- o4 f  `! |
查看生成代码的.map 文件
* Q, S- R9 M  c1 r0 t通过比较,所有 cryptolib 中的 symbol 在 map 中的大小都正常,唯一有问题的是 AESGCMctx_stt 结构变量的大小。
! |( C. Y1 I; u8 S: B" n" `应用代码.map:AESctx 0x2002f1f4 0x8f8 Data Gb AES_GCM_Decrypt.o [1]
/ e# d% L1 ]! k6 m正常测试代码 .map:AESctx 0x20002e64 0x938 Data Gb AES_GCM.o [1]7 Q3 ]8 ?! h( _$ U4 K9 n2 K, h
- f1 i4 z: D2 ?+ _4 j5 E
验证不过的问题应该和这个结构的数据有直接关系,接下来研究是什么造成了这个不同。
3 Y! O7 N7 D8 z) k8 H8 n
8 R! G7 k2 I9 N$ N2 U5 \查看项目使用的 crypto 库头文件
( N; ^: O& X/ \% v5 f' i经检查,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 是否定义会有所不同。
) x5 z. H  P4 q+ k, ]( U* r6 w/ B! ~5 r( A; @- L' n3 @
2 |+ L( L1 u* ]
//#define INCLUDE_DES ((uint16_t)0x0001) /*!< DES functions are included in the library. */
* ?; i9 B( b8 Z" M4 E. F) P$ ~" y//#define INCLUDE_TDES ((uint16_t)0x0002) /*!< TripleDES (TDES) functions are included in the library. */4 }3 R# c  G4 Q
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */* b. n& X; R1 X) Q* s
//#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */5 E7 w" p& ]( S* z1 |
//#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */
: W$ E- ^) O# w6 S/ c: K* N//#define INCLUDE_ARC4 ((uint16_t)0x0020) /*!< ARC4 functions are included in the library. */
) S. Q5 u# M7 t1 Z5 J% z+ Q//#define INCLUDE_CHACHA ((uint16_t)0x0040) /*!< ChaCha functions are included in the library. */! J! ~" ^% l# Q: k( ^" k
//#define INCLUDE_CHACHA20POLY1305 ((uint16_t)0x0080) /*!< oly1305- AES functions are included in the library */& G: J/ m/ \. F
9 Q/ e/ c8 b/ E9 [, I2 v5 r2 d+ G
问题解决
. k0 e/ J9 A6 a
& ^. a3 M+ S' p1 E) y. u
将 config.h 里面被注释掉的两行定义打开,重新编译,此时 TAG 验证能够正常通过。+ d" k: [! A  l; S6 |7 d
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
$ S  m; z$ E% Z* v4 n#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */% C/ B- H3 n* _4 k
#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */
1 [0 G& }/ O. C8 L2 M
6 Z! f/ k6 k1 I$ s. {
小结

$ e& V& H; W. A+ P, w6 s简言之,如果使用 X-Cube-Cryptolib 库的话,作为用户就不要改动 config.h 的内容, 不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。, C9 ?9 K- ^) n' Q% W+ f; L# r
( H5 R& w* G0 K' o
赞 收藏 1 评论0 发布时间:2021-9-7 16:48

举报

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