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

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

[复制链接]
STMCU小助手 发布时间:2021-9-7 16:48
! f$ u  X. J3 {8 ]1 ^9 @1 u
引言
& f7 J0 p' j* ~% G0 k$ g- r
) V7 d6 \: f( f

/ x, M5 [8 }# i' K3 D7 J& gX-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。) m( z* x, S7 R- s9 ~4 c' C+ _
; E  c' W, e! N# M/ L6 A, f
) D! e/ Y  U* f5 |, Y/ e
关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。
- J9 t, }4 L' |& i* D" q% ]2 @
5 ]4 N9 j7 A3 O; z$ S
问题描述

1 D6 G) c: k& x1 k. I
* S% L& ^8 I* Z) p% o. g
! z% i: M0 I) j: G6 b% \客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算法完成该任务。下载的固件通过 AES-GCM 进行加密,并带 TAG 可以用于验证固件来源的合法性。在项目的代码中使用 X-Cube-Cryptolib 进行 AES-GCM 运算。上位机使用 cryptopp820 加密库对固件目标 bin 文件进行加密,然后在 MCU 上通过X-Cube- Cryptolib 加密库进行 AES-GCM128 解密,解密数据没有问题,但是 TAG 数据总是无法校验通过。" ]: c1 w3 P9 U- N* e" u

. K, M) k9 A% J( j5 C* r4 U7 X+ p
问题分析与定位

, T( m& i$ {+ p! a6 \( i7 V6 `# ]- r$ Y6 @/ R, f

) J* u( ]- F2 }$ I% t5 N正常情况下,当调用 AES_GCM_Decrypt_Finish(P_pAESGCMctx, NULL, P_pOutputSize);执行后,AESctx.mFlags 结果会提示是否通过校验。如果校验成功,该值应该等于 0x22,而运行结果中看到的却是 0x12。
% u& O" s6 c: q3 r
6 t: O0 e% V- {: U9 F9 z) y, o确认库函数使用方法+ {$ Q0 E. e; q2 X) y" `, G
将调用 AES-GCM 功能的代码放在 X-Cube-Cryptolib 中一个简单的测试程序的环境进行测试,查看是否有该问题,结果发现测试程序中 AES-GCM 校验是可以成功的,但是集成到客户应用中时就无法成功。那我们接下来重点研究应用程序环境。
$ e+ `9 v$ C3 M8 Z4 \4 M3 q
- s' y- A3 r# n4 y应用程序环境, c! F3 C4 g% A- V5 g
应用程序使用了 FreeRTOS,基于 IAR 编译环境。7 P( L7 l2 L# W
: B3 }4 }; J9 ?7 D
查看库文件的使用
9 D9 Y& {9 D$ I+ e% J7 Z( D% W确认使用了正确的库文件。% ^, ?/ ?3 u1 v/ Z- W
$ W- p  c2 U/ V6 D+ G$ ~
确认是否存在多线程访问
$ e& ^. X: _8 `5 @, J$ wAES-GCM 的函数会在几个线程中调用,而且确认不会出现同时调用的情况,不存在 raise condition 的问题。
) ?, X1 I  H9 I) ^- l

% `- p" a, L; d9 @查看内存使用情况  Z6 u. `0 H5 \+ s* j
最初怀疑是否因为任务栈溢出造成,于是查看内存使用情况。2 ^% Q- e( }, \" D8 {
IAR stack size: 0x4800
! p! s# c+ W3 oIAR heap size: 0x40003 q. t+ G7 ^, }9 [/ B
FreeRTOS heap size: 85KB
) _$ P" y* g: r, l执行AES 运算的线程 stack size: 2560B- }6 G, v+ b1 R2 x: [' x6 D
# A1 m( z; @1 R- f
通过 FreeRTOS 的 uxTaskGetStackHighWaterMark() 函数查看该线程还有 500 字节左右剩余空间。
- c/ q; c2 {* S* s, B/ F! H6 W2 Y9 T; ^$ y0 [
AESGCMctx_stt 结构的大小有 2360 字节,AES-GCM 加解密函数需要的 stack 大小大概在 450 字节左右,但是应用代码中将该变量定义为全局变量,以便可以在几个不同的线程中使用,这样可以确认线程栈大小没有问题,不存在 stack overflow 的问题。
; E9 t# X0 D+ {  x6 Q/ z! ~+ }% x
- U9 S  l1 m" f4 u# L查看生成代码的.map 文件% L0 k7 H; t/ O
通过比较,所有 cryptolib 中的 symbol 在 map 中的大小都正常,唯一有问题的是 AESGCMctx_stt 结构变量的大小。
6 E" X! ^  f; K; H  l# w5 e应用代码.map:AESctx 0x2002f1f4 0x8f8 Data Gb AES_GCM_Decrypt.o [1]
; _6 o' e5 q2 R5 L9 Y0 D$ `正常测试代码 .map:AESctx 0x20002e64 0x938 Data Gb AES_GCM.o [1]
: X! f0 A, O  t* a' S; O
* s0 G& W9 K6 [' @! E' V验证不过的问题应该和这个结构的数据有直接关系,接下来研究是什么造成了这个不同。4 D$ I+ U5 w- `% {7 `/ @

: C* v+ G8 I# {$ o. N查看项目使用的 crypto 库头文件3 a" e; j7 u* G  n/ H* O, I: k+ ~
经检查,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 是否定义会有所不同。' G! d/ J8 y1 _; W! W
! h, ?  s* q7 N, e( \0 ]& Y& l
0 r# o" n( R- _" E. K2 d
//#define INCLUDE_DES ((uint16_t)0x0001) /*!< DES functions are included in the library. */  u- e- _0 ?4 v6 q" @% ^: j
//#define INCLUDE_TDES ((uint16_t)0x0002) /*!< TripleDES (TDES) functions are included in the library. */
% F! ^" n' }4 a% M. ?, @#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
  f/ h+ L9 D- ~  ^//#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */
, t! A) N1 p4 f; y) |//#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */
7 |( C2 J% b2 x4 q//#define INCLUDE_ARC4 ((uint16_t)0x0020) /*!< ARC4 functions are included in the library. */# t* ]6 K$ L- A/ j+ d6 c
//#define INCLUDE_CHACHA ((uint16_t)0x0040) /*!< ChaCha functions are included in the library. */& @! ]( E8 ?4 S7 _4 |3 {
//#define INCLUDE_CHACHA20POLY1305 ((uint16_t)0x0080) /*!< oly1305- AES functions are included in the library */
* S5 I7 _- S4 G& I9 i# w! x
4 o" S! R% t# }4 }: V
问题解决

; A6 ^  a2 f9 w  ]. \( _+ _" q7 D+ D, ]. @9 Q% k/ n
将 config.h 里面被注释掉的两行定义打开,重新编译,此时 TAG 验证能够正常通过。" |  ^. S: u/ y% N8 u/ ~
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
4 |( h$ R/ ]: l#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */+ Q! p* V! ]; W6 b/ Y
#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */' L; x# u1 e& f. t

$ k) m. @) a( d- q% d( }2 i
小结
' L; Y4 V1 h; A2 h
简言之,如果使用 X-Cube-Cryptolib 库的话,作为用户就不要改动 config.h 的内容, 不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。) N- K7 }* d) I$ p; P" f0 V
% n( ]: }0 P! I+ H8 Q
收藏 1 评论0 发布时间:2021-9-7 16:48

举报

0个回答

所属标签

相似分享

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