qemu/tests/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_print("Enc chunk %zu bytes ", chunk_size);
  74    g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last());
  75
  76    g_test_timer_start();
  77    remain = total;
  78    while (remain) {
  79        g_assert(qcrypto_cipher_decrypt(cipher,
  80                                        plaintext,
  81                                        ciphertext,
  82                                        chunk_size,
  83                                        &err) == 0);
  84        remain -= chunk_size;
  85    }
  86    g_test_timer_elapsed();
  87
  88    g_print("Dec chunk %zu bytes ", chunk_size);
  89    g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last());
  90
  91    qcrypto_cipher_free(cipher);
  92    g_free(plaintext);
  93    g_free(ciphertext);
  94    g_free(iv);
  95    g_free(key);
  96}
  97
  98
  99static void test_cipher_speed_ecb_aes_128(const void *opaque)
 100{
 101    size_t chunk_size = (size_t)opaque;
 102    test_cipher_speed(chunk_size,
 103                      QCRYPTO_CIPHER_MODE_ECB,
 104                      QCRYPTO_CIPHER_ALG_AES_128);
 105}
 106
 107static void test_cipher_speed_ecb_aes_256(const void *opaque)
 108{
 109    size_t chunk_size = (size_t)opaque;
 110    test_cipher_speed(chunk_size,
 111                      QCRYPTO_CIPHER_MODE_ECB,
 112                      QCRYPTO_CIPHER_ALG_AES_256);
 113}
 114
 115static void test_cipher_speed_cbc_aes_128(const void *opaque)
 116{
 117    size_t chunk_size = (size_t)opaque;
 118    test_cipher_speed(chunk_size,
 119                      QCRYPTO_CIPHER_MODE_CBC,
 120                      QCRYPTO_CIPHER_ALG_AES_128);
 121}
 122
 123static void test_cipher_speed_cbc_aes_256(const void *opaque)
 124{
 125    size_t chunk_size = (size_t)opaque;
 126    test_cipher_speed(chunk_size,
 127                      QCRYPTO_CIPHER_MODE_CBC,
 128                      QCRYPTO_CIPHER_ALG_AES_256);
 129}
 130
 131static void test_cipher_speed_ctr_aes_128(const void *opaque)
 132{
 133    size_t chunk_size = (size_t)opaque;
 134    test_cipher_speed(chunk_size,
 135                      QCRYPTO_CIPHER_MODE_CTR,
 136                      QCRYPTO_CIPHER_ALG_AES_128);
 137}
 138
 139static void test_cipher_speed_ctr_aes_256(const void *opaque)
 140{
 141    size_t chunk_size = (size_t)opaque;
 142    test_cipher_speed(chunk_size,
 143                      QCRYPTO_CIPHER_MODE_CTR,
 144                      QCRYPTO_CIPHER_ALG_AES_256);
 145}
 146
 147static void test_cipher_speed_xts_aes_128(const void *opaque)
 148{
 149    size_t chunk_size = (size_t)opaque;
 150    test_cipher_speed(chunk_size,
 151                      QCRYPTO_CIPHER_MODE_XTS,
 152                      QCRYPTO_CIPHER_ALG_AES_128);
 153}
 154
 155static void test_cipher_speed_xts_aes_256(const void *opaque)
 156{
 157    size_t chunk_size = (size_t)opaque;
 158    test_cipher_speed(chunk_size,
 159                      QCRYPTO_CIPHER_MODE_XTS,
 160                      QCRYPTO_CIPHER_ALG_AES_256);
 161}
 162
 163
 164int main(int argc, char **argv)
 165{
 166    char *alg = NULL;
 167    char *size = NULL;
 168    g_test_init(&argc, &argv, NULL);
 169    g_assert(qcrypto_init(NULL) == 0);
 170
 171#define ADD_TEST(mode, cipher, keysize, chunk)                          \
 172    if ((!alg || g_str_equal(alg, #mode)) &&                            \
 173        (!size || g_str_equal(size, #chunk)))                           \
 174        g_test_add_data_func(                                           \
 175        "/crypto/cipher/" #mode "-" #cipher "-" #keysize "/chunk-" #chunk, \
 176        (void *)chunk,                                                  \
 177        test_cipher_speed_ ## mode ## _ ## cipher ## _ ## keysize)
 178
 179    if (argc >= 2) {
 180        alg = argv[1];
 181    }
 182    if (argc >= 3) {
 183        size = argv[2];
 184    }
 185
 186#define ADD_TESTS(chunk)                        \
 187    do {                                        \
 188        ADD_TEST(ecb, aes, 128, chunk);         \
 189        ADD_TEST(ecb, aes, 256, chunk);         \
 190        ADD_TEST(cbc, aes, 128, chunk);         \
 191        ADD_TEST(cbc, aes, 256, chunk);         \
 192        ADD_TEST(ctr, aes, 128, chunk);         \
 193        ADD_TEST(ctr, aes, 256, chunk);         \
 194        ADD_TEST(xts, aes, 128, chunk);         \
 195        ADD_TEST(xts, aes, 256, chunk);         \
 196    } while (0)
 197
 198    ADD_TESTS(512);
 199    ADD_TESTS(4096);
 200    ADD_TESTS(16384);
 201    ADD_TESTS(65536);
 202
 203    return g_test_run();
 204}
 205