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

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

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

( ~' Z/ u; s" O! ~/ Z. j2 s
引言

, x& }( x! s& U" O; N5 S5 z
; g# u1 b0 O* J+ r5 S' i- S* d# g3 ]  A6 O3 t  O- c7 \' i7 F
X-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。; k% x3 U* A/ a4 D9 ~( j

# Z: {( R: R% }: [( \
5 B7 v- Q+ L( E; y7 q  b, g9 x) w
关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。  N$ L  J2 M+ U6 q( ]+ P

6 U0 F# ^) v" b( n8 Y! _
问题描述

* Y2 ], f7 p* H, i9 i1 [# |2 n
6 `: D& Z1 r8 Y! h3 Y
  r/ ]5 r& l% F9 |' U$ d+ r客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算法完成该任务。下载的固件通过 AES-GCM 进行加密,并带 TAG 可以用于验证固件来源的合法性。在项目的代码中使用 X-Cube-Cryptolib 进行 AES-GCM 运算。上位机使用 cryptopp820 加密库对固件目标 bin 文件进行加密,然后在 MCU 上通过X-Cube- Cryptolib 加密库进行 AES-GCM128 解密,解密数据没有问题,但是 TAG 数据总是无法校验通过。
' ^! _, a; x% V) |5 Y0 `, V
, y5 j7 r5 E3 {, l' O" S% X
问题分析与定位
7 {5 J- B8 Z# J& k2 H! K' M
; c6 i# Y0 T$ d$ F" Y4 n

% `& \6 P" P4 U正常情况下,当调用 AES_GCM_Decrypt_Finish(P_pAESGCMctx, NULL, P_pOutputSize);执行后,AESctx.mFlags 结果会提示是否通过校验。如果校验成功,该值应该等于 0x22,而运行结果中看到的却是 0x12。  F. U+ Y' x0 Y7 s; B& \+ {$ Y
, x2 v; J& i" s1 K6 }/ E. U$ ~* T
确认库函数使用方法; E3 T, p0 E0 Y4 U2 {
将调用 AES-GCM 功能的代码放在 X-Cube-Cryptolib 中一个简单的测试程序的环境进行测试,查看是否有该问题,结果发现测试程序中 AES-GCM 校验是可以成功的,但是集成到客户应用中时就无法成功。那我们接下来重点研究应用程序环境。/ W: ?) U) J7 ?# F
( i2 x0 P' B% w, U+ i, @
应用程序环境+ h, T" P. l" t3 ~: L
应用程序使用了 FreeRTOS,基于 IAR 编译环境。
, z& Q( ~9 [6 u$ D6 `8 v5 }
9 V9 j! t6 t* _; h7 |1 I' x查看库文件的使用  P( h5 N6 _: F$ u! f! Y7 P
确认使用了正确的库文件。8 e0 U, x' F$ h( w' p$ d) t

5 S* w" o& K# u+ E( n确认是否存在多线程访问' x2 o2 x( o) x
AES-GCM 的函数会在几个线程中调用,而且确认不会出现同时调用的情况,不存在 raise condition 的问题。
- O4 U% v* Z7 k) }7 J" l1 W. N

) d* p' G. I! U0 C% ?/ W3 v查看内存使用情况" R7 T1 [- [' z
最初怀疑是否因为任务栈溢出造成,于是查看内存使用情况。) |- D% l1 w' q/ T& I
IAR stack size: 0x4800
5 c- y8 g9 v( {) U1 b# Q8 dIAR heap size: 0x4000' A, w% Z. O4 Y, U2 L& j8 P  Z
FreeRTOS heap size: 85KB
$ p5 u! k; K4 N1 y执行AES 运算的线程 stack size: 2560B
+ V6 E5 D0 p5 I; z  R0 H* [' _' u1 |' O, T- }9 r
通过 FreeRTOS 的 uxTaskGetStackHighWaterMark() 函数查看该线程还有 500 字节左右剩余空间。
$ \) I' H1 y: Q+ i0 K0 L( f& O& y0 }9 N& U
AESGCMctx_stt 结构的大小有 2360 字节,AES-GCM 加解密函数需要的 stack 大小大概在 450 字节左右,但是应用代码中将该变量定义为全局变量,以便可以在几个不同的线程中使用,这样可以确认线程栈大小没有问题,不存在 stack overflow 的问题。
8 o- b. s/ C9 o" E, n- I; O2 f# L5 }9 j1 j# ~
查看生成代码的.map 文件
8 u* {' M$ B$ j( ?2 c通过比较,所有 cryptolib 中的 symbol 在 map 中的大小都正常,唯一有问题的是 AESGCMctx_stt 结构变量的大小。$ O$ h0 }% r& [' T3 Q$ c6 d" J
应用代码.map:AESctx 0x2002f1f4 0x8f8 Data Gb AES_GCM_Decrypt.o [1], D1 E& n/ d/ |  P, X. g3 u
正常测试代码 .map:AESctx 0x20002e64 0x938 Data Gb AES_GCM.o [1]5 ]& Z; s: b( K5 T. F

  N7 ?& C3 q; h: m! n验证不过的问题应该和这个结构的数据有直接关系,接下来研究是什么造成了这个不同。
) Z; i8 N3 W0 G" w4 G
8 u0 N% r, B" W! A+ L5 y查看项目使用的 crypto 库头文件
. H" {" y7 F2 Q* I7 Y9 \9 C3 _+ l* x) y经检查,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 是否定义会有所不同。$ l* x& J1 c9 \  g# q" o5 n& p

( u; ]* W1 d9 t- }  V" `: t* C, K

0 A4 F9 O8 W# m7 g4 L//#define INCLUDE_DES ((uint16_t)0x0001) /*!< DES functions are included in the library. */* H) D: r8 Z+ H) \& g% a
//#define INCLUDE_TDES ((uint16_t)0x0002) /*!< TripleDES (TDES) functions are included in the library. */( {0 ^- ], U" `2 v. b# c. B
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */, p2 j% _9 v$ R
//#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */
8 V: S! P: Z* V; N' E//#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */- P. `3 G) E, c
//#define INCLUDE_ARC4 ((uint16_t)0x0020) /*!< ARC4 functions are included in the library. */" u) x* Q( X; A- r% l- X% t
//#define INCLUDE_CHACHA ((uint16_t)0x0040) /*!< ChaCha functions are included in the library. */- v& L' I+ W, c4 K5 ?% s9 \
//#define INCLUDE_CHACHA20POLY1305 ((uint16_t)0x0080) /*!< oly1305- AES functions are included in the library */+ Y* i& _( t) u% N) b

, z$ L' Y  @8 r  b8 J% S* b. u
问题解决

+ ?8 L+ X) \7 D
( ^+ ~: r2 S: H7 C$ p; L  [将 config.h 里面被注释掉的两行定义打开,重新编译,此时 TAG 验证能够正常通过。7 y9 n5 r* F. h. h) P9 a! S
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */% ?1 P9 `" p1 I
#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */! `3 |! c3 @9 M" J6 L
#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */
' }- G! d. H9 w1 O7 B% I
8 r8 B9 c# q4 {8 F
小结

- \1 r4 A8 F+ _简言之,如果使用 X-Cube-Cryptolib 库的话,作为用户就不要改动 config.h 的内容, 不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。$ X* _7 K# |; A' W9 K3 c4 A
0 X! P3 g; T: ~) X6 i) Z" x
赞 收藏 1 评论0 发布时间:2021-9-7 16:48

举报

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