Tizen 2.0 Release
[external/libgnutls26.git] / src / benchmark.c
1 /*
2  * Copyright (C) 2009, 2010  Free Software Foundation, Inc.
3  *
4  * This file is part of GnuTLS.
5  *
6  * GnuTLS is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuTLS is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see
18  * <http://www.gnu.org/licenses/>.
19  *
20  * Written by Nikos Mavrogiannopoulos <nmav@gnutls.org>.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <gnutls/gnutls.h>
29 #include <gnutls/crypto.h>
30 #include <time.h>
31 #include <signal.h>
32 #include "timespec.h"           /* gnulib gettime */
33
34 static unsigned char data[64 * 1024];
35
36 static int must_finish = 0;
37
38 #if !defined(_WIN32)
39 static void
40 alarm_handler (int signo)
41 {
42   must_finish = 1;
43 }
44 #else
45 #include <windows.h>
46 DWORD WINAPI alarm_handler (LPVOID lpParameter);
47 DWORD WINAPI
48 alarm_handler (LPVOID lpParameter)
49 {
50   HANDLE wtimer = *((HANDLE *) lpParameter);
51   WaitForSingleObject (wtimer, INFINITE);
52   must_finish = 1;
53   return 0;
54 }
55
56 #define W32_ALARM_VARIABLES HANDLE wtimer = NULL, wthread = NULL; \
57   LARGE_INTEGER alarm_timeout
58 #define W32_ALARM_TRIGGER(timeout, leave) { \
59   wtimer = CreateWaitableTimer (NULL, TRUE, NULL); \
60   if (wtimer == NULL) \
61     { \
62       fprintf (stderr, "error: CreateWaitableTimer %u\n", GetLastError ()); \
63       leave; \
64     } \
65   wthread = CreateThread (NULL, 0, alarm_handler, &wtimer, 0, NULL); \
66   if (wthread == NULL) \
67     { \
68       fprintf (stderr, "error: CreateThread %u\n", GetLastError ()); \
69       leave; \
70     } \
71   alarm_timeout.QuadPart = timeout * 10000000; \
72   if (SetWaitableTimer (wtimer, &alarm_timeout, 0, NULL, NULL, FALSE) == 0) \
73     { \
74       fprintf (stderr, "error: SetWaitableTimer %u\n", GetLastError ()); \
75       leave; \
76     } \
77   }
78 #define W32_ALARM_CLEANUP { \
79   if (wtimer != NULL) \
80     CloseHandle (wtimer); \
81   if (wthread != NULL) \
82     CloseHandle (wthread);}
83 #endif
84
85 static void
86 tls_log_func (int level, const char *str)
87 {
88   fprintf (stderr, "|<%d>| %s", level, str);
89 }
90
91 static void
92 value2human (double bytes, double time, double *data, double *speed,
93              char *metric)
94 {
95   if (bytes > 1000 && bytes < 1000 * 1000)
96     {
97       *data = ((double) bytes) / 1000;
98       *speed = *data / time;
99       strcpy (metric, "Kb");
100       return;
101     }
102   else if (bytes >= 1000 * 1000 && bytes < 1000 * 1000 * 1000)
103     {
104       *data = ((double) bytes) / (1000 * 1000);
105       *speed = *data / time;
106       strcpy (metric, "Mb");
107       return;
108     }
109   else if (bytes >= 1000 * 1000 * 1000)
110     {
111       *data = ((double) bytes) / (1000 * 1000 * 1000);
112       *speed = *data / time;
113       strcpy (metric, "Gb");
114       return;
115     }
116   else
117     {
118       *data = (double) bytes;
119       *speed = *data / time;
120       strcpy (metric, "bytes");
121       return;
122     }
123 }
124
125 static void
126 cipher_bench (int algo, int size)
127 {
128   int ret;
129   gnutls_cipher_hd_t ctx;
130   void *_key, *_iv;
131   gnutls_datum_t key, iv;
132   struct timespec start, stop;
133   double secs;
134   double data_size = 0;
135   double dspeed, ddata;
136   int blocksize = gnutls_cipher_get_block_size (algo);
137   int keysize = gnutls_cipher_get_key_size (algo);
138   char metric[16];
139 #if defined(_WIN32)
140   W32_ALARM_VARIABLES;
141 #endif
142
143   _key = malloc (keysize);
144   if (_key == NULL)
145     return;
146   memset (_key, 0xf0, keysize);
147
148   _iv = malloc (blocksize);
149   if (_iv == NULL)
150     return;
151   memset (_iv, 0xf0, blocksize);
152
153   iv.data = _iv;
154   iv.size = blocksize;
155
156   key.data = _key;
157   key.size = keysize;
158
159   printf ("Checking %s (%dkb payload)... ", gnutls_cipher_get_name (algo),
160           size);
161   fflush (stdout);
162
163   must_finish = 0;
164 #if !defined(_WIN32)
165   alarm (5);
166 #else
167   W32_ALARM_TRIGGER(5, goto leave);
168 #endif
169
170   gettime (&start);
171
172   ret = gnutls_cipher_init (&ctx, algo, &key, &iv);
173   if (ret < 0)
174     {
175       fprintf (stderr, "error: %s\n", gnutls_strerror (ret));
176       goto leave;
177     }
178
179   do
180     {
181       gnutls_cipher_encrypt (ctx, data, size * 1024);
182       data_size += size * 1024;
183     }
184   while (must_finish == 0);
185
186   gnutls_cipher_deinit (ctx);
187
188   gettime (&stop);
189
190   secs = (stop.tv_sec * 1000 + stop.tv_nsec / (1000 * 1000) -
191           (start.tv_sec * 1000 + start.tv_nsec / (1000 * 1000)));
192   secs /= 1000;
193
194   value2human (data_size, secs, &ddata, &dspeed, metric);
195   printf ("Encrypted %.2f %s in %.2f secs: ", ddata, metric, secs);
196   printf ("%.2f %s/sec\n", dspeed, metric);
197
198 leave:
199   free (_key);
200   free (_iv);
201 #if defined(_WIN32)
202   W32_ALARM_CLEANUP;
203 #endif
204 }
205
206 static void
207 mac_bench (int algo, int size)
208 {
209   void *_key;
210   struct timespec start, stop;
211   double secs;
212   double data_size = 0;
213   double ddata, dspeed;
214   int blocksize = gnutls_hmac_get_len (algo);
215   char metric[16];
216 #if defined(_WIN32)
217   W32_ALARM_VARIABLES;
218 #endif
219
220   _key = malloc (blocksize);
221   if (_key == NULL)
222     return;
223   memset (_key, 0xf0, blocksize);
224
225   printf ("Checking %s (%dkb payload)... ", gnutls_mac_get_name (algo), size);
226   fflush (stdout);
227
228   must_finish = 0;
229 #if !defined(_WIN32)
230   alarm (5);
231 #else
232   W32_ALARM_TRIGGER(5, goto leave);
233 #endif
234
235   gettime (&start);
236
237   do
238     {
239       gnutls_hmac_fast (algo, _key, blocksize, data, size * 1024, _key);
240       data_size += size * 1024;
241     }
242   while (must_finish == 0);
243
244   gettime (&stop);
245
246   secs =
247     (stop.tv_sec * 1000 + stop.tv_nsec / (1000 * 1000) -
248      (start.tv_sec * 1000 + start.tv_nsec / (1000 * 1000)));
249   secs /= 1000;
250
251   value2human (data_size, secs, &ddata, &dspeed, metric);
252
253   printf ("Hashed %.2f %s in %.2f secs: ", ddata, metric, secs);
254   printf ("%.2f %s/sec\n", dspeed, metric);
255 #if defined(_WIN32)
256 leave:
257   W32_ALARM_CLEANUP;
258 #endif
259   free (_key);
260 }
261
262 int
263 main (int argc, char **argv)
264 {
265   int debug_level = 0;
266
267   if (argc > 1)
268     debug_level = 2;
269
270 #if !defined(_WIN32)
271   signal (SIGALRM, alarm_handler);
272 #endif
273
274   gnutls_global_set_log_function (tls_log_func);
275   gnutls_global_set_log_level (debug_level);
276   gnutls_global_init ();
277
278   mac_bench (GNUTLS_MAC_SHA1, 4);
279   mac_bench (GNUTLS_MAC_SHA1, 8);
280   mac_bench (GNUTLS_MAC_SHA1, 16);
281
282   mac_bench (GNUTLS_MAC_SHA256, 4);
283   mac_bench (GNUTLS_MAC_SHA256, 8);
284   mac_bench (GNUTLS_MAC_SHA256, 16);
285
286   cipher_bench (GNUTLS_CIPHER_3DES_CBC, 4);
287   cipher_bench (GNUTLS_CIPHER_3DES_CBC, 8);
288   cipher_bench (GNUTLS_CIPHER_3DES_CBC, 16);
289
290   cipher_bench (GNUTLS_CIPHER_AES_128_CBC, 4);
291   cipher_bench (GNUTLS_CIPHER_AES_128_CBC, 8);
292   cipher_bench (GNUTLS_CIPHER_AES_128_CBC, 16);
293
294   cipher_bench (GNUTLS_CIPHER_ARCFOUR, 4);
295   cipher_bench (GNUTLS_CIPHER_ARCFOUR, 8);
296   cipher_bench (GNUTLS_CIPHER_ARCFOUR, 16);
297
298   return 0;
299 }