Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread一般讨论
【N32L40XCL-STB 开发板评测】16-安全加密算法评测
发布于 2023-05-06 09:51:00 浏览:257
订阅该版
[tocm] # **1 本章内容** 本章主要以AES和SHA算法为例,介绍算法使用,同时对比基于硬件加速引擎和纯软件算法运算速度的差异。 # **2 测试环境** 开发板:N32L40XCL-STB V1.0 开发环境:Keil 5 RT-Thread版本:5.0.0 # **3 模块介绍** ## 3.1 SAC模块简介 本MCU具有密码算法硬件加速引擎(SAC),支持多种国际算法及国家密码对称密码算法和杂凑密码算法加速,相较于纯软件算法而言能极大的提高加解密速度。 ## 3.2 硬件支持的算法如下: ### 支持 DES对称算法 支持 DES和 3DES加解密运算 TDES支持 2KEY和 3KEY模式 支持 CBC和 ECB模式 ### 支持 AES对称算法 支持 128bit/192bit/ 256bit密钥长度 支持 CBC、 ECB、 CTR模式 ### 支持 SHA摘要算法 支持 SHA1/SHA224/SHA256 ### 支持 MD5摘要算法 支持 MD5摘要算法 ### 支持 国密算法 支持对称式国密 SM1、 SM4、 SM7算法以及 SM3杂凑算法 注: 国民技术SAC模块寄存器目前暂未开发,原厂仅提供基于加速引擎的静态库,通过查看API目前已开放下载的最新版本静态库仅支持AES、DES、TDES、SHA1/224/256、SM3和随机数。 目前已开放下载的最新版本静态库还不支持SM1、SM4和SM7,另外SM1和SM7国密局仅提供IP授权,算法并不开源,暂无有效验证工具。 TinyCrypt组件为RT-Thead官方移植库,API接口简洁明了,使用非常方便。该库目前最新版本暂不支持DES算法,故本例程选择国民技术原厂和TinyCrypt都支持的AES和SHA为例对比硬件加速和纯软件算法的差异。 # **4 创建工程** 由于官方只提供*.lib静态库,故采用ENV构建Keil工程项目。 在RT-Thread源码BSP目录中找到N32 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230506/b02ed3a530004290e04c442d38743b09.png.webp) 拷贝n32l40xcl-stb,重命名为n32l40xcl-stb_algo_test 使用ENV工具,添加以下TinyCrypt组件,由于n32l40x芯片内存较小(20KB),而加解密运算需要较大的缓冲区来做测试,故需将无关的功能配置组件等全部关闭。如外设,仅保留GPIO和UART,其他系统外设全部关闭。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230506/d3cd45e0cee35b5f02b4bbd23f83dc7d.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230506/f9bb847f5bd28c812cb7699003392d7f.png) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230506/d893d69952b88e19e5dfe0fd9e2088b6.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230506/43893dad2abf508f1aec509367e8e227.png) 保存配置,适用pkgs和 scons命令构建工程。 添加algo_test.c ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230506/10173f0d7362c8109ea487bf4b94252d.png) 手动添加国民技术基于SAC模块的算法驱动库。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230506/478eb636e0ada3e6a1421a252e5286bc.png) # **5 编写测试程序程序** ## HASH运算测试方法 1.记录系统tick值 2.读n32 flash 16Byte 3.计算HASH值 4.循环2-3步骤,直到128KB全部计算完成。 5.查询当前系统tick值,计算程序运行时间。 ## AES加解密测试方法 1.记录系统tick值 2.读n32 flash 16Byte 3.AES128_ECB 加密16Byte, ECB解密,解密后与明文比较 4.循环2-3步骤,直到128KB全部解密。 5.查询当前系统tick值,计算程序运行时间。 注:官方提供的AES API适用并不友好,参考TinyCrypt中AES API做了二次封装。 ## SHA1代码: ```c /** * @brief SHA1 algorithm test code * @param none * @return none * @note HASH operation test method * 1. Record the system tick value * 2. Read n32 flash R_FLASH_LEN Byte * 3. Calculate the HASH value * 4. Cycle steps 2-3 until the 128KB calculation is complete. * 5. Query the current system tick value and calculate the program running time. */ void sha1(void) { rt_tick_t tick ,tick_1,tick_2; tiny_sha1_context ctx; HASH_CTX n32sac_ctx; uint8_t output[20]; uint32_t pos = 0; uint32_t num = N32_FLASH_SIZE/R_FLASH_LEN ; rt_kprintf("\nTinyCrypt SHA1 Test\n"); tick_1 = rt_tick_get(); tiny_sha1_starts(&ctx ); pos = 0; for (int var = 0; var < num; ++var) { if (n32_flash_read(N32_FLASH_START_ADRESS+pos, databuf, R_FLASH_LEN) < 0) { rt_kprintf("read flash error !!! \n"); return; } else { tiny_sha1_update(&ctx, databuf, R_FLASH_LEN); pos += R_FLASH_LEN ; } } tiny_sha1_finish(&ctx, output); tick_2 = rt_tick_get(); memset(&ctx, 0, sizeof(tiny_sha1_context)); tick = tick_2 - tick_1 ; rt_kprintf("start systick:%dms \n", tick_1); rt_kprintf("finish systick:%dms \n", tick_2); rt_kprintf("data len :%dByte,time:%dms \n", N32_FLASH_SIZE,tick); rt_kprintf("SHA1 HASH:%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", output[0],output[1],output[2],output[3],output[4],output[5],output[6],output[7], output[8],output[9],output[10],output[11],output[12],output[13],output[14],output[15], output[16],output[17],output[18],output[19]); n32sac_ctx.hashAlg = HASH_ALG_SHA1; n32sac_ctx.sequence = HASH_SEQUENCE_FALSE; rt_kprintf("\nN32L4_SAC SHA1 Test\n"); tick_1 = rt_tick_get(); if (HASH_Init_OK != HASH_Init(&n32sac_ctx)) { rt_kprintf("N32L4_SAC HASH_Init failed.\n"); return; } if (HASH_Start_OK != HASH_Start(&n32sac_ctx)) { rt_kprintf("N32L4_SAC HASH_Start failed.\n"); return; } pos = 0; for (int var = 0; var < num; ++var) { if (n32_flash_read(N32_FLASH_START_ADRESS+pos, databuf, R_FLASH_LEN) < 0) { rt_kprintf("read flash error !!! \n"); return; } else { if (HASH_Update_OK != HASH_Update(&n32sac_ctx, (uint8_t*)databuf, R_FLASH_LEN)) { rt_kprintf("N32L4_SAC HASH_Update failed.\n"); return; } else { pos += R_FLASH_LEN ; } } } if (HASH_Complete_OK != HASH_Complete(&n32sac_ctx, output)) { rt_kprintf("N32L4_SAC HASH_Complete failed.\n"); return; } tick_2 = rt_tick_get(); memset(&n32sac_ctx, 0, sizeof(HASH_CTX)); tick = tick_2 - tick_1 ; rt_kprintf("start systick:%dms \n", tick_1); rt_kprintf("finish systick:%dms \n", tick_2); rt_kprintf("data len :%dByte,time:%dms \n", N32_FLASH_SIZE,tick); rt_kprintf("SHA1 HASH:%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", output[0],output[1],output[2],output[3],output[4],output[5],output[6],output[7], output[8],output[9],output[10],output[11],output[12],output[13],output[14],output[15], output[16],output[17],output[18],output[19]); } ``` ## AES代码: ```c /** * @brief AES algorithm test code * @param none * @return none * @note AES Encryption and decryption test method * 1. Record the tick value of the system * 2. Read n32 flash 16Byte * 3. AES128_ECB encrypts 16Byte, decrypts ECB, and compares with plaintext after decryption * 4. Repeat steps 2-3 until all 128KB is decrypted. * 5. Query the tick value of the current system and calculate the program running time. */ void aes(void) { rt_tick_t tick ,tick_1,tick_2; tiny_aes_context ctx; AES_PARM AES_Parm; uint8_t key[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; //uint8_t iv[16]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; uint8_t plain[16]={0};// uint8_t cipher[16]={0};// uint8_t plainOut[16]={0};// #if DBG_AES uint32_t num = 4 ; #else uint32_t num = N32_FLASH_SIZE/16 ; #endif uint32_t pos = 0; rt_kprintf("\nTinyCrypt AES128_ECB Test\n"); tick_1 = rt_tick_get(); pos = 0; for (int var = 0; var < num; ++var) { if (n32_flash_read(N32_FLASH_START_ADRESS+pos, plain, 16) < 0) { rt_kprintf("read flash error !!! \n"); return; } else { tiny_aes_setkey_enc(&ctx, key, 128); tiny_aes_crypt_ecb(&ctx,AES_ENCRYPT,plain, cipher); tiny_aes_setkey_dec(&ctx, key, 128); tiny_aes_crypt_ecb(&ctx,AES_DECRYPT,cipher, plainOut); #if DBG_AES rt_kprintf("key = "); DumpBytes(key, sizeof(key)); rt_kprintf("\n"); rt_kprintf("plain = "); DumpBytes(plain, sizeof(plain)); rt_kprintf("\n"); rt_kprintf("cipher = "); DumpBytes(cipher, sizeof(cipher)); rt_kprintf("\n"); rt_kprintf("decrypt out = "); DumpBytes(plainOut, sizeof(plainOut)); rt_kprintf("\n"); #endif if(memcmp(plain,plainOut,16)==0) { pos += 16 ; } else { rt_kprintf("tiny aes crypt error !!! \n"); return; } } } if (memcmp(plain, plainOut, sizeof(plain)) != 0) { rt_kprintf("AES decrypt result do not equal plain data.\n"); return; } tick_2 = rt_tick_get(); tick = tick_2 - tick_1 ; rt_kprintf("start systick:%dms \n", tick_1); rt_kprintf("finish systick:%dms \n", tick_2); rt_kprintf("data len :%dByte,time:%dms \n", N32_FLASH_SIZE,tick); rt_kprintf("\nN32L4_SAC AES128_ECB Test\n"); tick_1 = rt_tick_get(); pos = 0; for (int var = 0; var < num; ++var) { if (n32_flash_read(N32_FLASH_START_ADRESS+pos, plain, 16) < 0) { rt_kprintf("read flash error !!! \n"); return; } else { AES_SetKey_Enc(&AES_Parm, key, 128); AES_Crypt_ECB(&AES_Parm,AES_ENCRYPT,plain, cipher); AES_SetKey_Dec(&AES_Parm, key, 128); AES_Crypt_ECB(&AES_Parm,AES_DECRYPT,cipher, plainOut); #if DBG_AES rt_kprintf("key = "); DumpBytes(key, sizeof(key)); rt_kprintf("\n"); rt_kprintf("plain = "); DumpBytes(plain, sizeof(plain)); rt_kprintf("\n"); rt_kprintf("cipher = "); DumpBytes(cipher, sizeof(cipher)); rt_kprintf("\n"); rt_kprintf("decrypt out = "); DumpBytes(plainOut, sizeof(plainOut)); rt_kprintf("\n"); #endif if(memcmp(plain,plainOut,16)==0) { pos += 16 ; } else { rt_kprintf("tiny aes crypt error !!! \n"); return; } } } tick_2 = rt_tick_get(); tick = tick_2 - tick_1 ; rt_kprintf("start systick:%dms \n", tick_1); rt_kprintf("finish systick:%dms \n", tick_2); rt_kprintf("data len :%dByte,time:%dms \n", N32_FLASH_SIZE,tick); } ``` ## AES 重新封装代码: ```c /** * @brief AES key schedule (encryption) * @param[in] parm pointer to AES context and the detail please refer to struct AES_PARM in n32l40x_aes.h * @param[in] key encryption key * @param[in] keysize must be 128, 192 or 256 * @return none */ void AES_SetKey_Enc(AES_PARM *parm, unsigned char *key, int keysize) { parm->key = (uint32_t*)key; parm->iv = NULL; // IV is not needed in ECB mode switch (keysize) { case 128: parm->keyWordLen = 4; break; case 192: parm->keyWordLen = 6; break; case 256: parm->keyWordLen = 8; break; default: return; } parm->Mode = AES_ECB; parm->En_De = AES_ENC; } /** * @brief AES key schedule (decryption) * @param[in] parm pointer to AES context and the detail please refer to struct AES_PARM in n32l40x_aes.h * @param[in] key encryption key * @param[in] keysize must be 128, 192 or 256 * @return none */ void AES_SetKey_Dec(AES_PARM *parm, uint8_t *key, uint32_t keysize) { parm->key = (uint32_t*)key; parm->iv = NULL; // IV is not needed in ECB mode switch (keysize) { case 128: parm->keyWordLen = 4; break; case 192: parm->keyWordLen = 6; break; case 256: parm->keyWordLen = 8; break; default: return; } parm->Mode = AES_ECB; parm->En_De = AES_DEC; } /** * @brief AES-ECB block encryption/decryption * @param[in] parm pointer to AES context and the detail please refer to struct AES_PARM in n32l40x_aes.h * @param[in] mode AES_ENCRYPT or AES_DECRYPT * @param[in] input 16-byte input block * @param[out] output 16-byte output block * @return none */ void AES_Crypt_ECB(AES_PARM *parm, uint32_t mode, uint8_t input[16], uint8_t output[16]) { parm->inWordLen = 4; parm->in = (uint32_t*)input; parm->out = (uint32_t*)output; if (AES_Init_OK != AES_Init(parm)) { rt_kprintf("N32L4_SAC AES_Init failed.\n"); return; } if (AES_Crypto_OK != AES_Crypto(parm)) { rt_kprintf("N32L4_SAC AES_Crypto failed\n"); return; } } ``` # **6 测试数据** |序号|算法|数据长度|纯软件算法|硬件加速器|备注 |1|SHA1|128KB|95ms|75ms|含读flash等和打日志时间 |2|SHA224|128KB|162ms|65ms|含读flash等和打日志时间 |3|SHA256|128KB|161ms|65ms|含读flash等和打日志时间 |4|AES128|128KB|1202ms|239ms|含读flash等和打日志以及ECB加密和解密的时间 # **7 章节总结** 从测试数据上对比,执行相同的密码运算基于硬件加速引擎速度远远大于纯软件算法。尤其是进行大量数据加解密运算时差异较大。 # ** 8 代码路径** https://gitee.com/hawkros/n32_sac.git
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
iotgeek
这家伙很懒,什么也没写!
文章
4
回答
0
被采纳
0
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部