CE 模块主要支持对称算法、非对称算法、摘要算法进行数据的加密和解密功能。
CE 模块主要支持的算法如下:
其menuconfig 的配置如下:
Kernel Setup --->
Drivers Setup --->
SoC HAL Drivers --->
CE devices --->
[*] enable ce driver
[*] enbale ce hal APIs Test command
CE 驱动位于 source/drivers/hal/source/ce/
目录下。
hal/
├── source
│ ├── ce
│ │ ├── ce_common.c # CE公用操作接口函数文件
│ │ ├── ce_common.h # CE操作接口函数头文件
│ │ ├── hal_ce.c # CE底层驱动文件
│ │ ├── hal_ce.h # CE底层驱动头文件
│ │ ├── Makefile
│ │ └── platform.h # 平台配置头文件
| ├── platform
│ └── ce_sun20iw2.h # 具体的平台配置头文件
├── include/hal
└── sunxi_hal_ce.h # CE公用操作接口函数头文件
头文件
#include <sunxi_hal_ce.h>
CE 模块初始化,主要申请中断、clk 初始化等
函数原型:
int sunxi_ce_init(void)
参数:
返回值:
CE 模块去初始化,主要注销中断等
函数原型:
int sunxi_ce_uninit(void)
参数:
返回值:
主要实现对 AES 算法进行加解密
函数原型:
int do_aes_crypto(crypto_aes_req_ctx_t *req_ctx)
参数:
返回值:
typedef struct {
uint8_t *src_buffer;
uint32_t src_length;
uint8_t *dst_buffer;
uint32_t dst_length;
uint8_t *iv;
uint8_t *iv_next;
uint8_t *key;
uint32_t key_length;
__aligned(CACHELINE_LEN) uint8_t padding[AES_BLOCK_SIZE];
uint32_t padding_len;
uint32_t dir; /*0--加密,1--解密*/
uint32_t mode; /*AES算法的模式*/
uint32_t bitwidth;
} crypto_aes_req_ctx_t;
主要实现对HASH 算法进行运算
函数原型:
int do_hash_crypto(crypto_hash_req_ctx_t *req_ctx)
参数:
返回值:
typedef struct {
uint8_t *src_buffer;
uint32_t src_length;
uint8_t *dst_buffer;
uint32_t dst_length;
__aligned(CACHELINE_LEN) uint8_t md[SHA_MAX_DIGEST_SIZE];
uint32_t md_size;
__aligned(CACHELINE_LEN) uint8_t padding[SHA512_BLOCK_SIZE * 2];
uint32_t padding_len;
uint32_t type; /*hash算法的模式*/
uint32_t dir;
uint32_t padding_mode; /*hash算法的填充模式*/
} crypto_hash_req_ctx_t;
主要实现对RSA 算法进行加解密
函数原型:
int do_rsa_crypto(crypto_rsa_req_ctx_t *req_ctx)
参数:
返回值:
typedef struct {
uint8_t *key_n; /*公钥模数*/
uint32_t n_len;
uint8_t *key_e; /*公钥指数*/
uint32_t e_len;
uint8_t *key_d; /*私钥*/
uint32_t d_len;
uint8_t *src_buffer;
uint32_t src_length;
uint8_t *dst_buffer;
uint32_t dst_length;
uint32_t dir; /*0--加密,1--解密*/
uint32_t type; /*RSA算法的模式*/
uint32_t bitwidth; /*RSA算法位宽*/
} crypto_rsa_req_ctx_t;
主要实现随机数的生成
函数原型:
int do_rng_gen(crypto_rsa_req_ctx_t *req_ctx)
参数:
返回值:
typedef struct {
uint8_t *rng_buf;
uint32_t rng_len;
uint32_t mode;
uint8_t *key;
uint32_t key_len;
} crypto_rng_req_ctx_t;
由于测试用例较大,所以将其拆分进入一个头文件内,
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <hal_cmd.h>
#include <hal_mem.h>
#include <sunxi_hal_ce.h>
#include "test_ce.h"
#define AES_MODE_ECB (0)
#define AES_MODE_CBC (1)
#define AES_MODE_CTR (2)
#define AES_MODE_CTS (3)
#define AES_MODE_OFB (4)
#define AES_MODE_CFB (5)
#define AES_DIR_ENCRYPT (0)
#define AES_DIR_DECRYPT (1)
#define HASH_METHOD_MD5 (16)
#define HASH_METHOD_SHA1 (17)
#define HASH_METHOD_SHA224 (18)
#define HASH_METHOD_SHA256 (19)
#define HASH_METHOD_SHA384 (20)
#define HASH_METHOD_SHA512 (21)
void ce_dump(char *str, unsigned char *data, int len, int align) {
i
for (m = AES_MODE_ECB; m < AES_MODE_CFB + 1; m++) {
for (i = 0; i < sizeof(aes_key_len) / sizeof(aes_key_len[0]); i++) {
for (j = 0; j < sizeof(aes_src) / sizeof(aes_src[0]); j++) {
/* aes encrypt */
aes_ctx->src_buffer = aes_src[j];
aes_ctx->src_length = aes_src_len[j];
aes_ctx->key = aes_key[i];
aes_ctx->key_length = aes_key_len[i];
if (m == AES_MODE_ECB)
aes_ctx->iv = NULL;
else
aes_ctx->iv = aes_iv;
if (m == AES_MODE_CTR) {
memset(iv_next, 0, AES_BLOCK_SIZE);
aes_ctx->iv_next = iv_next;
} else
aes_ctx->iv_next = NULL;
if (m == AES_MODE_CFB)
aes_ctx->bitwidth = 8;
else
aes_ctx->bitwidth = 0;
aes_ctx->mode = m;
aes_ctx->dir = AES_DIR_ENCRYPT;
aes_ctx->dst_length = CE_ROUND_UP(aes_ctx->src_length, AES_BLOCK_SIZE);
printf(
"###############AES, mode: %d, ksize %d, src len %d, "
"begin###############\n",
m, aes_key_len[i], aes_src_len[j]);
ret = do_aes_crypto(aes_ctx);
if (ret < 0) {
printf("aes encrypt fail %d\n", ret);
goto out;
}
// for ecb/cbc/cts, enc data len should be 16 bytes aligned
if (m == AES_MODE_ECB || m == AES_MODE_CBC || m == AES_MODE_CTS)
enc_len = aes_ctx->dst_length;
else
enc_len = aes_src_len[j];
// openssl enc do not support cts, so create enc data manually.
if (m == AES_MODE_CTS) {
enc_buffer = (uint8_t *)hal_malloc_align(
enc_len, max(CE_ALIGN_SIZE, CACHELINE_LEN));
if (enc_buffer == NULL) {
printf("malloc ctr buffer fail\n");
ret = -1;
goto out;
}
blk_num = enc_len / AES_BLOCK_SIZE;
if (blk_num > 1) {
if (blk_num > 2)
memcpy(enc_buffer, aes_enc[m - AES_MODE_ECB][i][j],
(blk_num - 2) * AES_BLOCK_SIZE);
memcpy(enc_buffer + (blk_num - 2) * AES_BLOCK_SIZE,
aes_enc[m - AES_MODE_ECB][i][j] +
(blk_num - 1) * AES_BLOCK_SIZE,
AES_BLOCK_SIZE);
memcpy(enc_buffer + (blk_num - 1) * AES_BLOCK_SIZE,
aes_enc[m - AES_MODE_ECB][i][j] +
(blk_num - 2) * AES_BLOCK_SIZE,
AES_BLOCK_SIZE);
} else {
memcpy(enc_buffer, aes_enc[m - AES_MODE_ECB][i][j], enc_len);
}
} else
enc_buffer = aes_enc[m - AES_MODE_ECB][i][j];
if (memcmp(aes_ctx->dst_buffer, enc_buffer, enc_len) != 0) {
ce_dump("want data: ", enc_buffer, enc_len, 16);
ce_dump("calc data: ", aes_ctx->dst_buffer, enc_len, 16);
printf(
"###############AES ENC, mode: %d, ksize %d, src len %d, "
"fail###############\n",
m, aes_key_len[i], aes_src_len[j]);
ret = -1;
goto out;
}
/* aes decrypt */
memset(aes_ctx->dst_buffer, 0x0, aes_ctx->dst_length);
aes_ctx->dir = AES_DIR_DECRYPT;
aes_ctx->src_buffer = enc_buffer;
aes_ctx->src_length = enc_len;
ret = do_aes_crypto(aes_ctx);
if (ret < 0) {
printf("aes decrypt fail %d\n", ret);
goto out;
}
if (memcmp(aes_ctx->dst_buffer, aes_src[j], aes_src_len[j]) != 0) {
ce_dump("want data: ", aes_src[j], aes_src_len[j], 16);
ce_dump("calc data: ", aes_ctx->dst_buffer, aes_src_len[j], 16);
printf(
"###############AES DEC, mode: %d, ksize %d, src len %d, "
"fail###############\n",
m, aes_key_len[i], aes_src_len[j]);
ret = -1;
goto out;
}
if (m == AES_MODE_CTS) {
if (enc_buffer) hal_free_align(enc_buffer);
}
printf(
"###############AES, mode: %d, ksize %d, src len %d, "
"pass###############\n\n\n",
m, aes_key_len[i], aes_src_len[j]);
}
}
}
out:
if (aes_ctx->dst_buffer != NULL) {
hal_free_align(aes_ctx->dst_buffer);
}
if (m == AES_MODE_CTS) {
// goto out;
return ret;
}
FINSH_FUNCTION_EXPORT_CMD(cmd_test_ce, hal_ce, tina rtos ce test demo)