/* * Simple bench mark of AES 128 CBC ciphers * * Copyright (C) 2017 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * To compile: * * # gcc -Wall -Wno-deprecated-declarations -O2 -g \ * `pkg-config --cflags --libs openssl gnutls nettle` \ * `libgcrypt-config --cflags --libs` * -o aesbench aesbench.c * * Use '-DDISABLE_{LIB}' to skip specific libraries */ #include #include #include /* * Compute 4 GB of data in 512 byte chunks. * * Arbitrarily picked to get approx 5-10 seconds of compute on a * circa 2015 vintage Intel CPUs with AESNI instructions available. */ #define ROUNDS 8192000 void report(const char *lib, struct timeval *tv1, struct timeval *tv2) { unsigned long long ms = (((tv2->tv_sec * 1000000ull) + tv2->tv_usec) - ((tv1->tv_sec * 1000000ull) + tv1->tv_usec)) / 1000ull; fprintf(stderr, "%s: %llu MB/s\n", lib, ((ROUNDS * 512ll) / (1024 * 1024)) * 1024 / ms); } #ifndef DISABLE_NETTLE #include "nettle/aes.h" #include "nettle/cbc.h" void bench_nettle(uint8_t *key, uint8_t *iv, size_t keylen, uint8_t *data, size_t datalen) { struct timeval tv1, tv2; struct aes_ctx ctx = {0}; aes_set_encrypt_key(&ctx, keylen, key); gettimeofday(&tv1, NULL); for (size_t i = 0; i < ROUNDS; i++) { cbc_encrypt(&ctx, (nettle_cipher_func *)aes_encrypt, 16, iv, datalen, data, data); } gettimeofday(&tv2, NULL); report("nettle", &tv1, &tv2); } #endif #ifndef DISABLE_GCYPT #include void bench_gcrypt(uint8_t *key, uint8_t *iv, size_t keylen, uint8_t *data, size_t datalen) { struct timeval tv1, tv2; gcry_cipher_hd_t ctx; if (!gcry_check_version(GCRYPT_VERSION)) { abort(); } gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); gcry_cipher_open(&ctx, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(ctx, key, keylen); gcry_cipher_setiv(ctx, iv, keylen); gettimeofday(&tv1, NULL); for (size_t i = 0; i < ROUNDS; i++) { gcry_cipher_encrypt(ctx, data, datalen, data, datalen); } gettimeofday(&tv2, NULL); report("gcrypt", &tv1, &tv2); } #endif #ifndef DISABLE_GNUTLS #include #include void bench_gnutls(uint8_t *key, uint8_t *iv, size_t keylen, uint8_t *data, size_t datalen) { struct timeval tv1, tv2; gnutls_cipher_hd_t ctx; gnutls_datum_t gnkey = { key, keylen }; gnutls_datum_t gniv = { iv, keylen }; gnutls_global_init(); gnutls_cipher_init(&ctx, GNUTLS_CIPHER_AES_128_CBC, &gnkey, &gniv); gettimeofday(&tv1, NULL); for (size_t i = 0; i < ROUNDS; i++) { gnutls_cipher_encrypt(ctx, data, datalen); } gettimeofday(&tv2, NULL); report("gnutls", &tv1, &tv2); } #endif #ifndef DISABLE_OPENSSL #include #include #include void bench_openssl(uint8_t *key, uint8_t *iv, size_t keylen, uint8_t *data, size_t datalen) { struct timeval tv1, tv2; EVP_CIPHER_CTX *ctx; ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); OPENSSL_config(NULL); /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) abort(); /* Initialise the encryption operation. IMPORTANT - ensure you use a key * and IV size appropriate for your cipher * In this example we are using 256 bit AES (i.e. a 256 bit key). The * IV size for *most* modes is the same as the block size. For AES this * xis 128 bits */ if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) abort(); gettimeofday(&tv1, NULL); for (size_t i = 0; i < ROUNDS; i++) { int len; if (1 != EVP_EncryptUpdate(ctx, data, &len, data, datalen)) abort(); } gettimeofday(&tv2, NULL); report("openssl", &tv1, &tv2); } #endif int main(void) { uint8_t key[16]; uint8_t data[512]; uint8_t iv[16]; memset(key, 0x55, sizeof(key)); memset(iv, 0x77, sizeof(iv)); #ifndef DISABLE_NETTLE memset(data, 0x33, sizeof(data)); bench_nettle(key, iv, sizeof(key), data, sizeof(data)); #endif #ifndef DISABLE_GCRYPT memset(data, 0x33, sizeof(data)); bench_gcrypt(key, iv, sizeof(key), data, sizeof(data)); #endif #ifndef DISABLE_GNUTLS memset(data, 0x33, sizeof(data)); bench_gnutls(key, iv, sizeof(key), data, sizeof(data)); #endif #ifndef DISABLE_OPENSSL memset(data, 0x33, sizeof(data)); bench_openssl(key, iv, sizeof(key), data, sizeof(data)); #endif }