- test for external iterator
[oweals/gnunet.git] / src / util / test_crypto_ecc.c
1 /*
2      This file is part of GNUnet.
3      (C) 2002-2013 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_ecc.c
23  * @brief testcase for ECC public key crypto
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_signatures.h"
29 #include <gcrypt.h>
30
31 #define ITER 25
32
33 #define KEYFILE "/tmp/test-gnunet-crypto-ecc.key"
34
35 #define PERF GNUNET_YES
36
37
38 static struct GNUNET_CRYPTO_EccPrivateKey *key;
39
40
41 static int
42 testSignVerify ()
43 {
44   struct GNUNET_CRYPTO_EccSignature sig;
45   struct GNUNET_CRYPTO_EccSignaturePurpose purp;
46   struct GNUNET_CRYPTO_EccPublicKey pkey;
47   int i;
48   struct GNUNET_TIME_Absolute start;
49   int ok = GNUNET_OK;
50
51   FPRINTF (stderr, "%s",  "W");
52   GNUNET_CRYPTO_ecc_key_get_public (key, &pkey);
53   start = GNUNET_TIME_absolute_get ();
54   purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
55   purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
56
57   for (i = 0; i < ITER; i++)
58   {
59     FPRINTF (stderr, "%s",  ".");
60     if (GNUNET_SYSERR == GNUNET_CRYPTO_ecc_sign (key, &purp, &sig))
61     {
62       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_ecc_sign returned SYSERR\n");
63       ok = GNUNET_SYSERR;
64       continue;
65     }
66     if (GNUNET_SYSERR ==
67         GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig,
68                                   &pkey))
69     {
70       printf ("GNUNET_CRYPTO_ecc_verify failed!\n");
71       ok = GNUNET_SYSERR;
72       continue;
73     }
74     if (GNUNET_SYSERR !=
75         GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
76                                   &purp, &sig, &pkey))
77     {
78       printf ("GNUNET_CRYPTO_ecc_verify failed to fail!\n");
79       ok = GNUNET_SYSERR;
80       continue;
81     }
82   }
83   printf ("%d ECC sign/verify operations %s\n", ITER,
84           GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES));
85   return ok;
86 }
87
88
89 static int
90 testDeriveSignVerify ()
91 {
92   struct GNUNET_CRYPTO_EccSignature sig;
93   struct GNUNET_CRYPTO_EccSignaturePurpose purp;
94   struct GNUNET_CRYPTO_EccPrivateKey *dpriv;
95   struct GNUNET_CRYPTO_EccPublicKey pkey;
96   struct GNUNET_CRYPTO_EccPublicKey dpub;
97
98   dpriv = GNUNET_CRYPTO_ecc_key_derive (key, "test-derive", "test-CTX");
99   GNUNET_CRYPTO_ecc_key_get_public (key, &pkey);
100   GNUNET_CRYPTO_ecc_public_key_derive (&pkey, "test-derive", "test-CTX", &dpub);
101   purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
102   purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
103
104   if (GNUNET_SYSERR == GNUNET_CRYPTO_ecc_sign (dpriv, &purp, &sig))
105   {
106     FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_ecc_sign returned SYSERR\n");
107     GNUNET_CRYPTO_ecc_key_free (dpriv);
108     return GNUNET_SYSERR;
109   }
110   if (GNUNET_SYSERR ==
111       GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_TEST, 
112                                 &purp, &sig,
113                                 &dpub))
114   {
115     printf ("GNUNET_CRYPTO_ecc_verify failed!\n");
116     GNUNET_CRYPTO_ecc_key_free (dpriv);
117     return GNUNET_SYSERR;
118   }
119   if (GNUNET_SYSERR !=
120       GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_TEST, 
121                                 &purp, &sig,
122                                 &pkey))
123   {
124     printf ("GNUNET_CRYPTO_ecc_verify failed to fail!\n");
125     GNUNET_CRYPTO_ecc_key_free (dpriv);
126     return GNUNET_SYSERR;
127   }
128   if (GNUNET_SYSERR !=
129       GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
130                                 &purp, &sig, &dpub))
131   {
132     printf ("GNUNET_CRYPTO_ecc_verify failed to fail!\n");
133     GNUNET_CRYPTO_ecc_key_free (dpriv);
134     return GNUNET_SYSERR;
135   }
136   GNUNET_CRYPTO_ecc_key_free (dpriv);
137   return GNUNET_OK;
138 }
139
140
141
142
143 #if PERF
144 static int
145 testSignPerformance ()
146 {
147   struct GNUNET_CRYPTO_EccSignaturePurpose purp;
148   struct GNUNET_CRYPTO_EccSignature sig;
149   struct GNUNET_CRYPTO_EccPublicKey pkey;
150   int i;
151   struct GNUNET_TIME_Absolute start;
152   int ok = GNUNET_OK;
153
154   purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
155   purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
156   FPRINTF (stderr, "%s",  "W");
157   GNUNET_CRYPTO_ecc_key_get_public (key, &pkey);
158   start = GNUNET_TIME_absolute_get ();
159   for (i = 0; i < ITER; i++)
160   {
161     FPRINTF (stderr, "%s",  ".");
162     if (GNUNET_SYSERR == GNUNET_CRYPTO_ecc_sign (key, &purp, &sig))
163     {
164       FPRINTF (stderr, "%s",  "GNUNET_CRYPTO_ecc_sign returned SYSERR\n");
165       ok = GNUNET_SYSERR;
166       continue;
167     }
168   }
169   printf ("%d ECC sign operations %s\n", ITER,
170           GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start),
171                                                   GNUNET_YES));
172   return ok;
173 }
174 #endif
175
176
177 static int
178 testCreateFromFile ()
179 {
180   struct GNUNET_CRYPTO_EccPublicKey p1;
181   struct GNUNET_CRYPTO_EccPublicKey p2;
182
183   key = GNUNET_CRYPTO_ecc_key_create_from_file (KEYFILE);
184   GNUNET_assert (NULL != key);
185   GNUNET_CRYPTO_ecc_key_get_public (key, &p1);
186   GNUNET_CRYPTO_ecc_key_free (key);
187   key = GNUNET_CRYPTO_ecc_key_create_from_file (KEYFILE);
188   GNUNET_assert (NULL != key);
189   GNUNET_CRYPTO_ecc_key_get_public (key, &p2);
190   GNUNET_assert (0 == memcmp (&p1, &p2, sizeof (p1)));
191   GNUNET_CRYPTO_ecc_key_free (key);
192   GNUNET_assert (0 == UNLINK (KEYFILE));
193   key = GNUNET_CRYPTO_ecc_key_create_from_file (KEYFILE);
194   GNUNET_assert (NULL != key);
195   GNUNET_CRYPTO_ecc_key_get_public (key, &p2);
196   GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1)));
197   GNUNET_CRYPTO_ecc_key_free (key);
198   return GNUNET_OK;
199 }
200
201
202 static void
203 test_ecdh ()
204 {
205   struct GNUNET_CRYPTO_EccPrivateKey *priv1;
206   struct GNUNET_CRYPTO_EccPrivateKey *priv2;
207   struct GNUNET_CRYPTO_EccPublicKey pub1;
208   struct GNUNET_CRYPTO_EccPublicKey pub2;
209   struct GNUNET_HashCode ecdh1;
210   struct GNUNET_HashCode ecdh2;
211
212   priv1 = GNUNET_CRYPTO_ecc_key_create ();
213   priv2 = GNUNET_CRYPTO_ecc_key_create ();
214   GNUNET_CRYPTO_ecc_key_get_public (priv1, &pub1);
215   GNUNET_CRYPTO_ecc_key_get_public (priv2, &pub2);
216   GNUNET_CRYPTO_ecc_ecdh (priv1, &pub2, &ecdh1);
217   GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &ecdh2);
218   GNUNET_assert (0 == memcmp (&ecdh1, &ecdh2,
219                               sizeof (struct GNUNET_HashCode)));
220   GNUNET_CRYPTO_ecc_key_free (priv1);
221   GNUNET_CRYPTO_ecc_key_free (priv2);
222 }
223
224
225 static void
226 perf_keygen ()
227 {
228   struct GNUNET_TIME_Absolute start;
229   struct GNUNET_CRYPTO_EccPrivateKey *pk;
230   int i;
231
232   start = GNUNET_TIME_absolute_get ();
233   for (i=0;i<10;i++)
234   {
235     fprintf (stderr, ".");
236     pk = GNUNET_CRYPTO_ecc_key_create ();
237     GNUNET_CRYPTO_ecc_key_free (pk);
238   }
239   fprintf (stderr, "\n");
240   printf ("Creating 10 ECC keys took %s\n",
241           GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES));
242 }
243
244
245 int
246 main (int argc, char *argv[])
247 {
248   int failure_count = 0;
249
250   if (! gcry_check_version ("1.5.0"))
251   {
252     FPRINTF (stderr,
253              _
254              ("libgcrypt has not the expected version (version %s is required).\n"),
255              "1.5.0");
256     return 0;
257   }
258   GNUNET_log_setup ("test-crypto-ecc", "WARNING", NULL);
259   key = GNUNET_CRYPTO_ecc_key_create ();
260   if (GNUNET_OK != testDeriveSignVerify ())
261   {
262     failure_count++;
263     fprintf (stderr,
264              "\n\n%d TESTS FAILED!\n\n", failure_count);
265     return -1;
266   }
267 #if PERF
268   if (GNUNET_OK != testSignPerformance ())
269     failure_count++;
270 #endif
271   if (GNUNET_OK != testSignVerify ())
272     failure_count++;
273   GNUNET_CRYPTO_ecc_key_free (key);
274   if (GNUNET_OK != testCreateFromFile ())
275     failure_count++;
276   GNUNET_assert (0 == UNLINK (KEYFILE));
277   test_ecdh ();
278   perf_keygen ();
279
280   if (0 != failure_count)
281   {
282     fprintf (stderr,
283              "\n\n%d TESTS FAILED!\n\n", 
284              failure_count);
285     return -1;
286   }
287   return 0;
288 }
289
290 /* end of test_crypto_ecc.c */