Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / util / test_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
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_dlog.c
23  * @brief testcase for ECC DLOG calculation
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include <gcrypt.h>
29
30
31 /**
32  * Name of the curve we are using.  Note that we have hard-coded
33  * structs that use 256 bits, so using a bigger curve will require
34  * changes that break stuff badly.  The name of the curve given here
35  * must be agreed by all peers and be supported by libgcrypt.
36  */
37 #define CURVE "Ed25519"
38
39 /**
40  * Maximum value we test dlog for.
41  */
42 #define MAX_FACT 100
43
44 /**
45  * Maximum memory to use, sqrt(MAX_FACT) is a good choice.
46  */
47 #define MAX_MEM 10
48
49 /**
50  * How many values do we test?
51  */  
52 #define TEST_ITER 10
53
54 /**
55  * Range of values to use for MATH tests.
56  */  
57 #define MATH_MAX 5
58
59
60 /**
61  * Do some DLOG operations for testing.
62  *
63  * @param edc context for ECC operations
64  */
65 static void
66 test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc)
67 {
68   gcry_mpi_t fact;
69   gcry_mpi_t n;
70   gcry_ctx_t ctx;
71   gcry_mpi_point_t q;
72   gcry_mpi_point_t g;
73   unsigned int i;
74   int x;
75   int iret;
76
77   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
78   g = gcry_mpi_ec_get_point ("g", ctx, 0);
79   GNUNET_assert (NULL != g);
80   n = gcry_mpi_ec_get_mpi ("n", ctx, 0);
81   q = gcry_mpi_point_new (0);
82   fact = gcry_mpi_new (0);
83   for (i=0;i<TEST_ITER;i++)
84   {
85     fprintf (stderr, ".");
86     x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
87                                   MAX_FACT);
88     if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
89                                        2))
90     {
91       gcry_mpi_set_ui (fact, x);
92       gcry_mpi_sub (fact, n, fact);
93       x = - x;
94     }
95     else 
96     {
97       gcry_mpi_set_ui (fact, x);
98     }
99     gcry_mpi_ec_mul (q, fact, g, ctx);
100     if  (x !=
101          (iret = GNUNET_CRYPTO_ecc_dlog (edc,
102                                          q)))
103     {
104       fprintf (stderr, 
105                "DLOG failed for value %d (%d)\n", 
106                x,
107                iret);
108       GNUNET_assert (0);
109     }
110   }
111   gcry_mpi_release (fact);
112   gcry_mpi_release (n);
113   gcry_mpi_point_release (g);
114   gcry_mpi_point_release (q);
115   gcry_ctx_release (ctx);
116   fprintf (stderr, "\n");
117 }
118
119
120 /**
121  * Do some arithmetic operations for testing.
122  *
123  * @param edc context for ECC operations
124  */
125 static void
126 test_math (struct GNUNET_CRYPTO_EccDlogContext *edc)
127 {
128   int i;
129   int j;
130   gcry_mpi_point_t ip;
131   gcry_mpi_point_t jp;
132   gcry_mpi_point_t r;
133   gcry_mpi_point_t ir;
134   gcry_mpi_point_t irj;
135   gcry_mpi_point_t r_inv;
136   gcry_mpi_point_t sum;
137
138   for (i=-MATH_MAX;i<MATH_MAX;i++)
139   {
140     ip = GNUNET_CRYPTO_ecc_dexp (edc, i);
141     for (j=-MATH_MAX;j<MATH_MAX;j++)
142     {
143       fprintf (stderr, ".");
144       jp = GNUNET_CRYPTO_ecc_dexp (edc, j);
145       GNUNET_CRYPTO_ecc_rnd (edc,
146                              &r,
147                              &r_inv);
148       ir = GNUNET_CRYPTO_ecc_add (edc, ip, r);
149       irj = GNUNET_CRYPTO_ecc_add (edc, ir, jp);
150       sum = GNUNET_CRYPTO_ecc_add (edc, irj, r_inv);
151       GNUNET_assert (i + j ==
152                      GNUNET_CRYPTO_ecc_dlog (edc,
153                                              sum));
154       GNUNET_CRYPTO_ecc_free (jp);
155       GNUNET_CRYPTO_ecc_free (ir);
156       GNUNET_CRYPTO_ecc_free (irj);
157       GNUNET_CRYPTO_ecc_free (r);
158       GNUNET_CRYPTO_ecc_free (r_inv);
159       GNUNET_CRYPTO_ecc_free (sum);
160     }
161     GNUNET_CRYPTO_ecc_free (ip);
162   }
163   fprintf (stderr, "\n");
164 }
165
166
167
168 int
169 main (int argc, char *argv[])
170 {
171   struct GNUNET_CRYPTO_EccDlogContext *edc;
172
173   if (! gcry_check_version ("1.6.0"))
174   {
175     FPRINTF (stderr,
176              _
177              ("libgcrypt has not the expected version (version %s is required).\n"),
178              "1.6.0");
179     return 0;
180   }
181   if (getenv ("GNUNET_GCRYPT_DEBUG"))
182     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
183   GNUNET_log_setup ("test-crypto-ecc-dlog", 
184                     "WARNING", 
185                     NULL);
186   edc = GNUNET_CRYPTO_ecc_dlog_prepare (MAX_FACT,
187                                         MAX_MEM);
188   test_dlog (edc);
189   test_math (edc);
190   GNUNET_CRYPTO_ecc_dlog_release (edc);
191   return 0;
192 }
193
194 /* end of test_crypto_ecc_dlog.c */