使用基于STM32 AES GCM的加密算法库的技巧

2021-09-24 15:35 来源:电子说

X-CUBE-CRYPTOLIB是一个基于STM32的Crypto算法库,支持对称密钥、非对称密钥、哈希等多种算法。正确使用Cyrptolib算法库可以实现应用层所需的数据加密、设备身份认证、加密通信等诸多安全功能。相反,如果算法库使用不正确,往往会导致数据加解密错误等一系列问题。

STM32 Crypto算法库应用中常见的问题之一是应用程序没有启用MCU的CRC模块。虽然输出数据与期望值不同,但对加密和解密函数的调用不会返回异常。本文描述了算法库使用不正确的另一种情况。

问题描述

在客户应用程序项目中,固件需要在固件更新过程中进行加密和验证。根据推荐,采用AES- GCM算法完成该任务。下载的固件通过带有TAG的AES-GCM加密,可用于验证固件源的有效性。使用X-Cube-Cryptolib在项目的代码中执行AES-GCM操作。上位机使用cryptopp820加密库对固件目标bin文件进行加密,然后在MCU上通过AES-GCM128使用X-Cube- Cryptolib加密库对固件目标bin文件进行解密。解密数据没有问题,但是TAG数据总是无法验证。

问题分析和定位。

正常情况下,当调用AES _ GCM _ decrypt _ finish(P _ paesgcmtx,NULL,P_pOutputSize)时;执行后,AESctx.mFlags结果会提示验证是否通过。如果验证成功,该值应等于0x22,但在运行结果中可以看到0x12。

确认如何使用库函数。

在X-Cube-Cryptolib中的一个简单测试程序的环境下测试调用AES-GCM函数的代码,看看有没有问题。结果表明,测试程序中的AES-GCM验证可以成功,但集成到客户应用程序中就不能成功。然后我们将关注应用程序环境。

应用环境

该应用程序使用FreeRTOS,基于IAR编译环境。

检查库文件的使用情况。

验证是否使用了正确的库文件。

确认是否有多线程访问。

AES-GCM的函数会在几个线程中调用,确认不会同时调用,不存在提升条件问题。

检查内存使用情况。

最初,我想知道这是否是由任务堆栈溢出引起的,所以我检查了内存使用情况。IAR堆栈大小:0x4800

IAR堆大小:0x4000

自由实时操作系统堆大小:85KB

执行AES操作的线程堆栈大小:2560B。

查看FreeRTOS的uxTaskGetStackHighWaterMark()函数,可以看到线程还有大约500字节的剩余空间。

AESGCMctx_stt结构的大小为2360字节,AES-GCM加解密功能所需的堆栈大小约为450字节。但是,这个变量在应用程序代码中被定义为全局变量,这样就可以在几个不同的线程中使用,从而可以确认线程堆栈大小和堆栈溢出没有问题。

查看。生成代码的映射文件。

相比之下,图中cryptolib中所有符号的大小都是正常的,唯一的问题是AESGCMctx _ stt结构变量的大小。应用程序代码。map:AES CTX0x 2002 f1 f 40 x8f 8 data GB AES _ GCM _ decrypt . o[1]。

测试代码。地图:AES CTX0x20002e640x938数据GB AES _ GCM。o [1]。

但是,验证问题应该与这个结构的数据直接相关。接下来,我们将研究是什么导致了这种差异。

查看项目使用的加密库头文件。

经检查,在config.h的定义中注释了宏定义INCLUDE_AES192和INCLUDE_AES256,这将导致aes_gcm.h中AESGCMctx_stt数据结构的成员变量uint 32 _ t am ex pkey[CRL _ AES _ max _ ex pkey _ size];的大小已更改,因为CRL_AES_MAX_EXPKEY_SIZE的定义会因是否在INCLUDE_AES128/192/256中定义而有所不同。

//#定义INCLUDE _ DES((uint 16 _ t)0x 0001)/*!《DES》函数》包含在库中。*///#定义INCLUDE _ TDES((uint 16 _ t)0x 0002)/*!《三元组(TDES)函数》包含在库中。*/#定义INCLUDE _ AES 128((uint 16 _ t)0x 0004)/*!该库中包含了密钥大小为128位的俄歇电子能谱函数。*///#定义INCLUDE _ AES 192((uint 16 _ t)0x 0008)/*!该库中包含了密钥大小为192位的俄歇电子能谱函数。*///#定义INCLUDE _ AES 256((uint 16 _ t)0x 0010)/*!该库中包含了密钥大小为256位的俄歇电子能谱函数。*///#定义INCLUDE _ ARC 4((uint 16 _ t)0x 0020)/*!《ARC4》函数》包含在库中*///#定义INCLUDE _ CHACHA((uint 16 _ t)0x 0040)/*!《插茶》的功能都包含在库中。*///#定义INCLUDE _ chacha 20 poly 1305((uint 16 _ t)0x 0080)/*!《奥林匹克1305- AES》函数包含在库中*/

问题解决

将config.h里面被注释掉的两行定义打开,重新编译,此时标签验证能够正常通过#定义INCLUDE _ AES 128((uint 16 _ t)0x 0004)/*!该库中包含了密钥大小为128位的俄歇电子能谱函数。*/#定义INCLUDE _ AES 192((uint 16 _ t)0x 0008)/*!该库中包含了密钥大小为192位的俄歇电子能谱函数。*/#定义INCLUDE _ AES 256((uint 16 _ t)0x 0010)/*!该库中包含了密钥大小为256位的俄歇电子能谱函数。*/

小结

简言之,如果使用立方体密码库库的话,作为用户就不要改动config.h的内容,不可想当然地自行调整配置。其实,库是预先编译好了的,所有的功能都已经包含,只是链接的时候根据用户使用到的函数去链接最终的目标文件。

这个客户就是按照以为关闭某些配置可以节省代码空间的想法,贸然注释掉了他以为自己不需要的功能,造成数据结构大小发生变化等,影响加密库的正常使用。

延伸 · 阅读