2025-05-10 21:49:39 +08:00

1165 lines
27 KiB
C

/*
* Copyright (c) 2022 Rockchip Electronics Co. Ltd.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "rkcrypto_core.h"
#include "rkcrypto_mem.h"
#include "rkcrypto_otp_key.h"
#include "rkcrypto_random.h"
#include "test_utils.h"
#include "rsa_key_data.h"
#define TEST_BLOCK_SIZE 1024 * 1024 /* 1MB */
#define TEST_OTP_BLOCK_SIZE 500 * 1024
#define DURATION 1 /* 1s */
#define DATA_BUTT 0xFFFFFFFF
static int test_otp_key_item_tp(bool is_virt, uint32_t key_id, uint32_t key_len,
uint32_t algo, uint32_t mode, uint32_t operation,
rk_crypto_mem *fd, uint32_t data_len)
{
uint32_t res = 0;
rk_cipher_config config;
uint8_t iv[16];
uint8_t in_out[RK_CRYPTO_MAX_DATA_LEN];
struct timespec start, end;
uint64_t total_nsec, nsec;
uint32_t rounds;
nsec = DURATION * 1000000000;
memset(iv, 0x00, sizeof(iv));
test_get_rng(iv, sizeof(iv));
if (is_virt) {
memset(in_out, 0x00, sizeof(in_out));
test_get_rng(in_out, data_len);
}
memcpy(config.iv, iv, sizeof(iv));
config.algo = algo;
config.mode = mode;
config.key_len = key_len;
config.reserved = NULL;
config.operation = operation;
total_nsec = 0;
rounds = 0;
while (total_nsec < nsec) {
clock_gettime(CLOCK_REALTIME, &start);
if (is_virt)
res = rk_oem_otp_key_cipher_virt(key_id, &config, in_out, in_out, data_len);
else
res = rk_oem_otp_key_cipher(key_id, &config, fd->dma_fd, fd->dma_fd, data_len);
if (res == RK_CRYPTO_ERR_NOT_SUPPORTED) {
if (is_virt)
printf("virt:\totpkey\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));
else
printf("dma_fd:\totpkey\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));
return RK_CRYPTO_SUCCESS;
} else if (res) {
printf("test rk_oem_otp_key_cipher failed! 0x%08x\n", res);
return res;
}
clock_gettime(CLOCK_REALTIME, &end);
total_nsec += (end.tv_sec - start.tv_sec) * 1000000000 +
(end.tv_nsec - start.tv_nsec);
rounds ++;
}
if (is_virt)
printf("virt:\totpkey\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(operation), (data_len * rounds / (1024 * 1024)));
else
printf("dma_fd:\totpkey\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(operation), (data_len * rounds / (1024 * 1024)));
return res;
}
static int test_otp_key_virt_tp(void)
{
uint32_t h, j, k;
uint32_t algo, key_id, mode, operation, len, key_len;
const uint32_t algo_tab[] = {
RK_ALGO_AES,
RK_ALGO_SM4,
};
const uint32_t mode_tab[] = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CTR,
};
const uint32_t op_tab[] = {
RK_OP_CIPHER_ENC,
RK_OP_CIPHER_DEC,
};
for (h = 0; h < ARRAY_SIZE(algo_tab); h++) {
for (j = 0; j < ARRAY_SIZE(mode_tab); j++) {
for (k = 0; k < ARRAY_SIZE(op_tab); k++) {
algo = algo_tab[h];
mode = mode_tab[j];
operation = op_tab[k];
key_id = RK_OEM_OTP_KEY3;
len = TEST_OTP_BLOCK_SIZE;
if (algo == RK_ALGO_AES) {
key_len = 32;
} else {
key_len = 16;
}
if (test_otp_key_item_tp(true, key_id, key_len, algo,
mode, operation, NULL, len))
goto error;
}
}
}
printf("virt:\ttest otp_key throughput SUCCESS.\n\n");
return 0;
error:
printf("virt:\ttest otp_key throughput FAILED!!!\n\n");
return -1;
}
static int test_otp_key_fd_tp(void)
{
int res = 0;
uint32_t h, j, k;
uint32_t algo, key_id, mode, operation, len, key_len;
rk_crypto_mem *in_out = NULL;
const uint32_t algo_tab[] = {
RK_ALGO_AES,
RK_ALGO_SM4,
};
const uint32_t mode_tab[] = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CTR,
};
const uint32_t op_tab[] = {
RK_OP_CIPHER_ENC,
RK_OP_CIPHER_DEC,
};
if (rk_crypto_init()) {
printf("rk_crypto_init error!\n");
return -1;
}
in_out = rk_crypto_mem_alloc(TEST_OTP_BLOCK_SIZE);
if (!in_out) {
printf("rk_crypto_mem_alloc %uByte error!\n", TEST_OTP_BLOCK_SIZE);
res = -1;
goto out;
}
for (h = 0; h < ARRAY_SIZE(algo_tab); h++) {
for (j = 0; j < ARRAY_SIZE(mode_tab); j++) {
for (k = 0; k < ARRAY_SIZE(op_tab); k++) {
algo = algo_tab[h];
mode = mode_tab[j];
operation = op_tab[k];
key_id = RK_OEM_OTP_KEY3;
len = TEST_OTP_BLOCK_SIZE;
if (algo == RK_ALGO_AES) {
key_len = 32;
} else {
key_len = 16;
}
if (test_otp_key_item_tp(false, key_id, key_len, algo,
mode, operation, in_out, len)) {
printf("dma_fd:\ttest otp_key throughput FAILED!!!\n");
res = -1;
goto out;
}
}
}
}
printf("dma_fd:\ttest otp_key throughput SUCCESS.\n\n");
out:
if (!in_out)
rk_crypto_mem_free(in_out);
rk_crypto_deinit();
return res;
}
static int test_otp_key_tp(void)
{
if (test_otp_key_fd_tp())
return -1;
if (test_otp_key_virt_tp())
return -1;
return 0;
}
static int test_cipher_item_tp(bool is_virt, uint32_t key_len, uint32_t algo,
uint32_t mode, uint32_t operation,
void *in_out, uint32_t data_len)
{
uint32_t res = 0;
rk_handle handle = 0;
rk_cipher_config config;
struct timespec start, end;
uint64_t total_nsec, nsec;
uint32_t rounds;
nsec = DURATION * 1000000000;
test_get_rng(config.iv, sizeof(config.iv));
test_get_rng(config.key, key_len);
if (is_virt)
test_get_rng(in_out, data_len);
config.algo = algo;
config.mode = mode;
config.key_len = key_len;
config.reserved = NULL;
config.operation = operation;
total_nsec = 0;
rounds = 0;
while (total_nsec < nsec) {
clock_gettime(CLOCK_REALTIME, &start);
res = rk_cipher_init(&config, &handle);
if (res) {
if (res != RK_CRYPTO_ERR_NOT_SUPPORTED) {
printf("test rk_cipher_init failed! 0x%08x\n", res);
goto error;
}
if (is_virt)
printf("virt:\t[%s-%u]\t%s\tN/A\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
else
printf("dma_fd:\t[%s-%u]\t%s\tN/A\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
return 0;
}
if (is_virt)
res = rk_cipher_crypt_virt(handle, in_out, in_out, data_len);
else
res = rk_cipher_crypt(handle,
((rk_crypto_mem *)in_out)->dma_fd,
((rk_crypto_mem *)in_out)->dma_fd,
data_len);
if (res) {
rk_cipher_final(handle);
printf("test rk_cipher_crypt failed! 0x%08x\n", res);
goto error;
}
rk_cipher_final(handle);
clock_gettime(CLOCK_REALTIME, &end);
total_nsec += (end.tv_sec - start.tv_sec) * 1000000000 +
(end.tv_nsec - start.tv_nsec);
rounds ++;
}
if (is_virt)
printf("virt:\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(operation), (data_len * rounds / (1024 * 1024)));
else
printf("dma_fd:\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(operation), (data_len * rounds / (1024 * 1024)));
return res;
error:
if (is_virt)
printf("virt:\t[%s-%u]\t%s\tFailed.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
else
printf("dma_fd:\t[%s-%u]\t%s\tFailed.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
return res;
}
static int test_cipher_tp(void)
{
int res = 0;
uint32_t h, j, k;
uint32_t algo, mode, operation, len, key_len;
rk_crypto_mem *in_out_fd = NULL;
uint8_t *in_out_virt = NULL;
size_t page_size = getpagesize();
struct test_cipher_item_tp {
uint32_t algo;
uint32_t modes[RK_CIPHER_MODE_MAX];
uint32_t key_len;
uint32_t op[2];
};
static struct test_cipher_item_tp test_item_tbl[] = {
{
.algo = RK_ALGO_DES,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
DATA_BUTT,
},
.key_len = 8,
.op = {RK_OP_CIPHER_ENC, RK_OP_CIPHER_DEC},
},
{
.algo = RK_ALGO_TDES,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
DATA_BUTT,
},
.key_len = 24,
.op = {RK_OP_CIPHER_ENC, RK_OP_CIPHER_DEC},
},
{
.algo = RK_ALGO_AES,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CTS,
RK_CIPHER_MODE_CTR,
DATA_BUTT,
},
.key_len = 32,
.op = {RK_OP_CIPHER_ENC, RK_OP_CIPHER_DEC},
},
{
.algo = RK_ALGO_SM4,
.modes = {
RK_CIPHER_MODE_ECB,
RK_CIPHER_MODE_CBC,
RK_CIPHER_MODE_CTS,
RK_CIPHER_MODE_CTR,
DATA_BUTT,
},
.key_len = 16,
.op = {RK_OP_CIPHER_ENC, RK_OP_CIPHER_DEC},
},
};
if (rk_crypto_init()) {
printf("rk_crypto_init error!\n");
return -1;
}
in_out_fd = rk_crypto_mem_alloc(TEST_BLOCK_SIZE);
if (!in_out_fd) {
printf("rk_crypto_mem_alloc %uByte error!\n", TEST_BLOCK_SIZE);
res = -1;
goto out;
}
if (posix_memalign((void *)&in_out_virt, page_size, TEST_BLOCK_SIZE) || !in_out_virt) {
printf("malloc %uByte error!\n", TEST_BLOCK_SIZE);
res = -1;
goto out;
}
/* Test dma_fd cipher */
for (h = 0; h < ARRAY_SIZE(test_item_tbl); h++) {
for (j = 0; j < ARRAY_SIZE(test_item_tbl[h].modes); j++) {
if (test_item_tbl[h].modes[j] == DATA_BUTT)
break;
for (k = 0; k < ARRAY_SIZE(test_item_tbl[h].op); k++) {
algo = test_item_tbl[h].algo;
key_len = test_item_tbl[h].key_len;
mode = test_item_tbl[h].modes[j];
operation = test_item_tbl[h].op[k];
len = TEST_BLOCK_SIZE;
if (test_cipher_item_tp(false, key_len, algo, mode,
operation, in_out_fd, len)) {
printf("dma_fd:\ttest cipher throughput FAILED!!!\n");
res = -1;
goto out;
}
}
}
}
printf("dma_fd:\ttest cipher throughput SUCCESS.\n\n");
/* Test virt cipher */
for (h = 0; h < ARRAY_SIZE(test_item_tbl); h++) {
for (j = 0; j < ARRAY_SIZE(test_item_tbl[h].modes); j++) {
if (test_item_tbl[h].modes[j] == DATA_BUTT)
break;
for (k = 0; k < ARRAY_SIZE(test_item_tbl[h].op); k++) {
algo = test_item_tbl[h].algo;
key_len = test_item_tbl[h].key_len;
mode = test_item_tbl[h].modes[j];
operation = test_item_tbl[h].op[k];
len = TEST_BLOCK_SIZE;
if (test_cipher_item_tp(true, key_len, algo, mode,
operation, in_out_virt, len)) {
printf("virt:\ttest cipher throughput FAILED!!!\n");
res = -1;
goto out;
}
}
}
}
printf("virt:\ttest cipher throughput SUCCESS.\n\n");
out:
if (in_out_fd)
rk_crypto_mem_free(in_out_fd);
if (in_out_virt)
free(in_out_virt);
rk_crypto_deinit();
return res;
}
static int test_ae_item_tp(bool is_virt, uint32_t key_len, uint32_t algo,
uint32_t mode, void *in, void *out, uint32_t data_len,
void *aad, uint32_t aad_len, void *tag)
{
uint32_t res = 0;
rk_handle handle = 0;
rk_ae_config config;
struct timespec start, end;
uint64_t total_nsec, nsec;
uint32_t rounds;
uint8_t iv_tmp[32];
nsec = DURATION * 1000000000;
test_get_rng(config.iv, sizeof(config.iv));
test_get_rng(config.key, key_len);
memcpy(iv_tmp, config.iv, sizeof(config.iv));
if (is_virt) {
test_get_rng(in, data_len);
test_get_rng(aad, aad_len);
} else {
test_get_rng(((rk_crypto_mem *)in)->vaddr, data_len);
test_get_rng(((rk_crypto_mem *)aad)->vaddr, aad_len);
}
config.algo = algo;
config.mode = mode;
config.key_len = key_len;
config.reserved = NULL;
config.aad_len = aad_len;
config.iv_len = 12;
config.tag_len = 16;
/* ENC */
config.operation = RK_OP_CIPHER_ENC;
total_nsec = 0;
rounds = 0;
while (total_nsec < nsec) {
clock_gettime(CLOCK_REALTIME, &start);
res = rk_ae_init(&config, &handle);
if (res) {
if (res != RK_CRYPTO_ERR_NOT_SUPPORTED) {
printf("test rk_ae_init failed! 0x%08x\n", res);
goto error;
}
if (is_virt)
printf("virt:\t[%s-%u]\t%s\tN/A\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
else
printf("dma_fd:\t[%s-%u]\t%s\tN/A\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
return 0;
}
if (is_virt) {
res = rk_ae_set_aad_virt(handle, aad);
if (res) {
rk_ae_final(handle);
goto error;
}
res = rk_ae_crypt_virt(handle, in, out, data_len, tag);
} else {
res = rk_ae_set_aad(handle, ((rk_crypto_mem *)aad)->dma_fd);
if (res) {
rk_ae_final(handle);
goto error;
}
res = rk_ae_crypt(handle,
((rk_crypto_mem *)in)->dma_fd,
((rk_crypto_mem *)out)->dma_fd,
data_len,
tag);
}
if (res) {
rk_ae_final(handle);
printf("test rk_ad_crypt failed! 0x%08x\n", res);
goto error;
}
rk_ae_final(handle);
clock_gettime(CLOCK_REALTIME, &end);
total_nsec += (end.tv_sec - start.tv_sec) * 1000000000 +
(end.tv_nsec - start.tv_nsec);
rounds ++;
}
if (is_virt)
printf("virt:\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(config.operation), (data_len * rounds / (1024 * 1024)));
else
printf("dma_fd:\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(config.operation), (data_len * rounds / (1024 * 1024)));
/* DEC */
config.operation = RK_OP_CIPHER_DEC;
memcpy(config.iv, iv_tmp, config.iv_len);
total_nsec = 0;
rounds = 0;
while (total_nsec < nsec) {
clock_gettime(CLOCK_REALTIME, &start);
res = rk_ae_init(&config, &handle);
if (res) {
if (res != RK_CRYPTO_ERR_NOT_SUPPORTED) {
printf("test rk_ae_init failed! 0x%08x\n", res);
goto error;
}
if (is_virt)
printf("virt:\t[%s-%u]\t%s\tN/A\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
else
printf("dma_fd:\t[%s-%u]\t%s\tN/A\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
return 0;
}
if (is_virt) {
res = rk_ae_set_aad_virt(handle, aad);
if (res) {
rk_ae_final(handle);
goto error;
}
res = rk_ae_crypt_virt(handle, out, in, data_len, tag);
} else {
res = rk_ae_set_aad(handle, ((rk_crypto_mem *)aad)->dma_fd);
if (res) {
rk_ae_final(handle);
goto error;
}
res = rk_ae_crypt(handle,
((rk_crypto_mem *)out)->dma_fd,
((rk_crypto_mem *)in)->dma_fd,
data_len,
tag);
}
if (res) {
rk_ae_final(handle);
printf("test rk_ad_crypt failed! 0x%08x\n", res);
goto error;
}
rk_ae_final(handle);
clock_gettime(CLOCK_REALTIME, &end);
total_nsec += (end.tv_sec - start.tv_sec) * 1000000000 +
(end.tv_nsec - start.tv_nsec);
rounds ++;
}
if (is_virt)
printf("virt:\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(config.operation), (data_len * rounds / (1024 * 1024)));
else
printf("dma_fd:\t[%s-%u]\t%s\t%s\t%dMB/s.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode),
test_op_name(config.operation), (data_len * rounds / (1024 * 1024)));
return res;
error:
if (is_virt)
printf("virt:\t[%s-%u]\t%s\tFailed.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
else
printf("dma_fd:\t[%s-%u]\t%s\tFailed.\n",
test_algo_name(algo), key_len * 8, test_mode_name(mode));
return res;
}
static int test_ae_tp(void)
{
int res = 0;
uint32_t h, j;
uint32_t algo, mode, len, key_len, aad_len;
rk_crypto_mem *in_fd = NULL, *out_fd = NULL, *aad_fd = NULL;
uint8_t *in_virt = NULL, *out_virt = NULL, *aad_virt = NULL;
size_t page_size = getpagesize();
uint32_t aad_buff_len = 1024;
uint8_t tag[16];
struct test_aead_item_tp {
uint32_t algo;
uint32_t modes[RK_CIPHER_MODE_MAX];
uint32_t key_len;
uint32_t aad_len;
uint32_t len;
};
static struct test_aead_item_tp test_item_tbl[] = {
{
.algo = RK_ALGO_AES,
.modes = {
RK_CIPHER_MODE_GCM,
DATA_BUTT,
},
.key_len = 32,
.aad_len = 1024,
.len = TEST_BLOCK_SIZE,
},
{
.algo = RK_ALGO_SM4,
.modes = {
RK_CIPHER_MODE_GCM,
DATA_BUTT,
},
.key_len = 16,
.aad_len = 1024,
.len = TEST_BLOCK_SIZE,
},
};
if (rk_crypto_init()) {
printf("rk_crypto_init error!\n");
return -1;
}
in_fd = rk_crypto_mem_alloc(TEST_BLOCK_SIZE);
if (!in_fd) {
printf("rk_crypto_mem_alloc %uByte error!\n", TEST_BLOCK_SIZE);
res = -1;
goto out;
}
out_fd = rk_crypto_mem_alloc(TEST_BLOCK_SIZE);
if (!out_fd) {
printf("rk_crypto_mem_alloc %uByte error!\n", TEST_BLOCK_SIZE);
res = -1;
goto out;
}
aad_fd = rk_crypto_mem_alloc(aad_buff_len);
if (!aad_fd) {
printf("rk_crypto_mem_alloc %uByte error!\n", aad_buff_len);
res = -1;
goto out;
}
if (posix_memalign((void *)&in_virt, page_size, TEST_BLOCK_SIZE) || !in_virt) {
printf("malloc %uByte error!\n", TEST_BLOCK_SIZE);
res = -1;
goto out;
}
if (posix_memalign((void *)&out_virt, page_size, TEST_BLOCK_SIZE) || !out_virt) {
printf("malloc %uByte error!\n", TEST_BLOCK_SIZE);
res = -1;
goto out;
}
if (posix_memalign((void *)&aad_virt, page_size, aad_buff_len) || !aad_virt) {
printf("malloc %uByte error!\n", aad_buff_len);
res = -1;
goto out;
}
/* Test dma_fd cipher */
for (h = 0; h < ARRAY_SIZE(test_item_tbl); h++) {
for (j = 0; j < ARRAY_SIZE(test_item_tbl[h].modes); j++) {
if (test_item_tbl[h].modes[j] == DATA_BUTT)
break;
algo = test_item_tbl[h].algo;
key_len = test_item_tbl[h].key_len;
mode = test_item_tbl[h].modes[j];
aad_len = test_item_tbl[h].aad_len;
len = test_item_tbl[h].len;
if (test_ae_item_tp(false, key_len, algo, mode,
in_fd, out_fd, len,
aad_fd, aad_len, tag)) {
printf("dma_fd:\ttest aead throughput FAILED!!!\n");
res = -1;
goto out;
}
}
}
printf("dma_fd:\ttest aead throughput SUCCESS.\n\n");
/* Test virt cipher */
for (h = 0; h < ARRAY_SIZE(test_item_tbl); h++) {
for (j = 0; j < ARRAY_SIZE(test_item_tbl[h].modes); j++) {
if (test_item_tbl[h].modes[j] == DATA_BUTT)
break;
algo = test_item_tbl[h].algo;
key_len = test_item_tbl[h].key_len;
mode = test_item_tbl[h].modes[j];
aad_len = test_item_tbl[h].aad_len;
len = test_item_tbl[h].len;
if (test_ae_item_tp(true, key_len, algo, mode,
in_virt, out_virt, len,
aad_virt, aad_len, tag)) {
printf("virt:\ttest aead throughput FAILED!!!\n");
res = -1;
goto out;
}
}
}
printf("virt:\ttest aead throughput SUCCESS.\n\n");
out:
if (in_fd)
rk_crypto_mem_free(in_fd);
if (out_fd)
rk_crypto_mem_free(out_fd);
if (aad_fd)
rk_crypto_mem_free(aad_fd);
if (in_virt)
free(in_virt);
if (out_virt)
free(out_virt);
if (aad_virt)
free(aad_virt);
rk_crypto_deinit();
return res;
}
static int test_hash_item_tp(bool is_virt, bool is_hmac, uint32_t algo,
uint32_t blocksize, void *input, uint32_t data_len)
{
int res = 0;
uint32_t data_block = data_len;
uint32_t tmp_len;
uint8_t hash[64];
uint8_t key[MAX_HASH_BLOCK_SIZE];
uint8_t *tmp_data;
rk_handle hash_hdl = 0;
rk_hash_config hash_cfg;
uint32_t key_len;
struct timespec start, end;
uint64_t total_nsec, nsec;
uint32_t rounds;
nsec = DURATION * 1000000000;
if (is_virt)
test_get_rng(input, data_len);
memset(hash, 0x00, sizeof(hash));
memset(&hash_cfg, 0x00, sizeof(hash_cfg));
hash_cfg.algo = algo;
if (is_hmac) {
key_len = blocksize;
test_get_rng(key, key_len);
hash_cfg.key = key;
hash_cfg.key_len = key_len;
}
total_nsec = 0;
rounds = 0;
res = rk_hash_init(&hash_cfg, &hash_hdl);
if (res) {
if (is_virt)
printf("virt:\t[%12s]\tN/A\n", test_algo_name(algo));
else
printf("dma_fd:\t[%12s]\tN/A\n", test_algo_name(algo));
return 0;
}
while (total_nsec < nsec) {
clock_gettime(CLOCK_REALTIME, &start);
data_block = data_len;
if (is_virt) {
tmp_len = data_len;
tmp_data = input;
while (tmp_len) {
data_block = tmp_len > data_block ? data_block : tmp_len;
res = rk_hash_update_virt(hash_hdl, tmp_data, data_block);
if (res) {
rk_hash_final(hash_hdl, NULL);
printf("rk_hash_update_virt[%lu/%u] error = %d\n",
(unsigned long)(tmp_data - (uint8_t *)input), tmp_len, res);
goto error;
}
tmp_len -= data_block;
tmp_data += data_block;
}
} else {
res = rk_hash_update(hash_hdl, ((rk_crypto_mem *)input)->dma_fd, data_block);
if (res) {
rk_hash_final(hash_hdl, NULL);
printf("rk_hash_update error = %d\n", res);
goto error;
}
}
clock_gettime(CLOCK_REALTIME, &end);
total_nsec += (end.tv_sec - start.tv_sec) * 1000000000 +
(end.tv_nsec - start.tv_nsec);
rounds ++;
}
res = rk_hash_final(hash_hdl, hash);
if (res) {
printf("rk_hash_final error = %d\n", res);
return -1;
}
if (is_virt)
printf("virt:\t[%12s]\t%dMB/s.\n",
test_algo_name(algo), (data_len * rounds / (1024 * 1024)));
else
printf("dma_fd:\t[%12s]\t%dMB/s.\n",
test_algo_name(algo), (data_len * rounds / (1024 * 1024)));
return res;
error:
return res;
}
static int test_hash_tp(void)
{
int res;
uint32_t buffer_len = TEST_BLOCK_SIZE;;
rk_crypto_mem *input_fd = NULL;
uint8_t *input_virt = NULL;
uint32_t i;
size_t page_size = getpagesize();
struct test_hash_item {
uint32_t algo;
uint32_t blocksize;
};
static struct test_hash_item test_hash_tbl[] = {
{RK_ALGO_MD5, MD5_BLOCK_SIZE},
{RK_ALGO_SHA1, SHA1_BLOCK_SIZE},
{RK_ALGO_SHA256, SHA256_BLOCK_SIZE},
{RK_ALGO_SHA224, SHA224_BLOCK_SIZE},
{RK_ALGO_SHA512, SHA512_BLOCK_SIZE},
{RK_ALGO_SHA384, SHA384_BLOCK_SIZE},
{RK_ALGO_SHA512_224, SHA512_224_BLOCK_SIZE},
{RK_ALGO_SHA512_256, SHA512_256_BLOCK_SIZE},
{RK_ALGO_SM3, SM3_BLOCK_SIZE},
};
static struct test_hash_item test_hmac_tbl[] = {
{RK_ALGO_HMAC_MD5, MD5_BLOCK_SIZE},
{RK_ALGO_HMAC_SHA1, SHA1_BLOCK_SIZE},
{RK_ALGO_HMAC_SHA256, SHA256_BLOCK_SIZE},
{RK_ALGO_HMAC_SHA512, SHA512_BLOCK_SIZE},
{RK_ALGO_HMAC_SM3, SM3_BLOCK_SIZE},
};
if (rk_crypto_init()) {
printf("rk_crypto_init error!\n");
return -1;
}
input_fd = rk_crypto_mem_alloc(buffer_len);
if (!input_fd) {
printf("rk_crypto_mem_alloc %uByte error!\n", buffer_len);
res = -1;
goto out;
}
if (posix_memalign((void *)&input_virt, page_size, TEST_BLOCK_SIZE) || !input_virt) {
printf("malloc %uByte error!\n", TEST_BLOCK_SIZE);
res = -1;
goto out;
}
/* Test virt hash */
for (i = 0; i < ARRAY_SIZE(test_hash_tbl); i++) {
res = test_hash_item_tp(true, false, test_hash_tbl[i].algo,
test_hash_tbl[i].blocksize, input_virt, buffer_len);
if (res) {
printf("virt:\ttest hash throughput FAILED!!!\n");
goto out;
}
}
printf("virt:\ttest hash throughput SUCCESS.\n\n");
/* Test dma_fd hash */
for (i = 0; i < ARRAY_SIZE(test_hash_tbl); i++) {
res = test_hash_item_tp(false, false, test_hash_tbl[i].algo,
test_hash_tbl[i].blocksize, input_fd, buffer_len);
if (res) {
printf("dma_fd:\ttest hash throughput FAILED!!!\n");
goto out;
}
}
printf("dma_fd:\ttest hash throughput SUCCESS.\n\n");
/* Test virt hmac */
for (i = 0; i < ARRAY_SIZE(test_hmac_tbl); i++) {
res = test_hash_item_tp(true, true, test_hmac_tbl[i].algo,
test_hmac_tbl[i].blocksize, input_virt, buffer_len);
if (res) {
printf("virt:\ttest hmac throughput FAILED!!!\n");
goto out;
}
}
printf("virt:\ttest hmac throughput SUCCESS.\n\n");
/* Test dma_fd hmac */
for (i = 0; i < ARRAY_SIZE(test_hmac_tbl); i++) {
res = test_hash_item_tp(false, true, test_hmac_tbl[i].algo,
test_hmac_tbl[i].blocksize, input_fd, buffer_len);
if (res) {
printf("dma_fd:\ttest hmac throughput FAILED!!!\n");
goto out;
}
}
printf("dma_fd:\ttest hmac throughput SUCCESS.\n\n");
out:
if (input_fd)
rk_crypto_mem_free(input_fd);
if (input_virt)
free(input_virt);
rk_crypto_deinit();
return 0;
}
static int test_rsa_item_tp(uint32_t nbits)
{
uint8_t *data_plain = NULL, *data_enc = NULL, *data_dec = NULL;
uint32_t nbytes = nbits / 8;
rk_rsa_pub_key_pack pub_key;
rk_rsa_priv_key_pack priv_key;
struct timespec t1, t2, t3;
uint64_t priv_cost, pub_cost;
uint32_t out_len = 0;
RK_RES res;
data_plain = malloc(nbytes);
if (!data_plain) {
printf("malloc data_plain %uByte error!\n", nbytes);
res = RK_CRYPTO_ERR_OUT_OF_MEMORY;
goto exit;
}
data_enc = malloc(nbytes);
if (!data_enc) {
printf("malloc data_enc %uByte error!\n", nbytes);
res = RK_CRYPTO_ERR_OUT_OF_MEMORY;
goto exit;
}
data_dec = malloc(nbytes);
if (!data_dec) {
printf("malloc data_dec %uByte error!\n", nbytes);
res = RK_CRYPTO_ERR_OUT_OF_MEMORY;
goto exit;
}
res = rk_get_random(data_plain, nbytes);
if (res) {
printf("failed to get random data.");
goto exit;
}
/* make sure data_plain is less than n */
data_plain[0] = 0x00;
memset(data_enc, 0x00, nbytes);
test_init_pubkey(&pub_key, nbits);
test_init_privkey(&priv_key, nbits);
clock_gettime(CLOCK_REALTIME, &t1);
res = rk_rsa_priv_encrypt(&priv_key, RK_RSA_CRYPT_PADDING_NONE,
data_plain, nbytes, data_enc, &out_len);
if (res) {
if (res != RK_CRYPTO_ERR_NOT_SUPPORTED)
printf("rk_rsa_priv_encrypt failed %x\n", res);
goto exit;
}
clock_gettime(CLOCK_REALTIME, &t2);
res = rk_rsa_pub_decrypt(&pub_key, RK_RSA_CRYPT_PADDING_NONE,
data_enc, out_len, data_dec, &out_len);
if (res) {
printf("rk_rsa_pub_decrypt failed %x\n", res);
goto exit;
}
clock_gettime(CLOCK_REALTIME, &t3);
if (nbytes != out_len || memcmp(data_dec, data_plain, nbytes)) {
printf("rk_rsa_pub_decrypt compare failed\n");
test_dump_hex("result", data_dec, out_len);
test_dump_hex("expect", data_plain, nbytes);
res = RK_CRYPTO_ERR_GENERIC;
goto exit;
}
priv_cost = (t2.tv_sec - t1.tv_sec) * 1000000000 +
(t2.tv_nsec - t1.tv_nsec);
pub_cost = (t3.tv_sec - t2.tv_sec) * 1000000000 +
(t3.tv_nsec - t2.tv_nsec);
printf("virt:\t[RSA-%u]\tPRIV\tENCRYPT\t%lums.\n",
nbits, (unsigned long)(priv_cost / 1000000));
printf("virt:\t[RSA-%u]\tPUB\tDECRYPT\t%lums.\n",
nbits, (unsigned long)(pub_cost / 1000000));
exit:
if (data_plain)
free(data_plain);
if (data_enc)
free(data_enc);
if (data_dec)
free(data_dec);
return (res == RK_CRYPTO_SUCCESS) ? 0 : -1;
}
static int test_rsa_tp(void)
{
int res;
uint32_t i;
uint32_t rsa_bits_tbl[] = {
RSA_BITS_1024,
RSA_BITS_2048,
RSA_BITS_3072,
RSA_BITS_4096,
};
if (rk_crypto_init()) {
printf("rk_crypto_init error!\n");
return -1;
}
for (i = 0; i < ARRAY_SIZE(rsa_bits_tbl); i++) {
res = test_rsa_item_tp(rsa_bits_tbl[i]);
if (res) {
printf("test rsa-%u throughput FAIL.\n\n", rsa_bits_tbl[i]);
goto out;
}
}
printf("test rsa throughput SUCCESS.\n\n");
out:
rk_crypto_deinit();
return 0;
}
RK_RES test_throughput(void)
{
if (test_otp_key_tp())
printf("Test otp key throughput FAILED.\n\n");
if (test_cipher_tp())
printf("Test cipher throughput FAILED.\n\n");
if (test_ae_tp())
printf("Test ae throughput FAILED.\n\n");
if (test_hash_tp())
printf("Test hash throughput FAILED.\n\n");
if (test_rsa_tp())
printf("Test rsa throughput FAILED.\n\n");
printf("Test throughput SUCCESS.\n");
return RK_CRYPTO_SUCCESS;
}