5.2 ALGO 使用说明
本章说明 N32H49x 密码算法库(ALGO)的文件组成与接口来源,以及 ALGO_DEMO 示例。算法库以硬件加密算法加速引擎(SAC)为基础,其支持的算法清单、密钥长度与工作模式请配合用户手册的“密码算法硬件加速引擎(SAC)”章节阅读。
5.2.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32h49x_algo_lib/keil/inc/ |
Keil 版头文件目录:n32h49x_algo_common.h、n32h49x_aes.h、n32h49x_des.h、n32h49x_hash.h、n32h49x_rng.h、n32h49x_sm4.h,声明公共辅助、AES、DES/3DES、杂凑、随机数与 SM4 接口 |
firmware/n32h49x_algo_lib/keil/lib/ |
Keil 版预编译库:n32h49x_common.lib、n32h49x_aes.lib、n32h49x_des.lib、n32h49x_hash.lib、n32h49x_rng.lib、n32h49x_sm4.lib |
firmware/n32h49x_algo_lib/gcc/ |
GCC 版目录:inc/ 下为同名 6 个头文件,lib/ 下为 Common.a、AES.a、DES.a、HASH.a、RNG.a、SM4.a |
projects/n32h49x_EVAL/examples/ALGO/ |
ALGO 示例根目录,含 ALGO_DEMO 1 个示例 |
projects/n32h49x_EVAL/examples/ALGO/ALGO_DEMO/ |
ALGO_DEMO 示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32h49x_EVAL/bsp/ |
该示例使用的板级支持文件:日志初始化与打印串口重映射 |
5.2.2 API 参考
ALGO 是随 SDK 提供的预编译密码算法库,没有标准外设驱动那样的 inc/src 源文件,接口只以头文件加预编译库的形式提供,都放在 firmware/n32h49x_algo_lib/ 下。库按工具链分两套:Keil 版头文件在 keil/inc/、库文件在 keil/lib/(n32h49x_common.lib、n32h49x_aes.lib、n32h49x_des.lib、n32h49x_hash.lib、n32h49x_rng.lib、n32h49x_sm4.lib);GCC 版头文件在 gcc/inc/、库文件在 gcc/lib/(Common.a、AES.a、DES.a、HASH.a、RNG.a、SM4.a)。两套头文件同名,工程中按所用工具链把对应的 inc/ 加入头文件搜索路径、把对应的 lib/ 加入库路径即可。公开入口按头文件分组如下:
n32h49x_algo_common.h:RandomSort、Cpy_U8、Cpy_U32、XOR_U8、XOR_U32、SetZero_U8、SetZero_U32、ReverseBytesInWord_U32、Cmp_U32、Cmp_U8,以及返回值枚举Cpy_OK、SetZero_OK、XOR_OK、Reverse_OK、Cmp_EQUAL、Cmp_UNEQUAL。n32h49x_sm4.h:SM4_Init、SM4_Crypto、SM4_Close、SM4_Version,以及参数结构体SM4_PARM与工作模式、加解密方向宏SM4_ECB、SM4_CBC、SM4_ENC、SM4_DEC。n32h49x_aes.h:AES_Init、AES_Crypto、AES_Close、AES_Version,以及参数结构体AES_PARM与工作模式、加解密方向宏AES_ECB、AES_CBC、AES_CTR、AES_ENC、AES_DEC。n32h49x_des.h:DES_Init、DES_Crypto、DES_Close、DES_Version,以及参数结构体DES_PARM。n32h49x_hash.h:分段接口HASH_Init、HASH_Start、HASH_Update、HASH_Complete、HASH_Close,一次性接口SM3_Hash、SHA1_Hash、SHA224_Hash、SHA256_Hash、MD5_Hash,以及HASH_Version、上下文结构体HASH_CTX与算法描述表HASH_ALG_SHA1、HASH_ALG_SHA224、HASH_ALG_SHA256、HASH_ALG_MD5、HASH_ALG_SM3。n32h49x_rng.h:GetPseudoRand_U32、GetTrueRand_U32、RNG_Version。
对称算法都按“初始化 → 运算 → 关闭”三步使用:先 XXX_Init 把密钥、明文或密文、工作模式等填入参数结构体,再 XXX_Crypto 完成一次加解密,最后 XXX_Close 释放;同一个参数结构体改一下方向字段就能复用。杂凑算法既可用 HASH_Init/HASH_Start/HASH_Update/HASH_Complete/HASH_Close 分段喂数据,也可用 SM3_Hash、MD5_Hash 这类一次性接口。各模块的库版本通过 SM4_Version、AES_Version、DES_Version、HASH_Version、RNG_Version 读取。
5.2.3 Demo 示例说明
本节说明 ALGO 的 1 个示例:ALGO_DEMO 用一组固定的测试向量依次跑通库中每种算法,并把每项结果与预期值比对。
5.2.3.1 ALGO_DEMO 算法库综合演示
工程目录: projects/n32h49x_EVAL/examples/ALGO/ALGO_DEMO/
初始化日志串口并把接口与算法工作时钟都分频到 120 MHz→依次跑通 SM4、AES、DES 等对称算法与摘要算法→每项结果与预期向量比对并打印 success 或 fail→再取伪随机数与真随机数并打印→全部通过后打印统一提示并停留在主循环
| 项目 | 源码解读 |
|---|---|
| 功能 | 以一组固定的测试向量演示密码算法库的完整调用流程; 依次执行 SM4、AES128/192/256、DES、2KEY/3KEY 3DES 的加解密,以及 SHA、SM3、MD5 摘要与随机数取用,并把每项结果与预期值比对。 |
| 源码组成 | src/main.c:main 与各算法测试函数的声明;src/algo_demo.c:SM4_test、AES_128_test、DES_test、HASH_test、MD5_test 等测试函数与 TestRand 的实现;inc/algo_demo.h、inc/n32h47x_48x_it.h:函数声明与中断头文件;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。 |
| 关键配置 | 时钟源为 HSI+PLL; 接口时钟与算法工作时钟都按 2 分频配置为 120 MHz,算法库不支持 240 MHz 主频; 打印串口为 PA9,波特率 115200。 |
| 程序与数据路径 | main 先调用 log_init,再把接口时钟与算法工作时钟分频到 120 MHz,随后依次调用各算法测试函数与 TestRand;每个测试函数把输入、密钥与工作模式填入参数结构体,经初始化与运算接口得到结果,再用 Cmp_U32 与预期数组比对。 |
| 主要 API | SM4_Init、SM4_Crypto、SM4_Close、AES_Init、AES_Crypto、DES_Init、DES_Crypto、HASH_Init、HASH_Update、HASH_Complete、GetPseudoRand_U32、GetTrueRand_U32 |
| 验证方法 | 复位运行后串口打印 Algorithm demo start.;每项算法通过时打印对应的 ...-Test success,失败时打印 ...-Test fail 并返回 0x5A5A5A5A;全部通过后打印 ALGO demo all test OK!。 |
| 使用提示 | 算法库的预编译库分 Keil 与 GCC 两套,Keil 工程用 n32h49x_*.lib,IAR/GCC 工程用 *.a;算法库不支持 240 MHz 主频,必须把系统时钟 2 分频到 120 MHz 后再调用; 测试失败时各测试函数返回 0x5A5A5A5A。开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例把库文件按工具链加入工程后,用一组固定测试向量依次验证库中每种算法,并把结果与预期值比对。
数据路径: main 配置接口时钟与算法工作时钟 → 各测试函数把密钥、明文与工作模式填入参数结构体 → 初始化与运算接口完成加解密或摘要 → Cmp_U32 与预期数组比对并返回成功或失败 → TestRand 取伪随机与真随机数
1. 先分频时钟再按顺序调用各算法。 算法库要求接口时钟与算法工作时钟都不超过 120 MHz,示例统一在调用算法前把两者都 2 分频。
int main(void)
{
log_init();
log_info("-----------------------\nAlgorithm demo start.\n");
/* config interface clock is 120MHz */
RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2);
/* config work clock is 120MHz(must not exceed interface clock) */
RCC_ConfigRngcClk(RCC_RNGCCLK_SYSCLK_DIV2);
RCC_ConfigPeriphClk(RCC_PERIPH_HCLK_DIV2) 把接口时钟降为 HCLK 的一半,RCC_ConfigRngcClk(RCC_RNGCCLK_SYSCLK_DIV2) 把算法工作时钟也降到系统时钟的一半。
2. 把参数填入结构体后三步调用对称算法。 输入的明文先拷到输出缓冲区(原地加解密),再逐项填好密钥、长度、工作模式与方向字段。
Cpy_U32(out, in1, 32);
SM4_Parm.in = out;
SM4_Parm.key = key1;
SM4_Parm.out = out;
SM4_Parm.inWordLen = 32;
SM4_Parm.workingMode = SM4_ECB;
SM4_Parm.EnDeMode = SM4_ENC;
ret = SM4_Init(&SM4_Parm);
填好结构体后依次调用 SM4_Init、SM4_Crypto 与 SM4_Close 完成一次运算;解密只需把 EnDeMode 改成 SM4_DEC、CBC 模式再补上 iv,即可复用同一结构体。
3. 用已知测试向量校验结果。 运算返回值与预期数组都要检查:返回值非成功或与预期向量不一致时把标志置为 0x5A5A5A5A。
if(ret != SM4_Crypto_OK)
{
flag1 = 0x5A5A5A5A;
}
else
{
if(Cmp_U32(SM4_ECB_EN, 32, out, 32))
{
flag1 = 0x5A5A5A5A;
}
else
{
flag1 = 0;
}
}
每种模式各生成一个 flagN,最后用 if (flag1 | flag2 | flag3 | flag4) 汇总,任一失败即打印 SM4-Test fail 并返回 0x5A5A5A5A。
4. 取伪随机数与真随机数。 伪随机数需要两个种子字,真随机数直接用硬件熵源,二者都返回 RNG_OK 表示成功。
void TestRand(void)
{
uint32_t buf[8];
uint32_t seed[2] = {1, 2};
uint8_t i;
printf("\n");
if (RNG_OK != GetPseudoRand_U32(buf, 8, seed))
{
printf("GetPseudoRand_U32 failed.\n");
}
else
{
printf("Pseudo random with seed 1,2 success: ");
printf("\n");
}
GetPseudoRand_U32 的第三个参数是长度为 2 的种子数组,改变种子可得到不同序列;GetTrueRand_U32 只按需取的字数调用,用于需要真随机的场合。
对应源码: src/main.c、src/algo_demo.c
5.2.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 硬件支持的对称算法 | 密码算法硬件加速引擎支持的对称算法为 DES/3DES、AES 与 SM4; 算法库只在这些算法范围内提供加解密接口。 |
用户手册 |
| 对称算法的工作模式 | AES 支持 ECB、CBC 与 CTR 三种模式; DES/3DES 与 SM4 支持 ECB 与 CBC 两种模式。 |
用户手册 |
| AES 密钥长度 | AES 支持 128bit、192bit 与 256bit 三种密钥长度; 调用前须按所选长度准备好密钥。 |
用户手册 |
| 3DES 的密钥模式 | TDES 同时支持 2KEY 与 3KEY 两种密钥模式。 | 用户手册 |
| 硬件支持的杂凑与摘要算法 | 硬件支持 SHA1、SHA224、SHA256 三种 SHA 杂凑算法,以及 MD5 摘要算法与 SM3 杂凑算法。 | 用户手册 |
| 随机数生成 | 硬件加速引擎支持随机数生成。 | 用户手册 |
| 算法性能与使用支持 | 密码算法的性能数据与具体使用支持需联系国民技术销售人员; 手册只给出支持的算法与模式,不提供吞吐率数据。 |
用户手册 |