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

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

[复制链接]
STMCU小助手 发布时间:2021-9-7 16:48
: x/ u% g* {! [
引言

$ r- l, U3 D. g( h( \8 x' y! m1 \3 o
$ X0 w  {' r' R
X-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。5 m6 R4 ^5 y. Z/ `' f* R* T* t
, T/ o' S, E" S$ Q, L2 z. L
$ U7 G9 n, i3 `3 G/ n5 Q
关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。. |' H2 u# G' B  Z: `

; H1 R" f! T6 b" E5 w" u6 b: q' d
问题描述

8 ?8 L0 a) J4 \1 C# g+ V& V6 g4 d1 j) J- F0 ]( p7 k
4 p+ u+ c) D2 g# J4 M, s+ A4 R
客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算法完成该任务。下载的固件通过 AES-GCM 进行加密,并带 TAG 可以用于验证固件来源的合法性。在项目的代码中使用 X-Cube-Cryptolib 进行 AES-GCM 运算。上位机使用 cryptopp820 加密库对固件目标 bin 文件进行加密,然后在 MCU 上通过X-Cube- Cryptolib 加密库进行 AES-GCM128 解密,解密数据没有问题,但是 TAG 数据总是无法校验通过。  c& B5 L* ~4 R- @" e

) c; P5 w/ @; A7 ], c
问题分析与定位
" M! Q5 x1 H5 [! R# I- V- B
! S6 w" @: a/ F2 l- y/ H; p
. N5 S( c# @5 F9 A
正常情况下,当调用 AES_GCM_Decrypt_Finish(P_pAESGCMctx, NULL, P_pOutputSize);执行后,AESctx.mFlags 结果会提示是否通过校验。如果校验成功,该值应该等于 0x22,而运行结果中看到的却是 0x12。
% g$ Z! K9 b+ x1 F% i6 N+ ^4 c8 E  X  F# x6 s: w' p7 {. t' e
确认库函数使用方法" u; p0 i1 V; L
将调用 AES-GCM 功能的代码放在 X-Cube-Cryptolib 中一个简单的测试程序的环境进行测试,查看是否有该问题,结果发现测试程序中 AES-GCM 校验是可以成功的,但是集成到客户应用中时就无法成功。那我们接下来重点研究应用程序环境。, j$ q+ u, _# k' Q# t2 l
0 |( x. Q9 B. m6 R8 j( C
应用程序环境6 j  U  b  ?. `4 o0 b; Z
应用程序使用了 FreeRTOS,基于 IAR 编译环境。8 V4 L4 H8 F- K

1 D7 V1 v; o. I查看库文件的使用
9 N$ R* H' w5 w" i, }' F确认使用了正确的库文件。" [; [2 w" a, J

6 T( @8 _- b/ a  e0 Y确认是否存在多线程访问* u  q3 x! y: k4 V6 K
AES-GCM 的函数会在几个线程中调用,而且确认不会出现同时调用的情况,不存在 raise condition 的问题。
7 l' `! \+ ?: N. q/ i
  H* V. e" m* [& j
查看内存使用情况& W' K+ B- o# z8 q
最初怀疑是否因为任务栈溢出造成,于是查看内存使用情况。9 B/ K- A% d+ N* [% c5 I$ F
IAR stack size: 0x4800+ J. n' Y5 X) E5 `0 h9 U
IAR heap size: 0x40007 W2 p: \9 U- M, T- |; K& k
FreeRTOS heap size: 85KB
  @: K* `0 I# k0 G/ b$ m执行AES 运算的线程 stack size: 2560B
8 v$ o0 a& e6 x. Z3 Q2 {
3 A, I% ^6 \& I1 e7 _5 {7 @通过 FreeRTOS 的 uxTaskGetStackHighWaterMark() 函数查看该线程还有 500 字节左右剩余空间。6 U) d6 P, Z, c0 M  l2 t2 [& t

1 \+ ~/ r# P6 \0 G* K, zAESGCMctx_stt 结构的大小有 2360 字节,AES-GCM 加解密函数需要的 stack 大小大概在 450 字节左右,但是应用代码中将该变量定义为全局变量,以便可以在几个不同的线程中使用,这样可以确认线程栈大小没有问题,不存在 stack overflow 的问题。
/ ?# N+ F5 [+ U* T3 O, ]6 [( F8 `' G! g9 S. D' h+ j+ |
查看生成代码的.map 文件
( R6 ^7 X& r" d% b4 Q3 m8 S1 L; j" ^通过比较,所有 cryptolib 中的 symbol 在 map 中的大小都正常,唯一有问题的是 AESGCMctx_stt 结构变量的大小。
7 m# S6 w4 y# G应用代码.map:AESctx 0x2002f1f4 0x8f8 Data Gb AES_GCM_Decrypt.o [1]
4 v# \1 Q' @; w6 [+ y" I, K正常测试代码 .map:AESctx 0x20002e64 0x938 Data Gb AES_GCM.o [1]
) E8 f4 l0 p  I3 ?
0 u8 P4 G6 h8 l, h2 |& S* J/ y验证不过的问题应该和这个结构的数据有直接关系,接下来研究是什么造成了这个不同。: [/ d2 t5 ?( U5 x  q
+ `: o% o0 \$ c3 e' g  @5 i3 ^
查看项目使用的 crypto 库头文件
* v0 i& A; X: l4 O" U7 Z3 m1 c经检查,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 是否定义会有所不同。% E( N* |# h: H' G9 |5 U

# o, ~6 O; V1 R" i
3 k* A) m' M# C6 |
//#define INCLUDE_DES ((uint16_t)0x0001) /*!< DES functions are included in the library. */! p; V& I" ]  F* i
//#define INCLUDE_TDES ((uint16_t)0x0002) /*!< TripleDES (TDES) functions are included in the library. */) c" H# c) K4 _3 X; {! V' P
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
' D( w! o9 Z) t" D- D1 Z//#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */: `* S* Z6 Q! g2 I7 v
//#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */6 G  a4 Q0 V- E5 i+ @( o
//#define INCLUDE_ARC4 ((uint16_t)0x0020) /*!< ARC4 functions are included in the library. */
& T5 c/ @" k% T1 q0 ~8 Q# u//#define INCLUDE_CHACHA ((uint16_t)0x0040) /*!< ChaCha functions are included in the library. */
( l% Z2 C( ^& `7 `8 o//#define INCLUDE_CHACHA20POLY1305 ((uint16_t)0x0080) /*!< oly1305- AES functions are included in the library */
5 E% `! P  f+ k. N: z3 N$ \. l  e! \6 R2 `, K
问题解决
, e5 E% c1 h3 F+ a9 v+ h

, b5 {" H0 \. S! }1 q& N. K将 config.h 里面被注释掉的两行定义打开,重新编译,此时 TAG 验证能够正常通过。
# ?, r: N: q( b4 O5 u#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */# \/ ~7 b' D9 i
#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */1 G. s) A" l# n
#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */6 m( p7 A: O# k9 G8 S$ ~
, B2 ]! Y' j( w" @+ w4 @( c- ^, E
小结
" C6 H% v- O+ R( C4 H, y4 P' {
简言之,如果使用 X-Cube-Cryptolib 库的话,作为用户就不要改动 config.h 的内容, 不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。
% o. U' `" b: U$ R- T/ Q+ `' Y5 Z) S6 t! U3 M  r( u7 L
收藏 1 评论0 发布时间:2021-9-7 16:48

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版