/* * Copyright (c) 2022 Rockchip Electronics Co. Ltd. */ #include #include #include #include #include #include #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; }