0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【N32L40XCL-STB 开发板评测】安全加密算法评测

冬至子 来源:iotgeek 作者:iotgeek 2023-08-10 16:45 次阅读

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

拷贝n32l40xcl-stb,重命名为n32l40xcl-stb_algo_test
使用ENV工具,添加以下TinyCrypt组件,由于n32l40x芯片内存较小(20KB),而加解密运算需要较大的缓冲区来做测试,故需将无关的功能配置组件等全部关闭。如外设,仅保留GPIO和UART,其他系统外设全部关闭。

1.jpg

1.jpg

保存配置,适用pkgs和 scons命令构建工程。

添加algo_test.c

1.jpg

手动添加国民技术基于SAC模块的算法驱动库。

1.jpg

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代码:
/**

@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 Testn");
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%02Xn",
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 Testn");
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%02Xn",
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代码:
/**

  • @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 Testn");
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 Testn");
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 重新封装代码:
/**

@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 failedn");
return;
}
}

6 测试数据

1.jpg

7 章节总结

从测试数据上对比,执行相同的密码运算基于硬件加速引擎速度远远大于纯软件算法。尤其是进行大量数据加解密运算时差异较大。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • GPIO
    +关注

    关注

    16

    文章

    1139

    浏览量

    50615
  • AES算法
    +关注

    关注

    0

    文章

    11

    浏览量

    7812
  • UART接口
    +关注

    关注

    0

    文章

    123

    浏览量

    15070
  • RT-Thread
    +关注

    关注

    31

    文章

    1151

    浏览量

    38916
  • Flash存储
    +关注

    关注

    0

    文章

    38

    浏览量

    8239
收藏 人收藏

    评论

    相关推荐

    N32L40XCL-STB 开发板评测】SPI接口评测

    N32L40XCL片内集成2个SPI接口,SPI允许芯片与外部设备以半/全双工、同步、串行方式通信。此接口可以被配置成主模式,并为外部从设备提供通信时钟(SCK)。
    发表于 08-11 14:31 538次阅读
    【<b class='flag-5'>N32L40XCL-STB</b> <b class='flag-5'>开发板</b><b class='flag-5'>评测</b>】SPI接口<b class='flag-5'>评测</b>

    N32L40XRQ-STB开发板硬件使用指南

    N32L40XRQ-STB开发板硬件使用指南开发板用于国民技术股份有限公司32位N32L40XRQ系列MCU的开发。本文档详细描述了
    发表于 11-01 06:47

    N32L40XRL-STB开发板硬件使用指南

    N32L40XRL-STB开发板硬件使用指南开发板用于国民技术股份有限公司32位N32L40XRL系列MCU的开发。本文档详细描述了
    发表于 11-01 06:53

    N32L40XML-STB开发板硬件使用指南

    N32L40XML-STB开发板硬件使用指南开发板用于国民技术股份有限公司32位N32L40XML系列MCU的开发。本文档详细描述了
    发表于 11-01 08:27

    N32L40XKQ-STB开发板硬件使用指南

    N32L40XKQ-STB开发板硬件使用指南开发板用于国民技术股份有限公司32位N32L40XKQ系列MCU的开发。本文档详细描述了
    发表于 11-01 08:21

    N32L40XCQ-STB开发板硬件使用指南

    N32L40XCQ-STB开发板硬件使用指南开发板用于国民技术股份有限公司32位N32L40XCQ系列MCU的开发。本文档详细描述了
    发表于 11-01 08:14

    N32G43XCL-STB开发板硬件使用手册

    N32G43XCL-STB开发板用于国民技术股份有限公司高性能32位N32G43XCL系列芯片的样片开发。本文档详细描述了N32G43XCL-STB
    发表于 11-02 06:13

    N32L43XCL-STB开发板硬件使用手册

    N32L43XCL-STB开发板用于国民技术股份有限公司高性能32位N32L43XCL系列芯片的样片开发。本文档详细描述了N32L43XCL-STB
    发表于 11-02 08:10

    N32L40XCL-STB开发板硬件使用手册

    N32L40XCL-STB开发板用于国民技术股份有限公司高性能32位N32L40XCL系列芯片的样片开发。本文档详细描述了N32L40XCL-STB
    发表于 11-02 06:35

    N32G43XCL-STB开发板硬件使用手册

    N32G43XCL-STB开发板用于国民技术股份有限公司高性能32位N32G43XCL系列芯片的样片开发。本文档详细描述了N32G43XCL-STB
    发表于 11-02 08:12

    N32L40XCL-STB (LQFP48) 开发板

    N32L40XCL-STB (LQFP48) 开发板
    发表于 11-10 19:51 1次下载
    <b class='flag-5'>N32L40XCL-STB</b> (LQFP48) <b class='flag-5'>开发板</b>

    N32G43XCL-STB (LQFP48) 开发板

    N32G43XCL-STB (LQFP48) 开发板
    发表于 11-10 19:51 0次下载
    N32G43<b class='flag-5'>XCL-STB</b> (LQFP48) <b class='flag-5'>开发板</b>

    N32L40XCL-STB 开发板模块评测任务大挑战

    评测任务挑战活动,让开发者小伙伴们互相协作,对开发板的每个模块功能进行评测(可以自己外接外设,方式不限),以及编写所需的模块驱动(已有驱动则无需再写),
    的头像 发表于 03-28 03:25 639次阅读

    N32L40XCL-STB开发板模块评测任务大挑战之UART

    本文主要对通过RT-Thread Studio对国民技术开发板N32L40XCL-STB 进行UART外设配置,实现开发板串口功能。
    的头像 发表于 08-09 15:25 527次阅读
    <b class='flag-5'>N32L40XCL-STB</b><b class='flag-5'>开发板</b>模块<b class='flag-5'>评测</b>任务大挑战之UART

    N32L40XCL-STB开发板评测】I2C接口测试

    32L40XCL集成了2个独立的I2C总线接口,它提供多主机功能,控制所有I2C总线特定的时序
    发表于 08-11 14:37 383次阅读
    【<b class='flag-5'>N32L40XCL-STB</b><b class='flag-5'>开发板</b><b class='flag-5'>评测</b>】I2C接口测试