13b472e71SThomas Huth /* 23b472e71SThomas Huth * QEMU Crypto cipher speed benchmark 33b472e71SThomas Huth * 43b472e71SThomas Huth * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD. 53b472e71SThomas Huth * 63b472e71SThomas Huth * Authors: 73b472e71SThomas Huth * Longpeng(Mike) <longpeng2@huawei.com> 83b472e71SThomas Huth * 93b472e71SThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or 103b472e71SThomas Huth * (at your option) any later version. See the COPYING file in the 113b472e71SThomas Huth * top-level directory. 123b472e71SThomas Huth */ 133b472e71SThomas Huth #include "qemu/osdep.h" 143b472e71SThomas Huth #include "qemu/units.h" 153b472e71SThomas Huth #include "crypto/init.h" 163b472e71SThomas Huth #include "crypto/cipher.h" 173b472e71SThomas Huth 183b472e71SThomas Huth static void test_cipher_speed(size_t chunk_size, 193b472e71SThomas Huth QCryptoCipherMode mode, 20*a092c513SMarkus Armbruster QCryptoCipherAlgo alg) 213b472e71SThomas Huth { 223b472e71SThomas Huth QCryptoCipher *cipher; 233b472e71SThomas Huth Error *err = NULL; 243b472e71SThomas Huth uint8_t *key = NULL, *iv = NULL; 253b472e71SThomas Huth uint8_t *plaintext = NULL, *ciphertext = NULL; 263b472e71SThomas Huth size_t nkey; 273b472e71SThomas Huth size_t niv; 283b472e71SThomas Huth const size_t total = 2 * GiB; 293b472e71SThomas Huth size_t remain; 303b472e71SThomas Huth 313b472e71SThomas Huth if (!qcrypto_cipher_supports(alg, mode)) { 323b472e71SThomas Huth return; 333b472e71SThomas Huth } 343b472e71SThomas Huth 353b472e71SThomas Huth nkey = qcrypto_cipher_get_key_len(alg); 363b472e71SThomas Huth niv = qcrypto_cipher_get_iv_len(alg, mode); 373b472e71SThomas Huth if (mode == QCRYPTO_CIPHER_MODE_XTS) { 383b472e71SThomas Huth nkey *= 2; 393b472e71SThomas Huth } 403b472e71SThomas Huth 413b472e71SThomas Huth key = g_new0(uint8_t, nkey); 423b472e71SThomas Huth memset(key, g_test_rand_int(), nkey); 433b472e71SThomas Huth 443b472e71SThomas Huth iv = g_new0(uint8_t, niv); 453b472e71SThomas Huth memset(iv, g_test_rand_int(), niv); 463b472e71SThomas Huth 473b472e71SThomas Huth ciphertext = g_new0(uint8_t, chunk_size); 483b472e71SThomas Huth 493b472e71SThomas Huth plaintext = g_new0(uint8_t, chunk_size); 503b472e71SThomas Huth memset(plaintext, g_test_rand_int(), chunk_size); 513b472e71SThomas Huth 523b472e71SThomas Huth cipher = qcrypto_cipher_new(alg, mode, 533b472e71SThomas Huth key, nkey, &err); 543b472e71SThomas Huth g_assert(cipher != NULL); 553b472e71SThomas Huth 563b472e71SThomas Huth if (mode != QCRYPTO_CIPHER_MODE_ECB) 573b472e71SThomas Huth g_assert(qcrypto_cipher_setiv(cipher, 583b472e71SThomas Huth iv, niv, 593b472e71SThomas Huth &err) == 0); 603b472e71SThomas Huth 613b472e71SThomas Huth g_test_timer_start(); 623b472e71SThomas Huth remain = total; 633b472e71SThomas Huth while (remain) { 643b472e71SThomas Huth g_assert(qcrypto_cipher_encrypt(cipher, 653b472e71SThomas Huth plaintext, 663b472e71SThomas Huth ciphertext, 673b472e71SThomas Huth chunk_size, 683b472e71SThomas Huth &err) == 0); 693b472e71SThomas Huth remain -= chunk_size; 703b472e71SThomas Huth } 713b472e71SThomas Huth g_test_timer_elapsed(); 723b472e71SThomas Huth 733b472e71SThomas Huth g_test_message("enc(%s-%s) chunk %zu bytes %.2f MB/sec ", 74*a092c513SMarkus Armbruster QCryptoCipherAlgo_str(alg), 753b472e71SThomas Huth QCryptoCipherMode_str(mode), 763b472e71SThomas Huth chunk_size, (double)total / MiB / g_test_timer_last()); 773b472e71SThomas Huth 783b472e71SThomas Huth g_test_timer_start(); 793b472e71SThomas Huth remain = total; 803b472e71SThomas Huth while (remain) { 813b472e71SThomas Huth g_assert(qcrypto_cipher_decrypt(cipher, 823b472e71SThomas Huth plaintext, 833b472e71SThomas Huth ciphertext, 843b472e71SThomas Huth chunk_size, 853b472e71SThomas Huth &err) == 0); 863b472e71SThomas Huth remain -= chunk_size; 873b472e71SThomas Huth } 883b472e71SThomas Huth g_test_timer_elapsed(); 893b472e71SThomas Huth 903b472e71SThomas Huth g_test_message("dec(%s-%s) chunk %zu bytes %.2f MB/sec ", 91*a092c513SMarkus Armbruster QCryptoCipherAlgo_str(alg), 923b472e71SThomas Huth QCryptoCipherMode_str(mode), 933b472e71SThomas Huth chunk_size, (double)total / MiB / g_test_timer_last()); 943b472e71SThomas Huth 953b472e71SThomas Huth qcrypto_cipher_free(cipher); 963b472e71SThomas Huth g_free(plaintext); 973b472e71SThomas Huth g_free(ciphertext); 983b472e71SThomas Huth g_free(iv); 993b472e71SThomas Huth g_free(key); 1003b472e71SThomas Huth } 1013b472e71SThomas Huth 1023b472e71SThomas Huth 1033b472e71SThomas Huth static void test_cipher_speed_ecb_aes_128(const void *opaque) 1043b472e71SThomas Huth { 1053b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1063b472e71SThomas Huth test_cipher_speed(chunk_size, 1073b472e71SThomas Huth QCRYPTO_CIPHER_MODE_ECB, 108*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_128); 1093b472e71SThomas Huth } 1103b472e71SThomas Huth 1113b472e71SThomas Huth static void test_cipher_speed_ecb_aes_256(const void *opaque) 1123b472e71SThomas Huth { 1133b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1143b472e71SThomas Huth test_cipher_speed(chunk_size, 1153b472e71SThomas Huth QCRYPTO_CIPHER_MODE_ECB, 116*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_256); 1173b472e71SThomas Huth } 1183b472e71SThomas Huth 1193b472e71SThomas Huth static void test_cipher_speed_cbc_aes_128(const void *opaque) 1203b472e71SThomas Huth { 1213b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1223b472e71SThomas Huth test_cipher_speed(chunk_size, 1233b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CBC, 124*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_128); 1253b472e71SThomas Huth } 1263b472e71SThomas Huth 1273b472e71SThomas Huth static void test_cipher_speed_cbc_aes_256(const void *opaque) 1283b472e71SThomas Huth { 1293b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1303b472e71SThomas Huth test_cipher_speed(chunk_size, 1313b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CBC, 132*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_256); 1333b472e71SThomas Huth } 1343b472e71SThomas Huth 1353b472e71SThomas Huth static void test_cipher_speed_ctr_aes_128(const void *opaque) 1363b472e71SThomas Huth { 1373b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1383b472e71SThomas Huth test_cipher_speed(chunk_size, 1393b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CTR, 140*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_128); 1413b472e71SThomas Huth } 1423b472e71SThomas Huth 1433b472e71SThomas Huth static void test_cipher_speed_ctr_aes_256(const void *opaque) 1443b472e71SThomas Huth { 1453b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1463b472e71SThomas Huth test_cipher_speed(chunk_size, 1473b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CTR, 148*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_256); 1493b472e71SThomas Huth } 1503b472e71SThomas Huth 1513b472e71SThomas Huth static void test_cipher_speed_xts_aes_128(const void *opaque) 1523b472e71SThomas Huth { 1533b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1543b472e71SThomas Huth test_cipher_speed(chunk_size, 1553b472e71SThomas Huth QCRYPTO_CIPHER_MODE_XTS, 156*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_128); 1573b472e71SThomas Huth } 1583b472e71SThomas Huth 1593b472e71SThomas Huth static void test_cipher_speed_xts_aes_256(const void *opaque) 1603b472e71SThomas Huth { 1613b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 1623b472e71SThomas Huth test_cipher_speed(chunk_size, 1633b472e71SThomas Huth QCRYPTO_CIPHER_MODE_XTS, 164*a092c513SMarkus Armbruster QCRYPTO_CIPHER_ALGO_AES_256); 1653b472e71SThomas Huth } 1663b472e71SThomas Huth 1673b472e71SThomas Huth 1683b472e71SThomas Huth int main(int argc, char **argv) 1693b472e71SThomas Huth { 1703b472e71SThomas Huth char *alg = NULL; 1713b472e71SThomas Huth char *size = NULL; 1723b472e71SThomas Huth g_test_init(&argc, &argv, NULL); 1733b472e71SThomas Huth g_assert(qcrypto_init(NULL) == 0); 1743b472e71SThomas Huth 1753b472e71SThomas Huth #define ADD_TEST(mode, cipher, keysize, chunk) \ 1763b472e71SThomas Huth if ((!alg || g_str_equal(alg, #mode)) && \ 1773b472e71SThomas Huth (!size || g_str_equal(size, #chunk))) \ 1783b472e71SThomas Huth g_test_add_data_func( \ 1793b472e71SThomas Huth "/crypto/cipher/" #mode "-" #cipher "-" #keysize "/chunk-" #chunk, \ 1803b472e71SThomas Huth (void *)chunk, \ 1813b472e71SThomas Huth test_cipher_speed_ ## mode ## _ ## cipher ## _ ## keysize) 1823b472e71SThomas Huth 1833b472e71SThomas Huth if (argc >= 2) { 1843b472e71SThomas Huth alg = argv[1]; 1853b472e71SThomas Huth } 1863b472e71SThomas Huth if (argc >= 3) { 1873b472e71SThomas Huth size = argv[2]; 1883b472e71SThomas Huth } 1893b472e71SThomas Huth 1903b472e71SThomas Huth #define ADD_TESTS(chunk) \ 1913b472e71SThomas Huth do { \ 1923b472e71SThomas Huth ADD_TEST(ecb, aes, 128, chunk); \ 1933b472e71SThomas Huth ADD_TEST(ecb, aes, 256, chunk); \ 1943b472e71SThomas Huth ADD_TEST(cbc, aes, 128, chunk); \ 1953b472e71SThomas Huth ADD_TEST(cbc, aes, 256, chunk); \ 1963b472e71SThomas Huth ADD_TEST(ctr, aes, 128, chunk); \ 1973b472e71SThomas Huth ADD_TEST(ctr, aes, 256, chunk); \ 1983b472e71SThomas Huth ADD_TEST(xts, aes, 128, chunk); \ 1993b472e71SThomas Huth ADD_TEST(xts, aes, 256, chunk); \ 2003b472e71SThomas Huth } while (0) 2013b472e71SThomas Huth 2023b472e71SThomas Huth ADD_TESTS(512); 2033b472e71SThomas Huth ADD_TESTS(4096); 2043b472e71SThomas Huth ADD_TESTS(16384); 2053b472e71SThomas Huth ADD_TESTS(65536); 2063b472e71SThomas Huth 2073b472e71SThomas Huth return g_test_run(); 2083b472e71SThomas Huth } 209