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

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

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

/ W0 q) c) T9 U5 g4 D  ~
引言

8 k1 Y, q/ m' s. l, F; e1 X0 g- c; j/ U% q6 F

6 z/ n( {+ `* dX-CUBE-CRYPTOLIB 是基于 STM32 的 Crypto 算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确地使用 Cyrptolib 算法库,可以在应用程序中实现数据加密、设备身份认证、加密通信等多种应用层所需的安全功能。相反,若不能正确地使用算法库往往会带来加解密数据错误等系列问题。: E, {1 K: d. m* R- L/ [: B% D

0 Q# s  x" f6 K9 o6 j
3 Q( O, d( f0 n) H
关于 STM32 Crypto 算法库应用中的常见的问题之一就是应用程序没有使能 MCU 的CRC 模块,尽管输出的数据和期望值不同,但加解密函数的调用并未返回异常。本文在此描述另外一种没有正确使用算法库的情况。
, [1 }' T* c+ D9 o1 v+ h6 r
$ R: }5 @+ Z3 M/ B; |
问题描述
" n9 h; q9 c# r

  `$ \' ~2 z: {0 Q4 [/ {7 w. Q. R7 l% Z
客户应用项目中需要在固件更新过程中对固件进行加密并验证,根据推荐采用了 AES- GCM 算法完成该任务。下载的固件通过 AES-GCM 进行加密,并带 TAG 可以用于验证固件来源的合法性。在项目的代码中使用 X-Cube-Cryptolib 进行 AES-GCM 运算。上位机使用 cryptopp820 加密库对固件目标 bin 文件进行加密,然后在 MCU 上通过X-Cube- Cryptolib 加密库进行 AES-GCM128 解密,解密数据没有问题,但是 TAG 数据总是无法校验通过。' K3 \; \" m- R7 C& ?, U

; ]; z6 I7 v" L/ I. C7 {% S
问题分析与定位
1 G( }$ Q; M/ s. F+ V5 U

, F( c: y8 x  O
8 n2 Q0 O" l! N, `* Q+ o% M! @正常情况下,当调用 AES_GCM_Decrypt_Finish(P_pAESGCMctx, NULL, P_pOutputSize);执行后,AESctx.mFlags 结果会提示是否通过校验。如果校验成功,该值应该等于 0x22,而运行结果中看到的却是 0x12。: y9 I0 x4 y$ r9 Z% n7 x( Z  F

5 U# O. E: T$ J确认库函数使用方法2 G: v" U$ w5 O" t  Z2 p8 k8 y
将调用 AES-GCM 功能的代码放在 X-Cube-Cryptolib 中一个简单的测试程序的环境进行测试,查看是否有该问题,结果发现测试程序中 AES-GCM 校验是可以成功的,但是集成到客户应用中时就无法成功。那我们接下来重点研究应用程序环境。
4 x' `/ ^( w5 z3 Q2 Z7 j1 J& u9 m1 Z+ M7 [9 p
应用程序环境' P' q) u5 l7 k
应用程序使用了 FreeRTOS,基于 IAR 编译环境。
# G# }# j" v' N5 h3 `) I0 p- n6 s0 {
查看库文件的使用
; m& S. D4 }# x( Z8 L1 @" }7 @* w确认使用了正确的库文件。
# m# g. d" L& o& P, o: O
/ Y6 j' ]! B2 R" t% N% z, ?
确认是否存在多线程访问
" p# |. D+ ]1 J9 P3 \% UAES-GCM 的函数会在几个线程中调用,而且确认不会出现同时调用的情况,不存在 raise condition 的问题。
. J( [+ D( l" ]/ R. O' L# m
( ~: d3 Y7 B+ Q0 ?- z
查看内存使用情况/ R) j: p8 B3 ~  d
最初怀疑是否因为任务栈溢出造成,于是查看内存使用情况。( U7 @. W$ E  v: \; P1 i# s
IAR stack size: 0x4800( K% a, @% K" K/ g% K0 I6 l0 k1 q) B9 A
IAR heap size: 0x4000
9 }) v( p: d$ R# k. A: S; SFreeRTOS heap size: 85KB
8 n( j2 I3 g! a7 Q- I7 k+ a' ^2 H执行AES 运算的线程 stack size: 2560B" x" I% W& F$ E" P# t4 h' j
6 `5 p% Z7 N( d1 I/ `
通过 FreeRTOS 的 uxTaskGetStackHighWaterMark() 函数查看该线程还有 500 字节左右剩余空间。
* r$ \( ~8 i4 e# A* t
9 u4 n8 h, n( L9 m* G. {- gAESGCMctx_stt 结构的大小有 2360 字节,AES-GCM 加解密函数需要的 stack 大小大概在 450 字节左右,但是应用代码中将该变量定义为全局变量,以便可以在几个不同的线程中使用,这样可以确认线程栈大小没有问题,不存在 stack overflow 的问题。6 V7 S+ a% S9 W1 F* ]

; w% H% c5 i; H! {8 M3 M: x5 O查看生成代码的.map 文件
* G; j) s3 |. X通过比较,所有 cryptolib 中的 symbol 在 map 中的大小都正常,唯一有问题的是 AESGCMctx_stt 结构变量的大小。
( |+ i; i# @" b+ g5 t6 A3 ~应用代码.map:AESctx 0x2002f1f4 0x8f8 Data Gb AES_GCM_Decrypt.o [1]% l+ f/ Z8 c7 _" _+ H" S" U7 M! B" ?: x
正常测试代码 .map:AESctx 0x20002e64 0x938 Data Gb AES_GCM.o [1]
: k- p2 w! A! H
$ H0 s0 a. M0 `4 p验证不过的问题应该和这个结构的数据有直接关系,接下来研究是什么造成了这个不同。  n1 e. V; N/ f- M  H. ~

  i6 _7 o( S: u# K7 D查看项目使用的 crypto 库头文件
9 L' u. O" p# T4 P' N+ _0 R% x经检查,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 是否定义会有所不同。1 m8 ~5 Y2 L- b8 m2 Q( h9 S

* i0 a/ W5 l$ Y! f/ [  }

* z( M; Y, @  R1 Z( j5 o2 E) G3 ?//#define INCLUDE_DES ((uint16_t)0x0001) /*!< DES functions are included in the library. */
4 B6 }8 k# P! l( m# `0 H8 N: h//#define INCLUDE_TDES ((uint16_t)0x0002) /*!< TripleDES (TDES) functions are included in the library. */
+ y( \1 ~6 N' U8 x! K& }#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */% H$ n  h5 V1 X  g# O& x  \: @
//#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */4 o6 ]) K) }5 ]2 U' \- ~
//#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */# L8 t1 L8 u' P8 h% F2 O3 @( r
//#define INCLUDE_ARC4 ((uint16_t)0x0020) /*!< ARC4 functions are included in the library. */; e5 M8 X  w% W$ b2 ~  x
//#define INCLUDE_CHACHA ((uint16_t)0x0040) /*!< ChaCha functions are included in the library. */
: {5 e( J0 M; h2 R//#define INCLUDE_CHACHA20POLY1305 ((uint16_t)0x0080) /*!< oly1305- AES functions are included in the library */8 e4 j1 p0 t: `* @; x1 [6 T3 ]1 }
# K6 T7 j3 [0 y( {( h! i4 q; `
问题解决
! A1 W5 x0 A% U; c
& a( r2 T5 V: L+ l) e
将 config.h 里面被注释掉的两行定义打开,重新编译,此时 TAG 验证能够正常通过。6 X2 Q6 {9 j6 P* g8 A' C* F
#define INCLUDE_AES128 ((uint16_t)0x0004) /*!< AES functions with key size of 128 bit are included in the library. */
8 E6 T1 D/ T0 t9 x% T, Z#define INCLUDE_AES192 ((uint16_t)0x0008) /*!< AES functions with key size of 192 bit are included in the library. */
1 M* r* ]; Q4 G: V# \% Z#define INCLUDE_AES256 ((uint16_t)0x0010) /*!< AES functions with key size of 256 bit are included in the library. */
# F& t; G# `3 u: ]( k1 I0 k( H$ H- z9 n. q% |' H9 x9 p
小结
/ d; j" C. I) ?) o  ]; ?5 j- p
简言之,如果使用 X-Cube-Cryptolib 库的话,作为用户就不要改动 config.h 的内容, 不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。" s" _2 K. r* ?  Q2 e

; K' `; c* F" a
收藏 1 评论0 发布时间:2021-9-7 16:48

举报

0个回答

所属标签

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