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 QCryptoRSAPaddingAlgorithm padding, 24 QCryptoHashAlgorithm hash) 25 { 26 QCryptoAkCipherOptions opt; 27 QCryptoAkCipher *rsa; 28 29 opt.alg = QCRYPTO_AKCIPHER_ALG_RSA; 30 opt.u.rsa.padding_alg = padding; 31 opt.u.rsa.hash_alg = hash; 32 rsa = qcrypto_akcipher_new(&opt, QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE, 33 priv_key, keylen, &error_abort); 34 return rsa; 35 } 36 37 static void test_rsa_speed(const uint8_t *priv_key, size_t keylen, 38 size_t key_size) 39 { 40 #define BYTE 8 41 #define SHA1_DGST_LEN 20 42 #define SIGN_TIMES 10000 43 #define VERIFY_TIMES 100000 44 #define PADDING QCRYPTO_RSA_PADDING_ALG_PKCS1 45 #define HASH QCRYPTO_HASH_ALG_SHA1 46 47 g_autoptr(QCryptoAkCipher) rsa = 48 create_rsa_akcipher(priv_key, keylen, PADDING, HASH); 49 g_autofree uint8_t *dgst = NULL; 50 g_autofree uint8_t *signature = NULL; 51 size_t count; 52 53 dgst = g_new0(uint8_t, SHA1_DGST_LEN); 54 memset(dgst, g_test_rand_int(), SHA1_DGST_LEN); 55 signature = g_new0(uint8_t, key_size / BYTE); 56 57 g_test_message("benchmark rsa%zu (%s-%s) sign...", key_size, 58 QCryptoRSAPaddingAlgorithm_str(PADDING), 59 QCryptoHashAlgorithm_str(HASH)); 60 g_test_timer_start(); 61 for (count = 0; count < SIGN_TIMES; ++count) { 62 g_assert(qcrypto_akcipher_sign(rsa, dgst, SHA1_DGST_LEN, 63 signature, key_size / BYTE, 64 &error_abort) > 0); 65 } 66 g_test_timer_elapsed(); 67 g_test_message("rsa%zu (%s-%s) sign %zu times in %.2f seconds," 68 " %.2f times/sec ", 69 key_size, QCryptoRSAPaddingAlgorithm_str(PADDING), 70 QCryptoHashAlgorithm_str(HASH), 71 count, g_test_timer_last(), 72 (double)count / g_test_timer_last()); 73 74 g_test_message("benchmark rsa%zu (%s-%s) verification...", key_size, 75 QCryptoRSAPaddingAlgorithm_str(PADDING), 76 QCryptoHashAlgorithm_str(HASH)); 77 g_test_timer_start(); 78 for (count = 0; count < VERIFY_TIMES; ++count) { 79 g_assert(qcrypto_akcipher_verify(rsa, signature, key_size / BYTE, 80 dgst, SHA1_DGST_LEN, 81 &error_abort) == 0); 82 } 83 g_test_timer_elapsed(); 84 g_test_message("rsa%zu (%s-%s) verify %zu times in %.2f seconds," 85 " %.2f times/sec ", 86 key_size, QCryptoRSAPaddingAlgorithm_str(PADDING), 87 QCryptoHashAlgorithm_str(HASH), 88 count, g_test_timer_last(), 89 (double)count / g_test_timer_last()); 90 } 91 92 static void test_rsa_1024_speed(const void *opaque) 93 { 94 size_t key_size = (size_t)opaque; 95 test_rsa_speed(rsa1024_priv_key, sizeof(rsa1024_priv_key), key_size); 96 } 97 98 static void test_rsa_2048_speed(const void *opaque) 99 { 100 size_t key_size = (size_t)opaque; 101 test_rsa_speed(rsa2048_priv_key, sizeof(rsa2048_priv_key), key_size); 102 } 103 104 static void test_rsa_4096_speed(const void *opaque) 105 { 106 size_t key_size = (size_t)opaque; 107 test_rsa_speed(rsa4096_priv_key, sizeof(rsa4096_priv_key), key_size); 108 } 109 110 int main(int argc, char **argv) 111 { 112 char *alg = NULL; 113 char *size = NULL; 114 g_test_init(&argc, &argv, NULL); 115 g_assert(qcrypto_init(NULL) == 0); 116 117 #define ADD_TEST(asym_alg, keysize) \ 118 if ((!alg || g_str_equal(alg, #asym_alg)) && \ 119 (!size || g_str_equal(size, #keysize))) \ 120 g_test_add_data_func( \ 121 "/crypto/akcipher/" #asym_alg "-" #keysize, \ 122 (void *)keysize, \ 123 test_ ## asym_alg ## _ ## keysize ## _speed) 124 125 if (argc >= 2) { 126 alg = argv[1]; 127 } 128 if (argc >= 3) { 129 size = argv[2]; 130 } 131 132 ADD_TEST(rsa, 1024); 133 ADD_TEST(rsa, 2048); 134 ADD_TEST(rsa, 4096); 135 136 return g_test_run(); 137 } 138