1*3b472e71SThomas Huth /* 2*3b472e71SThomas Huth * QEMU Crypto cipher speed benchmark 3*3b472e71SThomas Huth * 4*3b472e71SThomas Huth * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD. 5*3b472e71SThomas Huth * 6*3b472e71SThomas Huth * Authors: 7*3b472e71SThomas Huth * Longpeng(Mike) <longpeng2@huawei.com> 8*3b472e71SThomas Huth * 9*3b472e71SThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or 10*3b472e71SThomas Huth * (at your option) any later version. See the COPYING file in the 11*3b472e71SThomas Huth * top-level directory. 12*3b472e71SThomas Huth */ 13*3b472e71SThomas Huth #include "qemu/osdep.h" 14*3b472e71SThomas Huth #include "qemu/units.h" 15*3b472e71SThomas Huth #include "crypto/init.h" 16*3b472e71SThomas Huth #include "crypto/cipher.h" 17*3b472e71SThomas Huth 18*3b472e71SThomas Huth static void test_cipher_speed(size_t chunk_size, 19*3b472e71SThomas Huth QCryptoCipherMode mode, 20*3b472e71SThomas Huth QCryptoCipherAlgorithm alg) 21*3b472e71SThomas Huth { 22*3b472e71SThomas Huth QCryptoCipher *cipher; 23*3b472e71SThomas Huth Error *err = NULL; 24*3b472e71SThomas Huth uint8_t *key = NULL, *iv = NULL; 25*3b472e71SThomas Huth uint8_t *plaintext = NULL, *ciphertext = NULL; 26*3b472e71SThomas Huth size_t nkey; 27*3b472e71SThomas Huth size_t niv; 28*3b472e71SThomas Huth const size_t total = 2 * GiB; 29*3b472e71SThomas Huth size_t remain; 30*3b472e71SThomas Huth 31*3b472e71SThomas Huth if (!qcrypto_cipher_supports(alg, mode)) { 32*3b472e71SThomas Huth return; 33*3b472e71SThomas Huth } 34*3b472e71SThomas Huth 35*3b472e71SThomas Huth nkey = qcrypto_cipher_get_key_len(alg); 36*3b472e71SThomas Huth niv = qcrypto_cipher_get_iv_len(alg, mode); 37*3b472e71SThomas Huth if (mode == QCRYPTO_CIPHER_MODE_XTS) { 38*3b472e71SThomas Huth nkey *= 2; 39*3b472e71SThomas Huth } 40*3b472e71SThomas Huth 41*3b472e71SThomas Huth key = g_new0(uint8_t, nkey); 42*3b472e71SThomas Huth memset(key, g_test_rand_int(), nkey); 43*3b472e71SThomas Huth 44*3b472e71SThomas Huth iv = g_new0(uint8_t, niv); 45*3b472e71SThomas Huth memset(iv, g_test_rand_int(), niv); 46*3b472e71SThomas Huth 47*3b472e71SThomas Huth ciphertext = g_new0(uint8_t, chunk_size); 48*3b472e71SThomas Huth 49*3b472e71SThomas Huth plaintext = g_new0(uint8_t, chunk_size); 50*3b472e71SThomas Huth memset(plaintext, g_test_rand_int(), chunk_size); 51*3b472e71SThomas Huth 52*3b472e71SThomas Huth cipher = qcrypto_cipher_new(alg, mode, 53*3b472e71SThomas Huth key, nkey, &err); 54*3b472e71SThomas Huth g_assert(cipher != NULL); 55*3b472e71SThomas Huth 56*3b472e71SThomas Huth if (mode != QCRYPTO_CIPHER_MODE_ECB) 57*3b472e71SThomas Huth g_assert(qcrypto_cipher_setiv(cipher, 58*3b472e71SThomas Huth iv, niv, 59*3b472e71SThomas Huth &err) == 0); 60*3b472e71SThomas Huth 61*3b472e71SThomas Huth g_test_timer_start(); 62*3b472e71SThomas Huth remain = total; 63*3b472e71SThomas Huth while (remain) { 64*3b472e71SThomas Huth g_assert(qcrypto_cipher_encrypt(cipher, 65*3b472e71SThomas Huth plaintext, 66*3b472e71SThomas Huth ciphertext, 67*3b472e71SThomas Huth chunk_size, 68*3b472e71SThomas Huth &err) == 0); 69*3b472e71SThomas Huth remain -= chunk_size; 70*3b472e71SThomas Huth } 71*3b472e71SThomas Huth g_test_timer_elapsed(); 72*3b472e71SThomas Huth 73*3b472e71SThomas Huth g_test_message("enc(%s-%s) chunk %zu bytes %.2f MB/sec ", 74*3b472e71SThomas Huth QCryptoCipherAlgorithm_str(alg), 75*3b472e71SThomas Huth QCryptoCipherMode_str(mode), 76*3b472e71SThomas Huth chunk_size, (double)total / MiB / g_test_timer_last()); 77*3b472e71SThomas Huth 78*3b472e71SThomas Huth g_test_timer_start(); 79*3b472e71SThomas Huth remain = total; 80*3b472e71SThomas Huth while (remain) { 81*3b472e71SThomas Huth g_assert(qcrypto_cipher_decrypt(cipher, 82*3b472e71SThomas Huth plaintext, 83*3b472e71SThomas Huth ciphertext, 84*3b472e71SThomas Huth chunk_size, 85*3b472e71SThomas Huth &err) == 0); 86*3b472e71SThomas Huth remain -= chunk_size; 87*3b472e71SThomas Huth } 88*3b472e71SThomas Huth g_test_timer_elapsed(); 89*3b472e71SThomas Huth 90*3b472e71SThomas Huth g_test_message("dec(%s-%s) chunk %zu bytes %.2f MB/sec ", 91*3b472e71SThomas Huth QCryptoCipherAlgorithm_str(alg), 92*3b472e71SThomas Huth QCryptoCipherMode_str(mode), 93*3b472e71SThomas Huth chunk_size, (double)total / MiB / g_test_timer_last()); 94*3b472e71SThomas Huth 95*3b472e71SThomas Huth qcrypto_cipher_free(cipher); 96*3b472e71SThomas Huth g_free(plaintext); 97*3b472e71SThomas Huth g_free(ciphertext); 98*3b472e71SThomas Huth g_free(iv); 99*3b472e71SThomas Huth g_free(key); 100*3b472e71SThomas Huth } 101*3b472e71SThomas Huth 102*3b472e71SThomas Huth 103*3b472e71SThomas Huth static void test_cipher_speed_ecb_aes_128(const void *opaque) 104*3b472e71SThomas Huth { 105*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 106*3b472e71SThomas Huth test_cipher_speed(chunk_size, 107*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_ECB, 108*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_128); 109*3b472e71SThomas Huth } 110*3b472e71SThomas Huth 111*3b472e71SThomas Huth static void test_cipher_speed_ecb_aes_256(const void *opaque) 112*3b472e71SThomas Huth { 113*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 114*3b472e71SThomas Huth test_cipher_speed(chunk_size, 115*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_ECB, 116*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_256); 117*3b472e71SThomas Huth } 118*3b472e71SThomas Huth 119*3b472e71SThomas Huth static void test_cipher_speed_cbc_aes_128(const void *opaque) 120*3b472e71SThomas Huth { 121*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 122*3b472e71SThomas Huth test_cipher_speed(chunk_size, 123*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CBC, 124*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_128); 125*3b472e71SThomas Huth } 126*3b472e71SThomas Huth 127*3b472e71SThomas Huth static void test_cipher_speed_cbc_aes_256(const void *opaque) 128*3b472e71SThomas Huth { 129*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 130*3b472e71SThomas Huth test_cipher_speed(chunk_size, 131*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CBC, 132*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_256); 133*3b472e71SThomas Huth } 134*3b472e71SThomas Huth 135*3b472e71SThomas Huth static void test_cipher_speed_ctr_aes_128(const void *opaque) 136*3b472e71SThomas Huth { 137*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 138*3b472e71SThomas Huth test_cipher_speed(chunk_size, 139*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CTR, 140*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_128); 141*3b472e71SThomas Huth } 142*3b472e71SThomas Huth 143*3b472e71SThomas Huth static void test_cipher_speed_ctr_aes_256(const void *opaque) 144*3b472e71SThomas Huth { 145*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 146*3b472e71SThomas Huth test_cipher_speed(chunk_size, 147*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_CTR, 148*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_256); 149*3b472e71SThomas Huth } 150*3b472e71SThomas Huth 151*3b472e71SThomas Huth static void test_cipher_speed_xts_aes_128(const void *opaque) 152*3b472e71SThomas Huth { 153*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 154*3b472e71SThomas Huth test_cipher_speed(chunk_size, 155*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_XTS, 156*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_128); 157*3b472e71SThomas Huth } 158*3b472e71SThomas Huth 159*3b472e71SThomas Huth static void test_cipher_speed_xts_aes_256(const void *opaque) 160*3b472e71SThomas Huth { 161*3b472e71SThomas Huth size_t chunk_size = (size_t)opaque; 162*3b472e71SThomas Huth test_cipher_speed(chunk_size, 163*3b472e71SThomas Huth QCRYPTO_CIPHER_MODE_XTS, 164*3b472e71SThomas Huth QCRYPTO_CIPHER_ALG_AES_256); 165*3b472e71SThomas Huth } 166*3b472e71SThomas Huth 167*3b472e71SThomas Huth 168*3b472e71SThomas Huth int main(int argc, char **argv) 169*3b472e71SThomas Huth { 170*3b472e71SThomas Huth char *alg = NULL; 171*3b472e71SThomas Huth char *size = NULL; 172*3b472e71SThomas Huth g_test_init(&argc, &argv, NULL); 173*3b472e71SThomas Huth g_assert(qcrypto_init(NULL) == 0); 174*3b472e71SThomas Huth 175*3b472e71SThomas Huth #define ADD_TEST(mode, cipher, keysize, chunk) \ 176*3b472e71SThomas Huth if ((!alg || g_str_equal(alg, #mode)) && \ 177*3b472e71SThomas Huth (!size || g_str_equal(size, #chunk))) \ 178*3b472e71SThomas Huth g_test_add_data_func( \ 179*3b472e71SThomas Huth "/crypto/cipher/" #mode "-" #cipher "-" #keysize "/chunk-" #chunk, \ 180*3b472e71SThomas Huth (void *)chunk, \ 181*3b472e71SThomas Huth test_cipher_speed_ ## mode ## _ ## cipher ## _ ## keysize) 182*3b472e71SThomas Huth 183*3b472e71SThomas Huth if (argc >= 2) { 184*3b472e71SThomas Huth alg = argv[1]; 185*3b472e71SThomas Huth } 186*3b472e71SThomas Huth if (argc >= 3) { 187*3b472e71SThomas Huth size = argv[2]; 188*3b472e71SThomas Huth } 189*3b472e71SThomas Huth 190*3b472e71SThomas Huth #define ADD_TESTS(chunk) \ 191*3b472e71SThomas Huth do { \ 192*3b472e71SThomas Huth ADD_TEST(ecb, aes, 128, chunk); \ 193*3b472e71SThomas Huth ADD_TEST(ecb, aes, 256, chunk); \ 194*3b472e71SThomas Huth ADD_TEST(cbc, aes, 128, chunk); \ 195*3b472e71SThomas Huth ADD_TEST(cbc, aes, 256, chunk); \ 196*3b472e71SThomas Huth ADD_TEST(ctr, aes, 128, chunk); \ 197*3b472e71SThomas Huth ADD_TEST(ctr, aes, 256, chunk); \ 198*3b472e71SThomas Huth ADD_TEST(xts, aes, 128, chunk); \ 199*3b472e71SThomas Huth ADD_TEST(xts, aes, 256, chunk); \ 200*3b472e71SThomas Huth } while (0) 201*3b472e71SThomas Huth 202*3b472e71SThomas Huth ADD_TESTS(512); 203*3b472e71SThomas Huth ADD_TESTS(4096); 204*3b472e71SThomas Huth ADD_TESTS(16384); 205*3b472e71SThomas Huth ADD_TESTS(65536); 206*3b472e71SThomas Huth 207*3b472e71SThomas Huth return g_test_run(); 208*3b472e71SThomas Huth } 209