fcaf78612ec1938282889f94341174ca0bb31c63
[oweals/gnunet.git] / src / util / test_crypto_rsa.c
1 /*
2      This file is part of GNUnet.
3      (C) 2002, 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19
20 */
21 /**
22  * @file util/test_crypto_rsa.c
23  * @brief testcase for RSA public key crypto
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_common.h"
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_signatures.h"
30 #include "gnunet_time_lib.h"
31
32 #define TESTSTRING "Hello World\0"
33 #define MAX_TESTVAL sizeof(struct GNUNET_CRYPTO_AesSessionKey)
34 #define ITER 25
35 #define KEYFILE "/tmp/test-gnunet-crypto-rsa.key"
36
37 #define PERF GNUNET_YES
38
39 static struct GNUNET_CRYPTO_RsaPrivateKey *key;
40
41
42 static int
43 testEncryptDecrypt ()
44 {
45   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
46   struct GNUNET_CRYPTO_RsaEncryptedData target;
47   char result[MAX_TESTVAL];
48   int i;
49   struct GNUNET_TIME_Absolute start;
50   int ok;
51
52   FPRINTF (stderr, "%s",  "W");
53   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
54   ok = 0;
55   start = GNUNET_TIME_absolute_get ();
56   for (i = 0; i < ITER; i++)
57   {
58     FPRINTF (stderr, "%s",  ".");
59     if (GNUNET_SYSERR ==
60         GNUNET_CRYPTO_rsa_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, &pkey,
61                                    &target))
62     {
63       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
64       ok++;
65       continue;
66     }
67     if (-1 ==
68         GNUNET_CRYPTO_rsa_decrypt (key, &target, result,
69                                    strlen (TESTSTRING) + 1))
70     {
71       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
72       ok++;
73       continue;
74
75     }
76     if (strncmp (TESTSTRING, result, strlen (TESTSTRING)) != 0)
77     {
78       printf ("%s != %.*s - testEncryptDecrypt failed!\n", TESTSTRING,
79               (int) MAX_TESTVAL, result);
80       ok++;
81       continue;
82     }
83   }
84   printf ("%d RSA encrypt/decrypt operations %s (%d failures)\n", 
85           ITER,
86           GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES), 
87           ok);
88   if (ok == 0)
89     return GNUNET_OK;
90   return GNUNET_SYSERR;
91 }
92
93
94 #if PERF
95 static int
96 testEncryptPerformance ()
97 {
98   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
99   struct GNUNET_CRYPTO_RsaEncryptedData target;
100   int i;
101   struct GNUNET_TIME_Absolute start;
102   int ok;
103
104   FPRINTF (stderr, "%s",  "W");
105   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
106   ok = 0;
107   start = GNUNET_TIME_absolute_get ();
108   for (i = 0; i < ITER; i++)
109   {
110     FPRINTF (stderr, "%s",  ".");
111     if (GNUNET_SYSERR ==
112         GNUNET_CRYPTO_rsa_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, &pkey,
113                                    &target))
114     {
115       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
116       ok++;
117       continue;
118     }
119   }
120   printf ("%d RSA encrypt operations %llu ms (%d failures)\n", ITER,
121           (unsigned long long)
122           GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
123   if (ok != 0)
124     return GNUNET_SYSERR;
125   return GNUNET_OK;
126 }
127 #endif
128
129 static int
130 testEncryptDecryptSK ()
131 {
132   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
133   struct GNUNET_CRYPTO_RsaEncryptedData target;
134   struct GNUNET_CRYPTO_AesSessionKey insk;
135   struct GNUNET_CRYPTO_AesSessionKey outsk;
136   int i;
137   struct GNUNET_TIME_Absolute start;
138   int ok;
139
140   FPRINTF (stderr, "%s",  "W");
141   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
142   ok = 0;
143   start = GNUNET_TIME_absolute_get ();
144   for (i = 0; i < ITER; i++)
145   {
146     FPRINTF (stderr, "%s",  ".");
147     GNUNET_CRYPTO_aes_create_session_key (&insk);
148     if (GNUNET_SYSERR ==
149         GNUNET_CRYPTO_rsa_encrypt (&insk,
150                                    sizeof (struct GNUNET_CRYPTO_AesSessionKey),
151                                    &pkey, &target))
152     {
153       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
154       ok++;
155       continue;
156     }
157     if (-1 ==
158         GNUNET_CRYPTO_rsa_decrypt (key, &target, &outsk,
159                                    sizeof (struct GNUNET_CRYPTO_AesSessionKey)))
160     {
161       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
162       ok++;
163       continue;
164     }
165     if (0 !=
166         memcmp (&insk, &outsk, sizeof (struct GNUNET_CRYPTO_AesSessionKey)))
167     {
168       printf ("testEncryptDecryptSK failed!\n");
169       ok++;
170       continue;
171     }
172   }
173   printf ("%d RSA encrypt/decrypt SK operations %s (%d failures)\n", 
174           ITER,
175           GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES), 
176           ok);
177   if (ok != 0)
178     return GNUNET_SYSERR;
179   return GNUNET_OK;
180 }
181
182
183 static int
184 testSignVerify ()
185 {
186   struct GNUNET_CRYPTO_RsaSignature sig;
187   struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
188   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
189   int i;
190   struct GNUNET_TIME_Absolute start;
191   int ok = GNUNET_OK;
192
193   FPRINTF (stderr, "%s",  "W");
194   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
195   start = GNUNET_TIME_absolute_get ();
196   purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
197   purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
198
199   for (i = 0; i < ITER; i++)
200   {
201     FPRINTF (stderr, "%s",  ".");
202     if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig))
203     {
204       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
205       ok = GNUNET_SYSERR;
206       continue;
207     }
208     if (GNUNET_SYSERR ==
209         GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig,
210                                   &pkey))
211     {
212       printf ("GNUNET_CRYPTO_rsa_verify failed!\n");
213       ok = GNUNET_SYSERR;
214       continue;
215     }
216     if (GNUNET_SYSERR !=
217         GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
218                                   &purp, &sig, &pkey))
219     {
220       printf ("GNUNET_CRYPTO_rsa_verify failed to fail!\n");
221       ok = GNUNET_SYSERR;
222       continue;
223     }
224   }
225   printf ("%d RSA sign/verify operations %s\n", ITER,
226           GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES));
227   return ok;
228 }
229
230
231 #if PERF
232 static int
233 testSignPerformance ()
234 {
235   struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
236   struct GNUNET_CRYPTO_RsaSignature sig;
237   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
238   int i;
239   struct GNUNET_TIME_Absolute start;
240   int ok = GNUNET_OK;
241
242   purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
243   purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
244   FPRINTF (stderr, "%s",  "W");
245   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
246   start = GNUNET_TIME_absolute_get ();
247   for (i = 0; i < ITER; i++)
248   {
249     FPRINTF (stderr, "%s",  ".");
250     if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig))
251     {
252       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
253       ok = GNUNET_SYSERR;
254       continue;
255     }
256   }
257   printf ("%d RSA sign operations %llu ms\n", ITER,
258           (unsigned long long)
259           GNUNET_TIME_absolute_get_duration (start).rel_value);
260   return ok;
261 }
262 #endif
263
264
265 static int
266 testCreateFromFile ()
267 {
268   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p1;
269   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p2;
270
271   key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
272   GNUNET_assert (NULL != key);
273   GNUNET_CRYPTO_rsa_key_get_public (key, &p1);
274   GNUNET_CRYPTO_rsa_key_free (key);
275   key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
276   GNUNET_assert (NULL != key);
277   GNUNET_CRYPTO_rsa_key_get_public (key, &p2);
278   GNUNET_assert (0 == memcmp (&p1, &p2, sizeof (p1)));
279   GNUNET_CRYPTO_rsa_key_free (key);
280   GNUNET_assert (0 == UNLINK (KEYFILE));
281   key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
282   GNUNET_assert (NULL != key);
283   GNUNET_CRYPTO_rsa_key_get_public (key, &p2);
284   GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1)));
285   return GNUNET_OK;
286 }
287
288
289 static void
290 key_cont (void *cls,
291           struct GNUNET_CRYPTO_RsaPrivateKey *pk,
292           const char *emsg)
293 {
294   const char *txt = cls;
295   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub1;
296   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub2;
297
298   GNUNET_assert (0 == strcmp ("ok", txt));
299   GNUNET_CRYPTO_rsa_key_get_public (pk, &pub1);
300   GNUNET_CRYPTO_rsa_key_get_public (key, &pub2);
301   GNUNET_assert (0 == memcmp (&pub1, &pub2, 
302                               sizeof (pub1)));
303   GNUNET_CRYPTO_rsa_key_free (pk);
304 }
305
306
307 static void
308 test_async_creation (void *cls,
309                      const struct GNUNET_SCHEDULER_TaskContext *tc)
310 {
311   struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc;
312
313   gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE,
314                                            &key_cont, 
315                                            (void*) "bug");
316   GNUNET_CRYPTO_rsa_key_create_stop (gc);
317   gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE,
318                                            &key_cont, 
319                                            (void*) "ok");
320 }
321
322
323 int
324 main (int argc, char *argv[])
325 {
326   int failureCount = 0;
327
328   GNUNET_log_setup ("test-crypto-rsa", "WARNING", NULL);
329   GNUNET_CRYPTO_random_disable_entropy_gathering ();
330   if (GNUNET_OK != testCreateFromFile ())
331     failureCount++;
332   GNUNET_SCHEDULER_run (&test_async_creation, NULL);
333 #if PERF
334   if (GNUNET_OK != testEncryptPerformance ())
335     failureCount++;
336   if (GNUNET_OK != testSignPerformance ())
337     failureCount++;
338 #endif
339   if (GNUNET_OK != testEncryptDecryptSK ())
340     failureCount++;
341   if (GNUNET_OK != testEncryptDecrypt ())
342     failureCount++;
343   if (GNUNET_OK != testSignVerify ())
344     failureCount++;
345   GNUNET_CRYPTO_rsa_key_free (key);
346   GNUNET_assert (0 == UNLINK (KEYFILE));
347
348   if (failureCount != 0)
349   {
350     printf ("\n\n%d TESTS FAILED!\n\n", failureCount);
351     return -1;
352   }
353   return 0;
354 }                               /* end of main */