K210内置了丰富的加速器,包括神经网络处理器 (KPU),AES(高级加密加速器),APU 麦克风阵列语音数据加速计算处理器,现场可编程 IO 阵列 (FPIOA),数字摄像头接口 (DVP),相对于软件可以极大的提高 AES 运算速度,快速傅里叶变换加速器 (FFT),安全散列算法加速器 (SHA256)。
本文介绍高级加密加速器 (AES);
AES是高级加密标准,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,目前已经被全世界广泛使用,同时AES已经成为对称密钥加密中最流行的算法之一。AES支持三种长度的密钥:128位,192位,256位。
AES加密算法涉及4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。下图给出了AES加解密的流程,从图中可以看出:
1、解密算法的每一步分别对应加密算法的逆操作;
2、加解密所有操作的顺序正好是相反的。正是由于这几点(再加上加密算法与解密算法每步的操作互逆)保证了算法的正确性。加解密中每轮的密钥分别由种子密钥经过密钥扩展算法得到。算法中16字节的明文、密文和轮子密钥都以一个4x4的矩阵表示。
AddRoundKey (轮密钥加)— 矩阵中的每一个字节都与该次轮密钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。
SubBytes(字节替代) — 通过非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
ShiftRows(行移位) — 将矩阵中的每个横列进行循环式移位。
MixColumns (列混淆)— 为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节。
AES的加密模式有多种,下面是常用的CNC模式
AES 加速器是用来加密和解密的模块,具体性能如下:
? 支持 ECB,CBC,GCM 三种加密方式
? 支持 128 位,192 位,256 位三种长度的 KEY
? KEY 可以通过软件配置,受到硬件电路保护
? 支持 DMA 传输
K210提供了非常丰富的用户接口,对应的头文件 aes.h
? aes_ecb128_hard_encrypt:AES-ECB-128 加密运算。输入输出数据都使用cpu 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb128_hard_decrypt:AES-ECB-128 解密运算。输入输出数据都使用cpu 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb192_hard_encrypt:AES-ECB-192 加密运算。输入输出数据都使用cpu 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb192_hard_decrypt:AES-ECB-192 解密运算。输入输出数据都使用cpu 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb256_hard_encrypt:AES-ECB-256 加密运算。输入输出数据都使用cpu 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb256_hard_decrypt:AES-ECB-256 解密运算。输入输出数据都使用cpu 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_cbc128_hard_encrypt:AES-CBC-128 加密运算。输入输出数据都使用cpu 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc128_hard_decrypt:AES-CBC-128 解密运算。输入输出数据都使用cpu 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc192_hard_encrypt:AES-CBC-192 加密运算。输入输出数据都使用cpu 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc192_hard_decrypt:AES-CBC-192 解密运算。输入输出数据都使用cpu 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc256_hard_encrypt:AES-CBC-256 加密运算。输入输出数据都使用cpu 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc256_hard_decrypt:AES-CBC-256 解密运算。输入输出数据都使用cpu 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_gcm128_hard_encrypt:AES-GCM-128 加密运算。输入输出数据都使用cpu 传输。
? aes_gcm128_hard_decrypt:AES-GCM-128 解密运算。输入输出数据都使用cpu 传输。
? aes_gcm192_hard_encrypt:AES-GCM-192 加密运算。输入输出数据都使用cpu 传输。
? aes_gcm192_hard_decrypt:AES-GCM-192 解密运算。输入输出数据都使用cpu 传输。
? aes_gcm256_hard_encrypt:AES-GCM-256 加密运算。输入输出数据都使用cpu 传输。
? aes_gcm256_hard_decrypt:AES-GCM-256 解密运算。输入输出数据都使用cpu 传输。
? aes_ecb128_hard_encrypt_dma:AES-ECB-128 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb128_hard_decrypt_dma:AES-ECB-128 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb192_hard_encrypt_dma:AES-ECB-192 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb192_hard_decrypt_dma:AES-ECB-192 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb256_hard_encrypt_dma:AES-ECB-256 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_ecb256_hard_decrypt_dma:AES-ECB-256 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。ECB 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。ECB 模式没有用到向量。
? aes_cbc128_hard_encrypt_dma:AES-CBC-128 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc128_hard_decrypt_dma:AES-CBC-128 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc192_hard_encrypt_dma:AES-CBC-192 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc192_hard_decrypt_dma:AES-CBC-192 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc256_hard_encrypt_dma:AES-CBC-256 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_cbc256_hard_decrypt_dma:AES-CBC-256 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。CBC 加密将明文按照固定大小16bytes 的块进行加密的,块大小不足则进行填充。
? aes_gcm128_hard_encrypt_dma:AES-GCM-128 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。
? aes_gcm128_hard_decrypt_dma:AES-GCM-128 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。
? aes_gcm192_hard_encrypt_dma:AES-GCM-192 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。
? aes_gcm192_hard_decrypt_dma:AES-GCM-192 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。
? aes_gcm256_hard_encrypt_dma:AES-GCM-256 加密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。
? aes_gcm256_hard_decrypt_dma:AES-GCM-256 解密运算。输入数据使用cpu 传输,输出数据都使用dma 传输。
? aes_init:AES 硬件模块的初始化。
? aes_process:AES 硬件模块执行加密解密操作。
? gcm_get_tag:获取AES-GCM 计算结束后的tag。
本实验验证AES的三种模式(ECB/CBC/GCM)并测试他们的加密时间;代码比较多,我这里只贴主函数的代码了,完整代码在我开放的gitee下载
int main(void)
{
aes_cipher_mode_t cipher;
printf("begin test %d\n", get_time_flag);
for (cipher = AES_ECB; cipher < AES_CIPHER_MAX; cipher++)
{
printf("[%s] test all byte ... \n", cipher_name[cipher]);
if (AES_CHECK_FAIL == aes_check_all_byte(cipher))
{
printf("aes %s check_all_byte fail\n", cipher_name[cipher]);
return -1;
}
printf("[%s] test all key ... \n", cipher_name[cipher]);
if (AES_CHECK_FAIL == aes_check_all_key(cipher))
{
printf("aes %s check_all_key fail\n", cipher_name[cipher]);
return -1;
}
printf("[%s] test all iv ... \n", cipher_name[cipher]);
if (AES_CHECK_FAIL == aes_check_all_iv(cipher))
{
printf("aes %s check_all_iv fail\n", cipher_name[cipher]);
return -1;
}
printf("[%s] [%ld bytes] cpu time = %ld us, dma time = %ld us, soft time = %ld us\n", cipher_name[cipher],
AES_TEST_DATA_LEN,
cycle[cipher][AES_HARD][AES_CPU]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000),
cycle[cipher][AES_HARD][AES_DMA]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000),
cycle[cipher][AES_SOFT][AES_CPU]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000));
}
printf("aes-256 test pass\n");
while (1)
;
return 0;
}
代码完成后,进行编译
cd build
cmake .. -DPROJ=aes -G "MinGW Makefiles"
make
编译完成后,在build文件夹下会生成aes.bin文件。
使用type-C数据线连接电脑与K210开发板,打开kflash,选择对应的设备,再将程序固件烧录到K210开发板上。
烧录后重启开发板,实验结果如下:
从实验结果看,AES硬件加速器效果非常明显,比单独使用软件加密更快。