1 /* 2 * QEMU Crypto akcipher speed benchmark 3 * 4 * Copyright (c) 2022 Bytedance 5 * 6 * Authors: 7 * lei he <helei.sig11@bytedance.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or 10 * (at your option) any later version. See the COPYING file in the 11 * top-level directory. 12 */ 13 14 #include "qemu/osdep.h" 15 #include "crypto/init.h" 16 #include "crypto/akcipher.h" 17 #include "standard-headers/linux/virtio_crypto.h" 18 19 #include "test_akcipher_keys.inc" 20 21 static QCryptoAkCipher *create_rsa_akcipher(const uint8_t *priv_key, 22 size_t keylen, 23 QCryptoRSAPaddingAlgo padding, 24 QCryptoHashAlgo hash) 25 { 26 QCryptoAkCipherOptions opt; 27 28 opt.alg = QCRYPTO_AK_CIPHER_ALGO_RSA; 29 opt.u.rsa.padding_alg = padding; 30 opt.u.rsa.hash_alg = hash; 31 return qcrypto_akcipher_new(&opt, QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE, 32 priv_key, keylen, &error_abort); 33 } 34 35 static void test_rsa_speed(const uint8_t *priv_key, size_t keylen, 36 size_t key_size) 37 { 38 #define BYTE 8 39 #define SHA1_DGST_LEN 20 40 #define SIGN_TIMES 10000 41 #define VERIFY_TIMES 100000 42 #define PADDING QCRYPTO_RSA_PADDING_ALGO_PKCS1 43 #define HASH QCRYPTO_HASH_ALGO_SHA1 44 45 g_autoptr(QCryptoAkCipher) rsa = 46 create_rsa_akcipher(priv_key, keylen, PADDING, HASH); 47 g_autofree uint8_t *dgst = NULL; 48 g_autofree uint8_t *signature = NULL; 49 size_t count; 50 51 dgst = g_new0(uint8_t, SHA1_DGST_LEN); 52 memset(dgst, g_test_rand_int(), SHA1_DGST_LEN); 53 signature = g_new0(uint8_t, key_size / BYTE); 54 55 g_test_message("benchmark rsa%zu (%s-%s) sign...", key_size, 56 QCryptoRSAPaddingAlgo_str(PADDING), 57 QCryptoHashAlgo_str(HASH)); 58 g_test_timer_start(); 59 for (count = 0; count < SIGN_TIMES; ++count) { 60 g_assert(qcrypto_akcipher_sign(rsa, dgst, SHA1_DGST_LEN, 61 signature, key_size / BYTE, 62 &error_abort) > 0); 63 } 64 g_test_timer_elapsed(); 65 g_test_message("rsa%zu (%s-%s) sign %zu times in %.2f seconds," 66 " %.2f times/sec ", 67 key_size, QCryptoRSAPaddingAlgo_str(PADDING), 68 QCryptoHashAlgo_str(HASH), 69 count, g_test_timer_last(), 70 (double)count / g_test_timer_last()); 71 72 g_test_message("benchmark rsa%zu (%s-%s) verification...", key_size, 73 QCryptoRSAPaddingAlgo_str(PADDING), 74 QCryptoHashAlgo_str(HASH)); 75 g_test_timer_start(); 76 for (count = 0; count < VERIFY_TIMES; ++count) { 77 g_assert(qcrypto_akcipher_verify(rsa, signature, key_size / BYTE, 78 dgst, SHA1_DGST_LEN, 79 &error_abort) == 0); 80 } 81 g_test_timer_elapsed(); 82 g_test_message("rsa%zu (%s-%s) verify %zu times in %.2f seconds," 83 " %.2f times/sec ", 84 key_size, QCryptoRSAPaddingAlgo_str(PADDING), 85 QCryptoHashAlgo_str(HASH), 86 count, g_test_timer_last(), 87 (double)count / g_test_timer_last()); 88 } 89 90 static void test_rsa_1024_speed(const void *opaque) 91 { 92 size_t key_size = (size_t)opaque; 93 test_rsa_speed(rsa1024_priv_key, sizeof(rsa1024_priv_key), key_size); 94 } 95 96 static void test_rsa_2048_speed(const void *opaque) 97 { 98 size_t key_size = (size_t)opaque; 99 test_rsa_speed(rsa2048_priv_key, sizeof(rsa2048_priv_key), key_size); 100 } 101 102 static void test_rsa_4096_speed(const void *opaque) 103 { 104 size_t key_size = (size_t)opaque; 105 test_rsa_speed(rsa4096_priv_key, sizeof(rsa4096_priv_key), key_size); 106 } 107 108 int main(int argc, char **argv) 109 { 110 char *alg = NULL; 111 char *size = NULL; 112 g_test_init(&argc, &argv, NULL); 113 g_assert(qcrypto_init(NULL) == 0); 114 115 #define ADD_TEST(asym_alg, keysize) \ 116 if ((!alg || g_str_equal(alg, #asym_alg)) && \ 117 (!size || g_str_equal(size, #keysize))) \ 118 g_test_add_data_func( \ 119 "/crypto/akcipher/" #asym_alg "-" #keysize, \ 120 (void *)keysize, \ 121 test_ ## asym_alg ## _ ## keysize ## _speed) 122 123 if (argc >= 2) { 124 alg = argv[1]; 125 } 126 if (argc >= 3) { 127 size = argv[2]; 128 } 129 130 ADD_TEST(rsa, 1024); 131 ADD_TEST(rsa, 2048); 132 ADD_TEST(rsa, 4096); 133 134 return g_test_run(); 135 } 136