You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

458 lines
14 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2021. All rights reserved.
* Description: stbm r2r keyladder sample.
* Author: Hisilicon
* Create: 2019-09-19
*/
#include "securec.h"
#include "uapi_system.h"
#include "uapi_memory.h"
#include "uapi_klad.h"
#include "uapi_cipher.h"
#include "parse_config_file.h"
#define klad_err_print_hex(val) printf("[%-32s][line:%04d]%s = 0x%08x\n", __FUNCTION__, __LINE__, #val, val)
#define klad_err_print_info(val) printf("[%-32s][line:%04d]%s\n", __FUNCTION__, __LINE__, val)
#define klad_err_print_val(val) printf("[%-32s][line:%04d]%s = %d\n", __FUNCTION__, __LINE__, #val, val)
#define klad_err_print_point(val) printf("[%-32s][line:%04d]%s = %p\n", __FUNCTION__, __LINE__, #val, val)
#define klad_print_error_code(err_code) \
printf("[%-32s][line:%04d]return [0x%08x]\n", __FUNCTION__, __LINE__, err_code)
#define klad_print_error_func(func, err_code) \
printf("[%-32s][line:%04d]call [%s] return [0x%08x]\n", __FUNCTION__, __LINE__, #func, err_code)
#define KEY_LEN 16
#define DATA_LEN 32
#define td_handle_makehandle(mod, privatedata, chnid) \
(td_handle)((((mod) & 0xff) << 24) | ((((privatedata) & 0xff)<< 16)) | (((chnid) & 0xffff)))
typedef struct {
td_handle handle_klad;
td_handle handle_cipher;
td_handle handle_ks;
} td_handle_klad;
static td_u8 g_data_in[DATA_LEN] = {0};
static td_u8 g_session_key[KEY_LEN] = {0};
static td_u8 g_content_key[KEY_LEN] = {0};
static td_void print_buffer(const td_char *string, const td_u8 *input, td_u32 length)
{
td_u32 i;
if (string != NULL) {
printf("%s\n", string);
}
for (i = 0; i < length; i++) {
if ((i % KEY_LEN == 0) && (i != 0)) {
printf("\n");
}
printf("0x%02x ", input[i]);
}
printf("\n");
return;
}
static td_s32 set_key(td_handle klad)
{
td_s32 ret;
errno_t errno;
uapi_klad_session_key session_key = {0};
uapi_klad_content_key content_key = {0};
session_key.level = UAPI_KLAD_LEVEL1;
session_key.key_size = KEY_LEN;
session_key.alg = UAPI_KLAD_ALG_TYPE_AES;
errno = memcpy_s(session_key.key, UAPI_KLAD_MAX_KEY_LEN, g_session_key, KEY_LEN);
if (errno != EOK) {
klad_print_error_func(memcpy_s, errno);
return TD_FAILURE;
}
ret = uapi_klad_set_session_key(klad, &session_key);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_klad_set_session_key, ret);
return ret;
}
content_key.odd = 0;
content_key.key_size = KEY_LEN;
content_key.alg = UAPI_KLAD_ALG_TYPE_AES;
errno = memcpy_s(content_key.key, UAPI_KLAD_MAX_KEY_LEN, g_content_key, KEY_LEN);
if (errno != EOK) {
klad_print_error_func(memcpy_s, errno);
return TD_FAILURE;
}
ret = uapi_klad_set_content_key(klad, &content_key);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_klad_set_content_key, ret);
return ret;
}
return TD_SUCCESS;
}
static td_s32 cfg_cipher(td_handle cipher, uapi_cipher_symc_alg alg,
uapi_cipher_symc_work_mode mode, const td_u8 *iv, td_u32 iv_len)
{
td_s32 ret;
uapi_cipher_symc_ctrl_t cipher_ctrl = {0};
cipher_ctrl.symc_alg = alg;
cipher_ctrl.work_mode = mode;
if (cipher_ctrl.symc_alg == UAPI_CIPHER_SYMC_ALG_AES) {
cipher_ctrl.symc_key_length = UAPI_CIPHER_SYMC_KEY_128BIT;
cipher_ctrl.symc_bit_width = UAPI_CIPHER_SYMC_BIT_WIDTH_128BIT;
if (iv != TD_NULL) {
cipher_ctrl.iv_change_flag = UAPI_CIPHER_SYMC_IV_CHANGE_ONE_PKG;
cipher_ctrl.iv_length = iv_len;
if (memcpy_s(cipher_ctrl.iv, sizeof(cipher_ctrl.iv), iv, iv_len) != EOK) {
return TD_FAILURE;
}
}
} else if (cipher_ctrl.symc_alg == UAPI_CIPHER_SYMC_ALG_TDES) {
cipher_ctrl.symc_key_length = UAPI_CIPHER_SYMC_KEY_128BIT;
cipher_ctrl.symc_bit_width = UAPI_CIPHER_SYMC_BIT_WIDTH_64BIT;
if (iv != TD_NULL) {
cipher_ctrl.iv_change_flag = UAPI_CIPHER_SYMC_IV_CHANGE_ONE_PKG;
cipher_ctrl.iv_length = iv_len;
if (memcpy_s(cipher_ctrl.iv, sizeof(cipher_ctrl.iv), iv, iv_len) != EOK) {
return TD_FAILURE;
}
}
} else if (cipher_ctrl.symc_alg == UAPI_CIPHER_SYMC_ALG_SM4) {
if (iv != TD_NULL) {
cipher_ctrl.iv_change_flag = UAPI_CIPHER_SYMC_IV_CHANGE_ONE_PKG;
cipher_ctrl.iv_length = iv_len;
if (memcpy_s(cipher_ctrl.iv, sizeof(cipher_ctrl.iv), iv, iv_len) != EOK) {
return TD_FAILURE;
}
}
} else {
return TD_FAILURE;
}
ret = uapi_cipher_symc_set_config(cipher, &cipher_ctrl);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_cipher_symc_set_config, ret);
return ret;
}
return TD_SUCCESS;
}
static td_s32 priv_klad_init(td_handle_klad *klad_handle)
{
td_s32 ret;
uapi_cipher_symc_attr cipher_attr = {0};
ret = uapi_sys_init();
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_sys_init, ret);
return ret;
}
ret = uapi_cipher_symc_init();
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_cipher_init, ret);
goto sys_deinit;
}
ret = uapi_klad_init();
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_klad_init, ret);
goto cipher_deinit;
}
ret = uapi_klad_create(&klad_handle->handle_klad);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_klad_create, ret);
goto klad_deinit;
}
cipher_attr.symc_type = UAPI_CIPHER_SYMC_TYPE_NORMAL;
cipher_attr.symc_alg = UAPI_CIPHER_SYMC_ALG_AES;
cipher_attr.work_mode = UAPI_CIPHER_SYMC_WORK_MODE_CBC;
cipher_attr.is_long_term = TD_TRUE;
ret = uapi_cipher_symc_create(&klad_handle->handle_cipher, &cipher_attr);
if (ret != TD_SUCCESS) {
goto klad_destroy;
}
return TD_SUCCESS;
klad_destroy:
uapi_klad_destroy(klad_handle->handle_klad);
klad_deinit:
uapi_klad_deinit();
cipher_deinit:
uapi_cipher_symc_deinit();
sys_deinit:
uapi_sys_deinit();
return ret;
}
static td_s32 priv_klad_attr(const td_handle_klad *klad_handle)
{
td_s32 ret;
uapi_klad_attr attr_klad = {0};
attr_klad.klad_cfg.owner_id = 0x01;
attr_klad.klad_cfg.klad_type = UAPI_KLAD_TYPE_R2R;
attr_klad.key_cfg.decrypt_support = 1;
attr_klad.key_cfg.encrypt_support = 1;
attr_klad.key_cfg.engine = UAPI_CRYPTO_ALG_RAW_AES;
ret = uapi_klad_set_attr(klad_handle->handle_klad, &attr_klad);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_klad_set_attr, ret);
}
return ret;
}
static td_s32 priv_klad_mem_addr_vir(td_mem_handle *src_handle, td_mem_handle *dst_handle,
td_u8 **input_addr_vir, td_u8 **output_addr_vir)
{
src_handle->addr_offset = 0;
src_handle->mem_handle = uapi_mem_new("cipher_buf_in", strlen("cipher_buf_in"), DATA_LEN, 0);
if (src_handle->mem_handle == 0) {
klad_err_print_info("error: get phyaddr for input failed!\n");
goto out;
}
*input_addr_vir = uapi_mem_map(src_handle->mem_handle, DATA_LEN);
dst_handle->addr_offset = 0;
dst_handle->mem_handle = uapi_mem_new("cipher_buf_out", strlen("cipher_buf_out"), DATA_LEN, 0);
if (dst_handle->mem_handle == 0) {
klad_err_print_info("error: get phyaddr for out_put failed!\n");
goto klad_umem;
}
*output_addr_vir = uapi_mem_map(dst_handle->mem_handle, DATA_LEN);
return TD_SUCCESS;
klad_umem:
if (src_handle->mem_handle > 0) {
uapi_mem_unmap(*input_addr_vir, DATA_LEN);
uapi_mem_delete(src_handle->mem_handle);
}
out:
return TD_FAILURE;
}
static td_void priv_klad_unmem_addr_vir(const td_mem_handle *src_handle, const td_mem_handle *dst_handle,
td_u8 *input_addr_vir, td_u8 *output_addr_vir);
static td_s32 priv_klad_attach(td_handle_klad *klad_handle, td_mem_handle *src_handle, td_mem_handle *dst_handle,
td_u8 **input_addr_vir, td_u8 **output_addr_vir)
{
td_s32 ret;
td_u8 iv[KEY_LEN] = {0};
ret = priv_klad_mem_addr_vir(src_handle, dst_handle, input_addr_vir, output_addr_vir);
if (ret != TD_SUCCESS) {
klad_print_error_func(priv_klad_mem_addr_vir, ret);
goto out;
}
ret = priv_klad_attr(klad_handle);
if (ret != TD_SUCCESS) {
klad_print_error_func(priv_klad_attr, ret);
goto klad_umem;
}
ret = uapi_cipher_symc_get_keyslot_handle(klad_handle->handle_cipher, &klad_handle->handle_ks);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_cipher_symc_get_keyslot_handle, ret);
goto klad_umem;
}
ret = uapi_klad_attach(klad_handle->handle_klad, klad_handle->handle_ks);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_klad_attach, ret);
goto klad_umem;
}
ret = cfg_cipher(klad_handle->handle_cipher, UAPI_CIPHER_SYMC_ALG_AES, UAPI_CIPHER_SYMC_WORK_MODE_CBC, iv, KEY_LEN);
if (ret != TD_SUCCESS) {
klad_print_error_func(cfg_cipher, ret);
goto klad_detach;
}
ret = set_key(klad_handle->handle_klad);
if (ret != TD_SUCCESS) {
klad_print_error_func(set_key, ret);
goto klad_detach;
}
return TD_SUCCESS;
klad_detach:
uapi_klad_detach(klad_handle->handle_klad, klad_handle->handle_ks);
klad_umem:
priv_klad_unmem_addr_vir(src_handle, dst_handle, *input_addr_vir, *output_addr_vir);
out:
return ret;
}
static td_s32 priv_klad_encrypt(const td_handle_klad *klad_handle, const td_mem_handle *src_handle,
const td_mem_handle *dst_handle, td_u8 *input_addr_vir, td_u8 *output_addr_vir)
{
errno_t errno;
td_s32 ret = TD_FAILURE;
const td_mem_size_t data_len = DATA_LEN;
uapi_cipher_buf_attr src_buf = {0};
uapi_cipher_buf_attr dest_buf = {0};
errno = memset_s(input_addr_vir, data_len, 0x0, data_len * sizeof(td_u8));
if (errno != EOK) {
klad_print_error_func(memset_s, errno);
goto out;
}
errno = memcpy_s(input_addr_vir, data_len, g_data_in, data_len * sizeof(td_u8));
if (errno != EOK) {
klad_print_error_func(memcpy_s, errno);
goto out;
}
errno = memset_s(output_addr_vir, data_len, 0x0, data_len * sizeof(td_u8));
if (errno != EOK) {
klad_print_error_func(memset_s, errno);
goto out;
}
src_buf.uapi_mem_handle = src_handle->mem_handle;
dest_buf.uapi_mem_handle = dst_handle->mem_handle;
ret = uapi_cipher_symc_encrypt(klad_handle->handle_cipher, &src_buf, &dest_buf, data_len);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_cipher_encrypt, ret);
goto out;
}
print_buffer("clear data:", g_data_in, data_len);
print_buffer("encrypted data:", output_addr_vir, data_len);
out:
return ret;
}
static td_void priv_klad_unmem_addr_vir(const td_mem_handle *src_handle, const td_mem_handle *dst_handle,
td_u8 *input_addr_vir, td_u8 *output_addr_vir)
{
if (src_handle->mem_handle > 0) {
uapi_mem_unmap(input_addr_vir, DATA_LEN);
uapi_mem_delete(src_handle->mem_handle);
}
if (dst_handle->mem_handle > 0) {
uapi_mem_unmap(output_addr_vir, DATA_LEN);
uapi_mem_delete(dst_handle->mem_handle);
}
return;
}
static td_void priv_klad_detach(const td_handle_klad *klad_handle,
const td_mem_handle *src_handle, const td_mem_handle *dst_handle,
td_u8 *input_addr_vir, td_u8 *output_addr_vir)
{
td_s32 ret;
ret = uapi_klad_detach(klad_handle->handle_klad, klad_handle->handle_ks);
if (ret != TD_SUCCESS) {
klad_print_error_func(uapi_klad_detach, ret);
}
priv_klad_unmem_addr_vir(src_handle, dst_handle, input_addr_vir, output_addr_vir);
return;
}
static td_void priv_klad_deinit(const td_handle_klad *klad_handle)
{
uapi_cipher_symc_destroy(klad_handle->handle_cipher);
uapi_klad_destroy(klad_handle->handle_klad);
uapi_klad_deinit();
uapi_cipher_symc_deinit();
uapi_sys_deinit();
return;
}
static td_s32 priv_data_init(const td_char *cfg_path)
{
td_s32 ret;
td_s32 value_num = 0;
ret = parse_config_file(cfg_path, &value_num);
if (ret != TD_SUCCESS || value_num == 0 || value_num > MAX_VAR_NUM) {
klad_print_error_func(parse_config_file, ret);
goto out;
}
ret = get_key_value(SESSIONKEY_TAG, g_session_key, KEY_LEN);
if (ret != TD_SUCCESS) {
klad_print_error_func(get_key_value, ret);
goto out;
}
ret = get_key_value(CONTENTKEY_TAG, g_content_key, KEY_LEN);
if (ret != TD_SUCCESS) {
klad_print_error_func(get_key_value, ret);
goto out;
}
ret = get_key_value(CIPHER_INPUT_DATA, g_data_in, DATA_LEN);
if (ret != TD_SUCCESS) {
klad_print_error_func(get_key_value, ret);
goto out;
}
out:
return ret;
}
td_s32 main(td_s32 argc, td_char *argv[])
{
td_s32 ret;
td_handle_klad klad_handle = {0};
td_u8 *input_addr_vir = TD_NULL;
td_u8 *output_addr_vir = TD_NULL;
td_mem_handle src_handle;
td_mem_handle dst_handle;
(void)argc;
if (argv == TD_NULL || argv[0x1] == TD_NULL) {
printf("Please enter the path of the klad_data_cfg.ini file.!!!\n");
return TD_FAILURE;
}
ret = priv_data_init(argv[0x1]);
if (ret != TD_SUCCESS) {
klad_print_error_func(priv_data_init, ret);
return ret;
}
ret = priv_klad_init(&klad_handle);
if (ret != TD_SUCCESS) {
return ret;
}
ret = priv_klad_attach(&klad_handle, &src_handle, &dst_handle, &input_addr_vir, &output_addr_vir);
if (ret != TD_SUCCESS) {
klad_print_error_func(priv_klad_attach, ret);
goto out;
}
ret = priv_klad_encrypt(&klad_handle, &src_handle, &dst_handle, input_addr_vir, output_addr_vir);
if (ret != TD_SUCCESS) {
klad_print_error_func(priv_klad_encrypt, ret);
}
priv_klad_detach(&klad_handle, &src_handle, &dst_handle, input_addr_vir, output_addr_vir);
out:
priv_klad_deinit(&klad_handle);
return ret;
}