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
test_cipher_speed(size_t chunk_size,QCryptoCipherMode mode,QCryptoCipherAlgo alg)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
test_cipher_speed_ecb_aes_128(const void * opaque)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
test_cipher_speed_ecb_aes_256(const void * opaque)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
test_cipher_speed_cbc_aes_128(const void * opaque)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
test_cipher_speed_cbc_aes_256(const void * opaque)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
test_cipher_speed_ctr_aes_128(const void * opaque)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
test_cipher_speed_ctr_aes_256(const void * opaque)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
test_cipher_speed_xts_aes_128(const void * opaque)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
test_cipher_speed_xts_aes_256(const void * opaque)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
main(int argc,char ** argv)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