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