开发板

K210开发板

基于K210开发板高级加密加速器测试_输入输出

实验目的

本次测试主要学习 K210 芯片中的高级加密加速器 AES 的功能。

实验准备

实验元件

K210 芯片中的高级加密加速器 AES

元件特性

K210 内置 AES(高级加密加速器),相对于软件可以极大的提高 AES 运算速度。AES 加 速 器 支 持 多 种 加 密 / 解 密 模 式 (ECB,CBC,GCM), 多 种 长 度 的KEY(128,192,256)的运算。 AES 加速器是用来加密和解密的模块,具体性能如下:

  • 支持 ECB,CBC,GCM 三种加密方式
  • 支持 128 位,192 位,256 位三种长度的 KEY
  • KEY 可以通过软件配置,受到硬件电路保护
  • 支持 DMA 传输

SDK 中对应 API 功能

以头文件 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,Advanced Encryption Standard)为最常见的对称加密算法。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图

基于K210开发板高级加密加速器测试_ci_02

  1. 明文 P:没有经过加密的数据。
  2. 密钥 K:用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。不可泄露。
  3. 密文 C:经过加密处理后的数据。
  4. AES 解密函数:解密的具体实现方法,输入密文,还原出明文。
  5. AES-GCM 模式,Galois/Counter Mode :提供对消息的加密和完整性校验。
  6. AES-ECB 模式,Electronic Codebook Book 电子密码本模式:将整个明文分成若干相同的组,然后对每一组进行加密。
  7. AES-CBC 模式,Cipher Block Chaining 密码分组链接模式:将明文切分成若干个组,每个小组与初始组或者上一组的密文组进行异或运算,再与密钥进行加密。

实验过程

  1. 通过一个 for 循环,把 AES 的三种模式(ECB/CBC/GCM)对应的时间打印出来。
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));
    }
  1. AES 检测所有 byte。
check_result_t aes_check_all_byte(aes_cipher_mode_t cipher)
{
    uint32_t check_tag = 0;
    uint32_t index = 0;
    size_t data_len = 0;
    memset(aes_hard_in_data, 0, AES_TEST_PADDING_LEN);
    if (cipher == AES_GCM)
        iv_len = iv_gcm_len;
    for (index = 0; index < (AES_TEST_DATA_LEN < 256 ? AES_TEST_DATA_LEN : 256); index++)
    {
        aes_hard_in_data[index] = index;
        data_len++;

        AES_DBG("[%s] test num: %ld \n", cipher_name[cipher], data_len);
        if (aes_check(aes_key, key_len, aes_iv, iv_len, aes_aad, aad_len, cipher, aes_hard_in_data, data_len)
            == AES_CHECK_FAIL)
            check_tag = 1;
    }

    memset(aes_hard_in_data, 0, AES_TEST_PADDING_LEN);
    get_time_flag = 1;
    data_len = AES_TEST_DATA_LEN;
    AES_DBG("[%s] test num: %ld \n", cipher_name[cipher], data_len);
    for (index = 0; index < data_len; index++)
        aes_hard_in_data[index] = index % 256;
    if (aes_check(aes_key, key_len, aes_iv, iv_len, aes_aad, aad_len, cipher, aes_hard_in_data, data_len)
        == AES_CHECK_FAIL)
        check_tag = 1;
    get_time_flag = 0;
    if(check_tag)
        return AES_CHECK_FAIL;
    else
        return AES_CHECK_PASS;
}
  1. AES 检测所有 key。
check_result_t aes_check_all_key(aes_cipher_mode_t cipher)
{
    size_t data_len = 0;
    uint32_t index = 0;
    uint32_t i = 0;
    uint32_t check_tag = 0;

    memset(aes_hard_in_data, 0, AES_TEST_PADDING_LEN);
    if (cipher == AES_GCM)
        iv_len = iv_gcm_len;
    data_len = AES_TEST_DATA_LEN;
    for (index = 0; index < data_len; index++)
        aes_hard_in_data[index] = index;
    for (i = 0; i < (256 / key_len); i++)
    {
        for (index = i * key_len; index < (i * key_len) + key_len; index++)
            aes_key[index - (i * key_len)] = index;
        if (aes_check(aes_key, key_len, aes_iv, iv_len, aes_aad, aad_len, cipher, aes_hard_in_data, data_len)
            == AES_CHECK_FAIL)
            check_tag = 1;
    }
    if(check_tag)
        return AES_CHECK_FAIL;
    else
        return AES_CHECK_PASS;
}
  1. AES 检测所有 IV
check_result_t aes_check_all_iv(aes_cipher_mode_t cipher)
{
    size_t data_len = 0;
    uint32_t index = 0;
    uint32_t i = 0;
    uint8_t check_tag = 0;

    memset(aes_hard_in_data, 0, AES_TEST_PADDING_LEN);
    if (cipher == AES_GCM)
        iv_len = iv_gcm_len;
    data_len = AES_TEST_DATA_LEN;
    for (index = 0; index < data_len; index++)
        aes_hard_in_data[index] = index;
    for (i = 0; i < (256 / iv_len); i++)
    {
        for (index = i * iv_len; index < (i * iv_len) + iv_len; index++)
            aes_iv[index - (i * iv_len)] = index;
        if (aes_check(aes_key, key_len, aes_iv, iv_len, aes_aad, aad_len, cipher, aes_hard_in_data, data_len)
            == AES_CHECK_FAIL)
            check_tag = 1;
    }
    if(check_tag)
        return AES_CHECK_FAIL;
    else
        return AES_CHECK_PASS;
}
  1. 编译调试,烧录运行 进入自己项目 build目录,运行以下命令编译。
cmake .. -DPROJ=watchdog -G "MinGW Makefiles"
make

实验现象

烧录固件完成后,系统会自动弹出一个终端窗口,并且打印出 AES 的 ECB 模=式、CBC 模式和 GCM 模式对数据加密处理的时间,包括软件和硬件的对比时间,CPU 和 DMA 使用的是硬件的 AES。

基于K210开发板高级加密加速器测试_数据_03

实验总结

  • AES 加密算法分为多种模式,每种模式的加密方式不同。
  • AES 硬件加速器比单独使用软件加密更省时间。