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