Merge branch 'master' of gnunet.org:gnunet
[oweals/gnunet.git] / src / util / perf_crypto_ecc_dlog.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2015 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 */
19 /**
20  * @file util/perf_crypto_ecc_dlog.c
21  * @brief benchmark for ECC DLOG calculation
22  * @author Christian Grothoff
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include <gcrypt.h>
27 #include <gauger.h>
28
29
30 /**
31  * Name of the curve we are using.  Note that we have hard-coded
32  * structs that use 256 bits, so using a bigger curve will require
33  * changes that break stuff badly.  The name of the curve given here
34  * must be agreed by all peers and be supported by libgcrypt.
35  */
36 #define CURVE "Ed25519"
37
38 /**
39  * Maximum value we benchmark dlog for.
40  */
41 #define MAX_FACT (1024 * 1024)
42
43 /**
44  * Maximum memory to use, sqrt(MAX_FACT) is a good choice.
45  */
46 #define MAX_MEM 1024
47
48 /**
49  * How many values do we test?
50  */  
51 #define TEST_ITER 10
52
53 /**
54  * Range of values to use for MATH tests.
55  */  
56 #define MATH_MAX 500000
57
58
59 /**
60  * Do some DLOG operations for testing.
61  *
62  * @param edc context for ECC operations
63  * @param do_dlog #GNUNET_YES if we want to actually do the bencharked operation
64  */
65 static void
66 test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, 
67            int do_dlog)
68 {
69   gcry_mpi_t fact;
70   gcry_mpi_t n;
71   gcry_ctx_t ctx;
72   gcry_mpi_point_t q;
73   gcry_mpi_point_t g;
74   unsigned int i;
75   int x;
76   int iret;
77
78   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
79   g = gcry_mpi_ec_get_point ("g", ctx, 0);
80   GNUNET_assert (NULL != g);
81   n = gcry_mpi_ec_get_mpi ("n", ctx, 0);
82   q = gcry_mpi_point_new (0);
83   fact = gcry_mpi_new (0);
84   for (i=0;i<TEST_ITER;i++)
85   {
86     fprintf (stderr, ".");
87     x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
88                                   MAX_FACT);
89     if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
90                                        2))
91     {
92       gcry_mpi_set_ui (fact, x);
93       gcry_mpi_sub (fact, n, fact);
94       x = - x;
95     }
96     else 
97     {
98       gcry_mpi_set_ui (fact, x);
99     }
100     gcry_mpi_ec_mul (q, fact, g, ctx);
101     if ( (GNUNET_YES == do_dlog) &&
102          (x !=
103           (iret = GNUNET_CRYPTO_ecc_dlog (edc,
104                                           q))) )
105     {
106       fprintf (stderr, 
107                "DLOG failed for value %d (%d)\n", 
108                x,
109                iret);
110       GNUNET_assert (0);
111     }
112   }
113   gcry_mpi_release (fact);
114   gcry_mpi_release (n);
115   gcry_mpi_point_release (g);
116   gcry_mpi_point_release (q);
117   gcry_ctx_release (ctx);
118   fprintf (stderr, "\n");
119 }
120
121
122 int
123 main (int argc, char *argv[])
124 {
125   struct GNUNET_CRYPTO_EccDlogContext *edc;
126   struct GNUNET_TIME_Absolute start;
127   struct GNUNET_TIME_Relative delta;
128
129   if (! gcry_check_version ("1.6.0"))
130   {
131     FPRINTF (stderr,
132              _
133              ("libgcrypt has not the expected version (version %s is required).\n"),
134              "1.6.0");
135     return 0;
136   }
137   if (getenv ("GNUNET_GCRYPT_DEBUG"))
138     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
139   GNUNET_log_setup ("perf-crypto-ecc-dlog", 
140                     "WARNING", 
141                     NULL);
142   start = GNUNET_TIME_absolute_get ();
143   edc = GNUNET_CRYPTO_ecc_dlog_prepare (MAX_FACT,
144                                         MAX_MEM);
145   printf ("DLOG precomputation 1M/1K took %s\n",
146           GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start),
147                                                   GNUNET_YES));
148   GAUGER ("UTIL", "ECC DLOG initialization",
149           GNUNET_TIME_absolute_get_duration
150           (start).rel_value_us / 1000LL, "ms/op");
151   start = GNUNET_TIME_absolute_get ();
152   /* first do a baseline run without the DLOG */
153   test_dlog (edc, GNUNET_NO);
154   delta = GNUNET_TIME_absolute_get_duration (start);
155   start = GNUNET_TIME_absolute_get ();
156   test_dlog (edc, GNUNET_YES);
157   delta = GNUNET_TIME_relative_subtract (GNUNET_TIME_absolute_get_duration (start),
158                                          delta);
159   printf ("%u DLOG calculations took %s\n",
160           TEST_ITER,
161           GNUNET_STRINGS_relative_time_to_string (delta,
162                                                   GNUNET_YES));
163   GAUGER ("UTIL", "ECC DLOG operations",
164           delta.rel_value_us / 1000LL / TEST_ITER, 
165           "ms/op");
166
167   GNUNET_CRYPTO_ecc_dlog_release (edc);
168   return 0;
169 }
170
171 /* end of perf_crypto_ecc_dlog.c */