/* * Copyright (C) 2009, 2010 Free Software Foundation, Inc. * * This file is part of GnuTLS. * * GnuTLS 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 3 of the License, or * (at your option) any later version. * * GnuTLS 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, see * . * * Written by Nikos Mavrogiannopoulos . */ #include #include #include #include #include #include #include #include #include #include "timespec.h" /* gnulib gettime */ static unsigned char data[64 * 1024]; static int must_finish = 0; #if !defined(_WIN32) static void alarm_handler (int signo) { must_finish = 1; } #else #include DWORD WINAPI alarm_handler (LPVOID lpParameter); DWORD WINAPI alarm_handler (LPVOID lpParameter) { HANDLE wtimer = *((HANDLE *) lpParameter); WaitForSingleObject (wtimer, INFINITE); must_finish = 1; return 0; } #define W32_ALARM_VARIABLES HANDLE wtimer = NULL, wthread = NULL; \ LARGE_INTEGER alarm_timeout #define W32_ALARM_TRIGGER(timeout, leave) { \ wtimer = CreateWaitableTimer (NULL, TRUE, NULL); \ if (wtimer == NULL) \ { \ fprintf (stderr, "error: CreateWaitableTimer %u\n", GetLastError ()); \ leave; \ } \ wthread = CreateThread (NULL, 0, alarm_handler, &wtimer, 0, NULL); \ if (wthread == NULL) \ { \ fprintf (stderr, "error: CreateThread %u\n", GetLastError ()); \ leave; \ } \ alarm_timeout.QuadPart = timeout * 10000000; \ if (SetWaitableTimer (wtimer, &alarm_timeout, 0, NULL, NULL, FALSE) == 0) \ { \ fprintf (stderr, "error: SetWaitableTimer %u\n", GetLastError ()); \ leave; \ } \ } #define W32_ALARM_CLEANUP { \ if (wtimer != NULL) \ CloseHandle (wtimer); \ if (wthread != NULL) \ CloseHandle (wthread);} #endif static void tls_log_func (int level, const char *str) { fprintf (stderr, "|<%d>| %s", level, str); } static void value2human (double bytes, double time, double *data, double *speed, char *metric) { if (bytes > 1000 && bytes < 1000 * 1000) { *data = ((double) bytes) / 1000; *speed = *data / time; strcpy (metric, "Kb"); return; } else if (bytes >= 1000 * 1000 && bytes < 1000 * 1000 * 1000) { *data = ((double) bytes) / (1000 * 1000); *speed = *data / time; strcpy (metric, "Mb"); return; } else if (bytes >= 1000 * 1000 * 1000) { *data = ((double) bytes) / (1000 * 1000 * 1000); *speed = *data / time; strcpy (metric, "Gb"); return; } else { *data = (double) bytes; *speed = *data / time; strcpy (metric, "bytes"); return; } } static void cipher_bench (int algo, int size) { int ret; gnutls_cipher_hd_t ctx; void *_key, *_iv; gnutls_datum_t key, iv; struct timespec start, stop; double secs; double data_size = 0; double dspeed, ddata; int blocksize = gnutls_cipher_get_block_size (algo); int keysize = gnutls_cipher_get_key_size (algo); char metric[16]; #if defined(_WIN32) W32_ALARM_VARIABLES; #endif _key = malloc (keysize); if (_key == NULL) return; memset (_key, 0xf0, keysize); _iv = malloc (blocksize); if (_iv == NULL) return; memset (_iv, 0xf0, blocksize); iv.data = _iv; iv.size = blocksize; key.data = _key; key.size = keysize; printf ("Checking %s (%dkb payload)... ", gnutls_cipher_get_name (algo), size); fflush (stdout); must_finish = 0; #if !defined(_WIN32) alarm (5); #else W32_ALARM_TRIGGER(5, goto leave); #endif gettime (&start); ret = gnutls_cipher_init (&ctx, algo, &key, &iv); if (ret < 0) { fprintf (stderr, "error: %s\n", gnutls_strerror (ret)); goto leave; } do { gnutls_cipher_encrypt (ctx, data, size * 1024); data_size += size * 1024; } while (must_finish == 0); gnutls_cipher_deinit (ctx); gettime (&stop); secs = (stop.tv_sec * 1000 + stop.tv_nsec / (1000 * 1000) - (start.tv_sec * 1000 + start.tv_nsec / (1000 * 1000))); secs /= 1000; value2human (data_size, secs, &ddata, &dspeed, metric); printf ("Encrypted %.2f %s in %.2f secs: ", ddata, metric, secs); printf ("%.2f %s/sec\n", dspeed, metric); leave: free (_key); free (_iv); #if defined(_WIN32) W32_ALARM_CLEANUP; #endif } static void mac_bench (int algo, int size) { void *_key; struct timespec start, stop; double secs; double data_size = 0; double ddata, dspeed; int blocksize = gnutls_hmac_get_len (algo); char metric[16]; #if defined(_WIN32) W32_ALARM_VARIABLES; #endif _key = malloc (blocksize); if (_key == NULL) return; memset (_key, 0xf0, blocksize); printf ("Checking %s (%dkb payload)... ", gnutls_mac_get_name (algo), size); fflush (stdout); must_finish = 0; #if !defined(_WIN32) alarm (5); #else W32_ALARM_TRIGGER(5, goto leave); #endif gettime (&start); do { gnutls_hmac_fast (algo, _key, blocksize, data, size * 1024, _key); data_size += size * 1024; } while (must_finish == 0); gettime (&stop); secs = (stop.tv_sec * 1000 + stop.tv_nsec / (1000 * 1000) - (start.tv_sec * 1000 + start.tv_nsec / (1000 * 1000))); secs /= 1000; value2human (data_size, secs, &ddata, &dspeed, metric); printf ("Hashed %.2f %s in %.2f secs: ", ddata, metric, secs); printf ("%.2f %s/sec\n", dspeed, metric); #if defined(_WIN32) leave: W32_ALARM_CLEANUP; #endif free (_key); } int main (int argc, char **argv) { int debug_level = 0; if (argc > 1) debug_level = 2; #if !defined(_WIN32) signal (SIGALRM, alarm_handler); #endif gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (debug_level); gnutls_global_init (); mac_bench (GNUTLS_MAC_SHA1, 4); mac_bench (GNUTLS_MAC_SHA1, 8); mac_bench (GNUTLS_MAC_SHA1, 16); mac_bench (GNUTLS_MAC_SHA256, 4); mac_bench (GNUTLS_MAC_SHA256, 8); mac_bench (GNUTLS_MAC_SHA256, 16); cipher_bench (GNUTLS_CIPHER_3DES_CBC, 4); cipher_bench (GNUTLS_CIPHER_3DES_CBC, 8); cipher_bench (GNUTLS_CIPHER_3DES_CBC, 16); cipher_bench (GNUTLS_CIPHER_AES_128_CBC, 4); cipher_bench (GNUTLS_CIPHER_AES_128_CBC, 8); cipher_bench (GNUTLS_CIPHER_AES_128_CBC, 16); cipher_bench (GNUTLS_CIPHER_ARCFOUR, 4); cipher_bench (GNUTLS_CIPHER_ARCFOUR, 8); cipher_bench (GNUTLS_CIPHER_ARCFOUR, 16); return 0; }