benchmark-crypto-cipher.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * QEMU Crypto cipher speed benchmark
  3. *
  4. * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
  5. *
  6. * Authors:
  7. * Longpeng(Mike) <longpeng2@huawei.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. #include "qemu/osdep.h"
  14. #include "qemu/units.h"
  15. #include "crypto/init.h"
  16. #include "crypto/cipher.h"
  17. static void test_cipher_speed(size_t chunk_size,
  18. QCryptoCipherMode mode,
  19. QCryptoCipherAlgorithm alg)
  20. {
  21. QCryptoCipher *cipher;
  22. Error *err = NULL;
  23. uint8_t *key = NULL, *iv = NULL;
  24. uint8_t *plaintext = NULL, *ciphertext = NULL;
  25. size_t nkey;
  26. size_t niv;
  27. const size_t total = 2 * GiB;
  28. size_t remain;
  29. if (!qcrypto_cipher_supports(alg, mode)) {
  30. return;
  31. }
  32. nkey = qcrypto_cipher_get_key_len(alg);
  33. niv = qcrypto_cipher_get_iv_len(alg, mode);
  34. if (mode == QCRYPTO_CIPHER_MODE_XTS) {
  35. nkey *= 2;
  36. }
  37. key = g_new0(uint8_t, nkey);
  38. memset(key, g_test_rand_int(), nkey);
  39. iv = g_new0(uint8_t, niv);
  40. memset(iv, g_test_rand_int(), niv);
  41. ciphertext = g_new0(uint8_t, chunk_size);
  42. plaintext = g_new0(uint8_t, chunk_size);
  43. memset(plaintext, g_test_rand_int(), chunk_size);
  44. cipher = qcrypto_cipher_new(alg, mode,
  45. key, nkey, &err);
  46. g_assert(cipher != NULL);
  47. if (mode != QCRYPTO_CIPHER_MODE_ECB)
  48. g_assert(qcrypto_cipher_setiv(cipher,
  49. iv, niv,
  50. &err) == 0);
  51. g_test_timer_start();
  52. remain = total;
  53. while (remain) {
  54. g_assert(qcrypto_cipher_encrypt(cipher,
  55. plaintext,
  56. ciphertext,
  57. chunk_size,
  58. &err) == 0);
  59. remain -= chunk_size;
  60. }
  61. g_test_timer_elapsed();
  62. g_print("Enc chunk %zu bytes ", chunk_size);
  63. g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last());
  64. g_test_timer_start();
  65. remain = total;
  66. while (remain) {
  67. g_assert(qcrypto_cipher_decrypt(cipher,
  68. plaintext,
  69. ciphertext,
  70. chunk_size,
  71. &err) == 0);
  72. remain -= chunk_size;
  73. }
  74. g_test_timer_elapsed();
  75. g_print("Dec chunk %zu bytes ", chunk_size);
  76. g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last());
  77. qcrypto_cipher_free(cipher);
  78. g_free(plaintext);
  79. g_free(ciphertext);
  80. g_free(iv);
  81. g_free(key);
  82. }
  83. static void test_cipher_speed_ecb_aes_128(const void *opaque)
  84. {
  85. size_t chunk_size = (size_t)opaque;
  86. test_cipher_speed(chunk_size,
  87. QCRYPTO_CIPHER_MODE_ECB,
  88. QCRYPTO_CIPHER_ALG_AES_128);
  89. }
  90. static void test_cipher_speed_ecb_aes_256(const void *opaque)
  91. {
  92. size_t chunk_size = (size_t)opaque;
  93. test_cipher_speed(chunk_size,
  94. QCRYPTO_CIPHER_MODE_ECB,
  95. QCRYPTO_CIPHER_ALG_AES_256);
  96. }
  97. static void test_cipher_speed_cbc_aes_128(const void *opaque)
  98. {
  99. size_t chunk_size = (size_t)opaque;
  100. test_cipher_speed(chunk_size,
  101. QCRYPTO_CIPHER_MODE_CBC,
  102. QCRYPTO_CIPHER_ALG_AES_128);
  103. }
  104. static void test_cipher_speed_cbc_aes_256(const void *opaque)
  105. {
  106. size_t chunk_size = (size_t)opaque;
  107. test_cipher_speed(chunk_size,
  108. QCRYPTO_CIPHER_MODE_CBC,
  109. QCRYPTO_CIPHER_ALG_AES_256);
  110. }
  111. static void test_cipher_speed_ctr_aes_128(const void *opaque)
  112. {
  113. size_t chunk_size = (size_t)opaque;
  114. test_cipher_speed(chunk_size,
  115. QCRYPTO_CIPHER_MODE_CTR,
  116. QCRYPTO_CIPHER_ALG_AES_128);
  117. }
  118. static void test_cipher_speed_ctr_aes_256(const void *opaque)
  119. {
  120. size_t chunk_size = (size_t)opaque;
  121. test_cipher_speed(chunk_size,
  122. QCRYPTO_CIPHER_MODE_CTR,
  123. QCRYPTO_CIPHER_ALG_AES_256);
  124. }
  125. static void test_cipher_speed_xts_aes_128(const void *opaque)
  126. {
  127. size_t chunk_size = (size_t)opaque;
  128. test_cipher_speed(chunk_size,
  129. QCRYPTO_CIPHER_MODE_XTS,
  130. QCRYPTO_CIPHER_ALG_AES_128);
  131. }
  132. static void test_cipher_speed_xts_aes_256(const void *opaque)
  133. {
  134. size_t chunk_size = (size_t)opaque;
  135. test_cipher_speed(chunk_size,
  136. QCRYPTO_CIPHER_MODE_XTS,
  137. QCRYPTO_CIPHER_ALG_AES_256);
  138. }
  139. int main(int argc, char **argv)
  140. {
  141. char *alg = NULL;
  142. char *size = NULL;
  143. g_test_init(&argc, &argv, NULL);
  144. g_assert(qcrypto_init(NULL) == 0);
  145. #define ADD_TEST(mode, cipher, keysize, chunk) \
  146. if ((!alg || g_str_equal(alg, #mode)) && \
  147. (!size || g_str_equal(size, #chunk))) \
  148. g_test_add_data_func( \
  149. "/crypto/cipher/" #mode "-" #cipher "-" #keysize "/chunk-" #chunk, \
  150. (void *)chunk, \
  151. test_cipher_speed_ ## mode ## _ ## cipher ## _ ## keysize)
  152. if (argc >= 2) {
  153. alg = argv[1];
  154. }
  155. if (argc >= 3) {
  156. size = argv[2];
  157. }
  158. #define ADD_TESTS(chunk) \
  159. do { \
  160. ADD_TEST(ecb, aes, 128, chunk); \
  161. ADD_TEST(ecb, aes, 256, chunk); \
  162. ADD_TEST(cbc, aes, 128, chunk); \
  163. ADD_TEST(cbc, aes, 256, chunk); \
  164. ADD_TEST(ctr, aes, 128, chunk); \
  165. ADD_TEST(ctr, aes, 256, chunk); \
  166. ADD_TEST(xts, aes, 128, chunk); \
  167. ADD_TEST(xts, aes, 256, chunk); \
  168. } while (0)
  169. ADD_TESTS(512);
  170. ADD_TESTS(4096);
  171. ADD_TESTS(16384);
  172. ADD_TESTS(65536);
  173. return g_test_run();
  174. }