1
0
Fork 0
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.

401 lines
9.3 KiB

/*
* Copyright (c) 2022 Rockchip Electronics Co. Ltd.
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "rkcrypto_core.h"
#include "rkcrypto_mem.h"
#include "rkcrypto_trace.h"
#include "cmode_adapter.h"
#include "test_cipher.h"
#include "test_utils.h"
#define DATA_BUTT 0xFFFFFFFF
#define TEST_DATA_MAX (1024 * 1024)
#define MULTI_BLOCKSIZE (256 * 1024)
struct test_cipher_item {
uint32_t algo;
uint32_t modes[RK_CIPHER_MODE_MAX];
uint32_t key_lens[4];
uint32_t iv_len;
};
static struct test_cipher_item test_item_tbl[] = {
{
.algo = RK_ALGO_DES,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CFB,
RK_CIPHER_MODE_OFB,
DATA_BUTT,
},
.key_lens = {8},
.iv_len = DES_BLOCK_SIZE,
},
{
.algo = RK_ALGO_TDES,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CFB,
RK_CIPHER_MODE_OFB,
DATA_BUTT,
},
.key_lens = {24},
.iv_len = DES_BLOCK_SIZE,
},
{
.algo = RK_ALGO_AES,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CTS,
RK_CIPHER_MODE_CTR,
RK_CIPHER_MODE_CFB,
RK_CIPHER_MODE_OFB,
RK_CIPHER_MODE_XTS,
DATA_BUTT,
},
.key_lens = {16, 24, 32},
.iv_len = AES_BLOCK_SIZE,
},
{
.algo = RK_ALGO_SM4,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CTS,
RK_CIPHER_MODE_CTR,
RK_CIPHER_MODE_CFB,
RK_CIPHER_MODE_OFB,
RK_CIPHER_MODE_XTS,
DATA_BUTT,
},
.key_lens = {16},
.iv_len = SM4_BLOCK_SIZE,
},
};
static RK_RES test_cipher_item_virt(const struct test_cipher_item *item, int verbose)
{
RK_RES res = RK_CRYPTO_ERR_GENERIC;
uint32_t i, j, k;
uint32_t ops[] = {RK_OP_CIPHER_ENC, RK_OP_CIPHER_DEC};
uint32_t data_len = TEST_DATA_MAX;
rk_handle cipher_hdl = 0;
rk_cipher_config cipher_cfg;
uint8_t *plain = NULL, *cipher_soft = NULL, *cipher_hard = NULL;
uint32_t algo = 0, mode = 0, key_len, iv_len, operation;
uint32_t loop_nbytes, tmp_len;
uint8_t *tmp_data_in, *tmp_data_out;
uint8_t iv_tmp[AES_BLOCK_SIZE];
size_t page_size = getpagesize();
if (posix_memalign((void *)&plain, page_size, data_len) || !plain) {
E_TRACE("plain malloc %uByte error!\n", data_len);
goto exit;
}
if (posix_memalign((void *)&cipher_soft, page_size, data_len) || !cipher_soft) {
E_TRACE("cipher_soft malloc %uByte error!\n", data_len);
goto exit;
}
if (posix_memalign((void *)&cipher_hard, page_size, data_len) || !cipher_hard) {
E_TRACE("cipher_hard malloc %uByte error!\n", data_len);
goto exit;
}
test_get_rng(plain, data_len);
memset(cipher_soft, 0x00, data_len);
memset(cipher_hard, 0x00, data_len);
for (i = 0; i < ARRAY_SIZE(item->modes); i++) {
algo = item->algo;
mode = item->modes[i];
if (mode == DATA_BUTT)
break;
for (j = 0; j < ARRAY_SIZE(item->key_lens); j++) {
key_len = item->key_lens[j];
iv_len = item->iv_len;
if (key_len == 0)
break;
if (mode == RK_CIPHER_MODE_XTS)
key_len *= 2;
for (k = 0; k < ARRAY_SIZE(ops); k++) {
operation = ops[k];
memset(&cipher_cfg, 0x00, sizeof(cipher_cfg));
cipher_cfg.algo = algo;
cipher_cfg.mode = mode;
cipher_cfg.operation = operation;
cipher_cfg.key_len = key_len;
test_get_rng(cipher_cfg.key, key_len);
test_get_rng(cipher_cfg.iv, iv_len);
memcpy(iv_tmp, cipher_cfg.iv, iv_len);
res = rk_cipher_init(&cipher_cfg, &cipher_hdl);
if (res) {
if (res != RK_CRYPTO_ERR_NOT_SUPPORTED) {
E_TRACE("rk_cipher_init error[%x]\n", res);
goto exit;
}
if (verbose)
printf("virt:\t[%s-%u]\t%s\t%s\tN/A\n",
test_algo_name(algo), key_len * 8,
test_mode_name(mode),
test_op_name(operation));
res = RK_CRYPTO_SUCCESS;
continue;
}
if (is_no_multi_blocksize(mode))
data_len = TEST_DATA_MAX - 3;
else
data_len = TEST_DATA_MAX;
/* chain multi crypt */
loop_nbytes = data_len;
tmp_data_in = plain;
tmp_data_out = cipher_hard;
while (loop_nbytes) {
tmp_len = loop_nbytes > MULTI_BLOCKSIZE ? MULTI_BLOCKSIZE : loop_nbytes;
res = rk_cipher_crypt_virt(cipher_hdl, tmp_data_in,
tmp_data_out, tmp_len);
if (res) {
rk_cipher_final(cipher_hdl);
E_TRACE("rk_cipher_crypt_virt error[%x]\n", res);
goto exit;
}
tmp_data_in += tmp_len;
tmp_data_out += tmp_len;
loop_nbytes -= tmp_len;
}
rk_cipher_final(cipher_hdl);
cipher_hdl = 0;
res = soft_cipher(algo, mode, operation,
cipher_cfg.key, cipher_cfg.key_len, iv_tmp,
plain, data_len, cipher_soft);
if (res) {
E_TRACE("soft_cipher error[%x]\n", res);
goto exit;
}
/* Verify the result */
if (memcmp(cipher_hard, cipher_soft, data_len) != 0) {
E_TRACE("rkcrypto_test_cipher_virt compare failed.\n");
// test_dump_hex("cipher_hard", cipher_hard, data_len);
// test_dump_hex("cipher_soft", cipher_soft, data_len);
res = RK_CRYPTO_ERR_GENERIC;
goto exit;
}
if (verbose)
printf("virt:\t[%s-%u]\t%s\t%s\tPASS\n",
test_algo_name(algo), key_len * 8,
test_mode_name(mode), test_op_name(operation));
}
}
}
res = RK_CRYPTO_SUCCESS;
exit:
if (plain)
free(plain);
if (cipher_soft)
free(cipher_soft);
if (cipher_hard)
free(cipher_hard);
if (res)
printf("virt:\t[%s-%u]\t%s\t%s\tFAIL\n",
test_algo_name(algo), key_len * 8,
test_mode_name(mode), test_op_name(operation));
return res;
}
static RK_RES test_cipher_item_fd(const struct test_cipher_item *item, int verbose)
{
RK_RES res = RK_CRYPTO_ERR_GENERIC;
uint32_t i, j, k;
uint32_t ops[] = {RK_OP_CIPHER_ENC, RK_OP_CIPHER_DEC};
uint32_t data_len = TEST_DATA_MAX;
rk_handle cipher_hdl = 0;
rk_cipher_config cipher_cfg;
rk_crypto_mem *plain = NULL, *cipher_soft = NULL, *cipher_hard = NULL;
uint32_t algo = 0, mode = 0, key_len = 0, iv_len, operation;
uint8_t iv_tmp[AES_BLOCK_SIZE];
plain = rk_crypto_mem_alloc(data_len);
if (!plain) {
E_TRACE("plain malloc %uByte error!\n", data_len);
goto exit;
}
cipher_soft = rk_crypto_mem_alloc(data_len);
if (!cipher_soft) {
E_TRACE("cipher_soft malloc %uByte error!\n", data_len);
goto exit;
}
cipher_hard = rk_crypto_mem_alloc(data_len);
if (!cipher_hard) {
E_TRACE("cipher_hard malloc %uByte error!\n", data_len);
goto exit;
}
test_get_rng(plain->vaddr, data_len);
for (i = 0; i < ARRAY_SIZE(item->modes); i++) {
algo = item->algo;
mode = item->modes[i];
if (mode == DATA_BUTT)
break;
for (j = 0; j < ARRAY_SIZE(item->key_lens); j++) {
key_len = item->key_lens[j];
iv_len = item->iv_len;
if (key_len == 0)
break;
if (mode == RK_CIPHER_MODE_XTS)
key_len *= 2;
for (k = 0; k < ARRAY_SIZE(ops); k++) {
operation = ops[k];
memset(&cipher_cfg, 0x00, sizeof(cipher_cfg));
cipher_cfg.algo = algo;
cipher_cfg.mode = mode;
cipher_cfg.operation = operation;
cipher_cfg.key_len = key_len;
test_get_rng(cipher_cfg.key, key_len);
test_get_rng(cipher_cfg.iv, iv_len);
memcpy(iv_tmp, cipher_cfg.iv, iv_len);
res = rk_cipher_init(&cipher_cfg, &cipher_hdl);
if (res) {
if (res != RK_CRYPTO_ERR_NOT_SUPPORTED) {
E_TRACE("rk_cipher_init error[%x]\n", res);
goto exit;
}
if (verbose)
printf("dma_fd:\t[%s-%u]\t%s\t%s\tN/A\n",
test_algo_name(algo), key_len * 8,
test_mode_name(mode), test_op_name(operation));
res = RK_CRYPTO_SUCCESS;
continue;
}
if (is_no_multi_blocksize(mode))
data_len = TEST_DATA_MAX - 7;
else
data_len = TEST_DATA_MAX;
res = rk_cipher_crypt(cipher_hdl, plain->dma_fd,
cipher_hard->dma_fd, data_len);
if (res) {
rk_cipher_final(cipher_hdl);
E_TRACE("rk_cipher_crypt error[%x]\n", res);
goto exit;
}
rk_cipher_final(cipher_hdl);
cipher_hdl = 0;
res = soft_cipher(algo, mode, operation,
cipher_cfg.key, cipher_cfg.key_len, iv_tmp,
plain->vaddr, data_len, cipher_soft->vaddr);
if (res) {
E_TRACE("soft_cipher error[%x]\n", res);
goto exit;
}
/* Verify the result */
if (memcmp(cipher_hard->vaddr, cipher_soft->vaddr, data_len) != 0) {
E_TRACE("rkcrypto_test_cipher compare failed.\n");
// test_dump_hex("cipher_hard", cipher_hard->vaddr, data_len);
// test_dump_hex("cipher_soft", cipher_soft->vaddr, data_len);
res = RK_CRYPTO_ERR_GENERIC;
goto exit;
}
if (verbose)
printf("dma_fd:\t[%s-%u]\t%s\t%s\tPASS\n",
test_algo_name(algo), key_len * 8,
test_mode_name(mode), test_op_name(operation));
}
}
}
res = RK_CRYPTO_SUCCESS;
exit:
rk_crypto_mem_free(plain);
rk_crypto_mem_free(cipher_soft);
rk_crypto_mem_free(cipher_hard);
if (res && key_len)
printf("dma_fd:\t[%s-%u]\t%s\t%s\tFAIL\n",
test_algo_name(algo), key_len * 8,
test_mode_name(mode), test_op_name(operation));
return res;
}
RK_RES test_cipher(int verbose)
{
RK_RES res = RK_CRYPTO_ERR_GENERIC;
uint32_t i;
res = rk_crypto_init();
if (res) {
printf("rk_crypto_init error %08x\n", res);
return res;
}
for (i = 0; i < ARRAY_SIZE(test_item_tbl); i++) {
res = test_cipher_item_virt(&test_item_tbl[i], verbose);
if (res)
goto exit;
res = test_cipher_item_fd(&test_item_tbl[i], verbose);
if (res)
goto exit;
if (verbose)
printf("\n");
}
exit:
rk_crypto_deinit();
return res;
}