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

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

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

- P# q- A' M' u% e( \9 |) Y
引言

  R) a/ ?. e6 l/ T* l0 a9 t! r0 g) ~0 \
/ V% g" ~; Z! E- R! {
X-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。/ s! s+ H5 ^+ @: V# a. m: o
$ l5 w: G* n( J1 W
4 D2 H3 A* w; L/ Z) H; O
关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。- B0 M5 Q; v1 U5 @$ R1 B

: K' w  O1 ~% j& m3 P% o
问题描述
# B& t/ j2 W- G  }  N" a

1 ?" ~; h" x% R; |7 w( O6 K; o6 T. k
客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算法完成该任务。下载的固件通过 AES-GCM 进行加密,并带 TAG 可以用于验证固件来源的合法性。在项目的代码中使用 X-Cube-Cryptolib 进行 AES-GCM 运算。上位机使用 cryptopp820 加密库对固件目标 bin 文件进行加密,然后在 MCU 上通过X-Cube- Cryptolib 加密库进行 AES-GCM128 解密,解密数据没有问题,但是 TAG 数据总是无法校验通过。( T& `) ^9 \' E, ^  K7 A- ]* Y  Q
' p* l& c% h9 u; U9 J
问题分析与定位

3 a( u& R% I  Y, }+ I, f+ e( M
( h  {4 u+ ]6 C$ Q& X3 C6 W. s
正常情况下,当调用 AES_GCM_Decrypt_Finish(P_pAESGCMctx, NULL, P_pOutputSize);执行后,AESctx.mFlags 结果会提示是否通过校验。如果校验成功,该值应该等于 0x22,而运行结果中看到的却是 0x12。+ r- R/ k, }* r& P0 E- }
6 _% F3 T8 I  s! v. b, n
确认库函数使用方法; A0 P. l: G/ w& P. A
将调用 AES-GCM 功能的代码放在 X-Cube-Cryptolib 中一个简单的测试程序的环境进行测试,查看是否有该问题,结果发现测试程序中 AES-GCM 校验是可以成功的,但是集成到客户应用中时就无法成功。那我们接下来重点研究应用程序环境。
9 R$ V( u2 V# B" H8 d
8 `$ }- a/ n7 a: r" a+ L应用程序环境
2 _: ?) h# ?4 D4 r, E$ A. O应用程序使用了 FreeRTOS,基于 IAR 编译环境。" w2 ^3 x; Q" t# W* ~5 C
2 B& z4 o: P) t7 U5 Z, p
查看库文件的使用- _# l" K* T3 \
确认使用了正确的库文件。
$ e. V1 @' s% {7 U

* H- v$ I2 j0 u+ _. q& N确认是否存在多线程访问
; e! |) A" F& D/ G* YAES-GCM 的函数会在几个线程中调用,而且确认不会出现同时调用的情况,不存在 raise condition 的问题。( x. Q' K  n& o' ^  s; B

( J! t. f0 v, ^! T$ @6 `! X7 \查看内存使用情况
2 p8 w1 p0 {5 a5 s. l2 r最初怀疑是否因为任务栈溢出造成,于是查看内存使用情况。9 f) ?( X1 n- T% ]9 K2 g6 L
IAR stack size: 0x4800& G; u3 H7 @/ {" i
IAR heap size: 0x40009 W) z/ t5 H) D+ [" F! i9 k8 P1 t# O
FreeRTOS heap size: 85KB
7 x1 n9 g) q( x执行AES 运算的线程 stack size: 2560B5 r7 r; w( Y/ [

% Y* g5 }  F0 Y0 T8 \通过 FreeRTOS 的 uxTaskGetStackHighWaterMark() 函数查看该线程还有 500 字节左右剩余空间。
7 S5 F* X" E. P" Q1 p4 ?  S( X& O+ U  B0 h! Q- H* S
AESGCMctx_stt 结构的大小有 2360 字节,AES-GCM 加解密函数需要的 stack 大小大概在 450 字节左右,但是应用代码中将该变量定义为全局变量,以便可以在几个不同的线程中使用,这样可以确认线程栈大小没有问题,不存在 stack overflow 的问题。. @* C+ J8 [; f( L" J- V; u- Q/ ~

7 S5 t0 q9 ^+ _0 N8 O查看生成代码的.map 文件
$ _% i8 K1 l, s( F: V% }通过比较,所有 cryptolib 中的 symbol 在 map 中的大小都正常,唯一有问题的是 AESGCMctx_stt 结构变量的大小。
  _% m$ R: l7 |3 E: }# A应用代码.map:AESctx 0x2002f1f4 0x8f8 Data Gb AES_GCM_Decrypt.o [1]- S! D9 E5 z* M$ J: y! m
正常测试代码 .map:AESctx 0x20002e64 0x938 Data Gb AES_GCM.o [1]
% ^/ U2 z6 i9 S* Z* ]2 V, F- j- v/ a
验证不过的问题应该和这个结构的数据有直接关系,接下来研究是什么造成了这个不同。
& Z- }7 X" \& {) b) u+ b; D3 s  J/ I+ I7 `) P; p/ E3 V' L
查看项目使用的 crypto 库头文件
& X1 m. Z; D2 f) C! r3 r# P& Z经检查,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 是否定义会有所不同。' g8 _' x( B/ c9 ?+ j

# U: l: i3 X1 X' H$ S1 {

1 _0 I& \! D! i1 c//#define INCLUDE_DES ((uint16_t)0x0001) /*!< DES functions are included in the library. */
  O; h0 O% I( ^5 N//#define INCLUDE_TDES ((uint16_t)0x0002) /*!< TripleDES (TDES) functions are included in the library. */. {2 g5 C. R1 i
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
" w; J! e/ L- d2 L6 [: o//#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */4 j- R* ]& f* S8 I7 g
//#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */' d% @4 _& q! Y! r+ D" l
//#define INCLUDE_ARC4 ((uint16_t)0x0020) /*!< ARC4 functions are included in the library. */
4 ?7 ~8 }( a" e- U% e0 A//#define INCLUDE_CHACHA ((uint16_t)0x0040) /*!< ChaCha functions are included in the library. */
1 N# ?5 K2 d# q+ [5 a//#define INCLUDE_CHACHA20POLY1305 ((uint16_t)0x0080) /*!< oly1305- AES functions are included in the library */
" l) }) V% d0 _7 V- D" S  }
3 f$ y+ ]4 P" p! q
问题解决
# W- D6 Y& t3 N& s+ l
! k% T9 n8 N( m; z# p6 q$ _% y6 y
将 config.h 里面被注释掉的两行定义打开,重新编译,此时 TAG 验证能够正常通过。* e1 T% @, r6 X- r1 Y
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
0 d. G3 h4 L5 D' a# h#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */
( a% T3 \  h4 C  y4 U6 e' j#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */
$ h- W& J3 _8 Z9 w1 F; ^( h" |, t  Z/ w. b8 H# h
小结

. y2 T" p) q. j7 L: l, b2 _# x简言之,如果使用 X-Cube-Cryptolib 库的话,作为用户就不要改动 config.h 的内容, 不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。
7 d+ T* h, H" R/ w9 G8 X3 R: \0 j! f0 \4 G2 \
收藏 1 评论0 发布时间:2021-9-7 16:48

举报

0个回答

所属标签

相似分享

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