aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-07-06 14:22:51 +0000
committerChristian Grothoff <christian@grothoff.org>2015-07-06 14:22:51 +0000
commit0f9e6bcd1e511abae16ecc4c86056b0c26d73936 (patch)
tree4ba3af76391ee6c67563316de29b6ad8830cd7f2 /src
parentf1e619572751f7652db025f66f119d6a0308114b (diff)
downloadgnunet-0f9e6bcd1e511abae16ecc4c86056b0c26d73936.tar.gz
gnunet-0f9e6bcd1e511abae16ecc4c86056b0c26d73936.zip
-fix non-deterministic peerstore sync failure
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_crypto_lib.h84
-rw-r--r--src/peerstore/gnunet-service-peerstore.c2
-rw-r--r--src/peerstore/test_peerstore_api_sync.c131
-rw-r--r--src/util/crypto_ecc_dlog.c231
-rw-r--r--src/util/crypto_paillier.c2
-rw-r--r--src/util/gnunet-ecc.c13
-rw-r--r--src/util/resolver_api.c5
-rw-r--r--src/util/test_crypto_ecc_dlog.c102
8 files changed, 518 insertions, 52 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 3ee8ea5a7..38a3ab3b6 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -1297,20 +1297,100 @@ GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
1297 unsigned int mem); 1297 unsigned int mem);
1298 1298
1299 1299
1300
1301/** 1300/**
1302 * Calculate ECC discrete logarithm for small factors. 1301 * Calculate ECC discrete logarithm for small factors.
1302 * Opposite of #GNUNET_CRYPTO_ecc_dexp().
1303 * 1303 *
1304 * @param dlc precalculated values, determine range of factors 1304 * @param dlc precalculated values, determine range of factors
1305 * @param input point on the curve to factor 1305 * @param input point on the curve to factor
1306 * @return `dlc->max` if dlog failed, otherwise the factor 1306 * @return `dlc->max` if dlog failed, otherwise the factor
1307 */ 1307 */
1308unsigned int 1308int
1309GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, 1309GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
1310 gcry_mpi_point_t input); 1310 gcry_mpi_point_t input);
1311 1311
1312 1312
1313/** 1313/**
1314 * Multiply the generator g of the elliptic curve by @a val
1315 * to obtain the point on the curve representing @a val.
1316 * Afterwards, point addition will correspond to integer
1317 * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to
1318 * convert a point back to an integer (as long as the
1319 * integer is smaller than the MAX of the @a edc context).
1320 *
1321 * @param edc calculation context for ECC operations
1322 * @param val value to encode into a point
1323 * @return representation of the value as an ECC point,
1324 * must be freed using #GNUNET_CRYPTO_ecc_free()
1325 */
1326gcry_mpi_point_t
1327GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc,
1328 int val);
1329
1330
1331/**
1332 * Multiply the generator g of the elliptic curve by @a val
1333 * to obtain the point on the curve representing @a val.
1334 *
1335 * @param edc calculation context for ECC operations
1336 * @param val (positive) value to encode into a point
1337 * @return representation of the value as an ECC point,
1338 * must be freed using #GNUNET_CRYPTO_ecc_free()
1339 */
1340gcry_mpi_point_t
1341GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc,
1342 gcry_mpi_t val);
1343
1344
1345/**
1346 * Add two points on the elliptic curve.
1347 *
1348 * @param edc calculation context for ECC operations
1349 * @param a some value
1350 * @param b some value
1351 * @return @a a + @a b, must be freed using #GNUNET_CRYPTO_ecc_free()
1352 */
1353gcry_mpi_point_t
1354GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc,
1355 gcry_mpi_point_t a,
1356 gcry_mpi_point_t b);
1357
1358
1359/**
1360 * Obtain a random point on the curve and its
1361 * additive inverse. Both returned values
1362 * must be freed using #GNUNET_CRYPTO_ecc_free().
1363 *
1364 * @param edc calculation context for ECC operations
1365 * @param[out] r set to a random point on the curve
1366 * @param[out] r_inv set to the additive inverse of @a r
1367 */
1368void
1369GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc,
1370 gcry_mpi_point_t *r,
1371 gcry_mpi_point_t *r_inv);
1372
1373
1374/**
1375 * Generate a random value mod n.
1376 *
1377 * @param edc ECC context
1378 * @return random value mod n.
1379 */
1380gcry_mpi_t
1381GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc);
1382
1383
1384/**
1385 * Free a point value returned by the API.
1386 *
1387 * @param p point to free
1388 */
1389void
1390GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p);
1391
1392
1393/**
1314 * Release precalculated values. 1394 * Release precalculated values.
1315 * 1395 *
1316 * @param dlc dlog context 1396 * @param dlc dlog context
diff --git a/src/peerstore/gnunet-service-peerstore.c b/src/peerstore/gnunet-service-peerstore.c
index 99facb0cc..f680c5d14 100644
--- a/src/peerstore/gnunet-service-peerstore.c
+++ b/src/peerstore/gnunet-service-peerstore.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 3 Copyright (C) 2014, 2015 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
diff --git a/src/peerstore/test_peerstore_api_sync.c b/src/peerstore/test_peerstore_api_sync.c
index 2b2d34374..f53aad544 100644
--- a/src/peerstore/test_peerstore_api_sync.c
+++ b/src/peerstore/test_peerstore_api_sync.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 3 Copyright (C) 2015 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -19,26 +19,69 @@
19*/ 19*/
20/** 20/**
21 * @file peerstore/test_peerstore_api_sync.c 21 * @file peerstore/test_peerstore_api_sync.c
22 * @brief testcase for peerstore sync before disconnect feature 22 * @brief testcase for peerstore sync-on-disconnect feature. Stores
23 * a value just before disconnecting, and then checks that
24 * this value is actually stored.
25 * @author Omar Tarabai
26 * @author Christian Grothoff (minor fix, comments)
23 */ 27 */
24#include "platform.h" 28#include "platform.h"
25#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
26#include "gnunet_testing_lib.h" 30#include "gnunet_testing_lib.h"
27#include "gnunet_peerstore_service.h" 31#include "gnunet_peerstore_service.h"
28 32
29static int ok = 1; 33/**
34 * Overall result, 0 for success.
35 */
36static int ok = 404;
30 37
38/**
39 * Configuration we use.
40 */
31static const struct GNUNET_CONFIGURATION_Handle *cfg; 41static const struct GNUNET_CONFIGURATION_Handle *cfg;
32 42
43/**
44 * handle to talk to the peerstore.
45 */
33static struct GNUNET_PEERSTORE_Handle *h; 46static struct GNUNET_PEERSTORE_Handle *h;
34 47
35static char *subsystem = "test_peerstore_api_sync"; 48/**
49 * Subsystem we store the value for.
50 */
51static const char *subsystem = "test_peerstore_api_sync";
52
53/**
54 * Fake PID under which we store the value.
55 */
36static struct GNUNET_PeerIdentity pid; 56static struct GNUNET_PeerIdentity pid;
37static char *key = "test_peerstore_api_store_key";
38static char *val = "test_peerstore_api_store_val";
39 57
58/**
59 * Test key we're storing the test value under.
60 */
61static const char *key = "test_peerstore_api_store_key";
62
63/**
64 * Test value we are storing.
65 */
66static const char *val = "test_peerstore_api_store_val";
67
68
69/**
70 * Function that should be called with the result of the
71 * lookup, and finally once with NULL to signal the end
72 * of the iteration.
73 *
74 * Upon the first call, we set "ok" to success. On the
75 * second call (end of iteration) we terminate the test.
76 *
77 * @param cls NULL
78 * @param record the information stored in the peerstore
79 * @param emsg any error message
80 * @return #GNUNET_YES (all good, continue)
81 */
40static int 82static int
41iterate_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, 83iterate_cb (void *cls,
84 const struct GNUNET_PEERSTORE_Record *record,
42 const char *emsg) 85 const char *emsg)
43{ 86{
44 const char *rec_val; 87 const char *rec_val;
@@ -46,7 +89,8 @@ iterate_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record,
46 GNUNET_break (NULL == emsg); 89 GNUNET_break (NULL == emsg);
47 if (NULL == record) 90 if (NULL == record)
48 { 91 {
49 GNUNET_PEERSTORE_disconnect (h, GNUNET_NO); 92 GNUNET_PEERSTORE_disconnect (h,
93 GNUNET_NO);
50 GNUNET_SCHEDULER_shutdown (); 94 GNUNET_SCHEDULER_shutdown ();
51 return GNUNET_YES; 95 return GNUNET_YES;
52 } 96 }
@@ -57,25 +101,68 @@ iterate_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record,
57} 101}
58 102
59 103
104/**
105 * Run the 2nd stage of the test where we fetch the
106 * data that should have been stored.
107 *
108 * @param cls NULL
109 * @param tc unused
110 */
111static void
112test_cont (void *cls,
113 const struct GNUNET_SCHEDULER_TaskContext *tc)
114{
115 h = GNUNET_PEERSTORE_connect (cfg);
116 GNUNET_PEERSTORE_iterate (h,
117 subsystem,
118 &pid, key,
119 GNUNET_TIME_UNIT_FOREVER_REL,
120 &iterate_cb, NULL);
121}
122
123
124/**
125 * Actually run the test.
126 */
60static void 127static void
61test1 () 128test1 ()
62{ 129{
63 GNUNET_PEERSTORE_store (h, subsystem, &pid, key, val, strlen (val) + 1,
64 GNUNET_TIME_UNIT_FOREVER_ABS,
65 GNUNET_PEERSTORE_STOREOPTION_REPLACE, NULL, NULL);
66 GNUNET_PEERSTORE_disconnect (h, GNUNET_YES);
67 h = GNUNET_PEERSTORE_connect (cfg); 130 h = GNUNET_PEERSTORE_connect (cfg);
68 GNUNET_PEERSTORE_iterate (h, subsystem, &pid, key, 131 GNUNET_PEERSTORE_store (h,
69 GNUNET_TIME_UNIT_FOREVER_REL, &iterate_cb, NULL); 132 subsystem,
133 &pid,
134 key,
135 val, strlen (val) + 1,
136 GNUNET_TIME_UNIT_FOREVER_ABS,
137 GNUNET_PEERSTORE_STOREOPTION_REPLACE,
138 NULL, NULL);
139 GNUNET_PEERSTORE_disconnect (h,
140 GNUNET_YES);
141 h = NULL;
142 /* We need to wait a little bit to give the disconnect
143 a chance to actually finish the operation; otherwise,
144 the test may fail non-deterministically if the new
145 connection is faster than the cleanup routine of the
146 old one. */
147 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
148 &test_cont,
149 NULL);
70} 150}
71 151
72 152
153/**
154 * Initialize globals and launch the test.
155 *
156 * @param cls NULL
157 * @param c configuration to use
158 * @param peer handle to our peer (unused)
159 */
73static void 160static void
74run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, 161run (void *cls,
162 const struct GNUNET_CONFIGURATION_Handle *c,
75 struct GNUNET_TESTING_Peer *peer) 163 struct GNUNET_TESTING_Peer *peer)
76{ 164{
77 cfg = c; 165 cfg = c;
78 h = GNUNET_PEERSTORE_connect (cfg);
79 GNUNET_assert (NULL != h); 166 GNUNET_assert (NULL != h);
80 memset (&pid, 1, sizeof (pid)); 167 memset (&pid, 1, sizeof (pid));
81 test1 (); 168 test1 ();
@@ -86,10 +173,16 @@ int
86main (int argc, char *argv[]) 173main (int argc, char *argv[])
87{ 174{
88 if (0 != 175 if (0 !=
89 GNUNET_TESTING_service_run ("test-gnunet-peerstore", "peerstore", 176 GNUNET_TESTING_service_run ("test-gnunet-peerstore-sync",
90 "test_peerstore_api_data.conf", &run, NULL)) 177 "peerstore",
178 "test_peerstore_api_data.conf",
179 &run, NULL))
91 return 1; 180 return 1;
181 if (0 != ok)
182 fprintf (stderr,
183 "Test failed: %d\n",
184 ok).
92 return ok; 185 return ok;
93} 186}
94 187
95/* end of test_peerstore_api_store.c */ 188/* end of test_peerstore_api_sync.c */
diff --git a/src/util/crypto_ecc_dlog.c b/src/util/crypto_ecc_dlog.c
index 34f3c203d..3a2a91532 100644
--- a/src/util/crypto_ecc_dlog.c
+++ b/src/util/crypto_ecc_dlog.c
@@ -20,11 +20,10 @@
20 20
21/** 21/**
22 * @file util/crypto_ecc_dlog.c 22 * @file util/crypto_ecc_dlog.c
23 * @brief ECC discreate logarithm for small values 23 * @brief ECC addition and discreate logarithm for small values.
24 * Allows us to use ECC for computations as long as the
25 * result is relativey small.
24 * @author Christian Grothoff 26 * @author Christian Grothoff
25 *
26 * TODO:
27 * - support negative factors
28 */ 27 */
29#include "platform.h" 28#include "platform.h"
30#include <gcrypt.h> 29#include <gcrypt.h>
@@ -66,9 +65,27 @@ extract_pk (gcry_mpi_point_t pt,
66 */ 65 */
67struct GNUNET_CRYPTO_EccDlogContext 66struct GNUNET_CRYPTO_EccDlogContext
68{ 67{
68 /**
69 * Maximum absolute value the calculation supports.
70 */
69 unsigned int max; 71 unsigned int max;
72
73 /**
74 * How much memory should we use (relates to the number of entries in the map).
75 */
70 unsigned int mem; 76 unsigned int mem;
77
78 /**
79 * Map mapping points (here "interpreted" as EdDSA public keys) to
80 * a "void * = long" which corresponds to the numeric value of the
81 * point. As NULL is used to represent "unknown", the actual value
82 * represented by the entry in the map is the "long" minus @e max.
83 */
71 struct GNUNET_CONTAINER_MultiPeerMap *map; 84 struct GNUNET_CONTAINER_MultiPeerMap *map;
85
86 /**
87 * Context to use for operations on the elliptic curve.
88 */
72 gcry_ctx_t ctx; 89 gcry_ctx_t ctx;
73 90
74}; 91};
@@ -91,8 +108,10 @@ GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
91 struct GNUNET_PeerIdentity key; 108 struct GNUNET_PeerIdentity key;
92 gcry_mpi_point_t gKi; 109 gcry_mpi_point_t gKi;
93 gcry_mpi_t fact; 110 gcry_mpi_t fact;
111 gcry_mpi_t n;
94 unsigned int i; 112 unsigned int i;
95 113
114 GNUNET_assert (max < INT32_MAX);
96 edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); 115 edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext);
97 edc->max = max; 116 edc->max = max;
98 edc->mem = mem; 117 edc->mem = mem;
@@ -115,10 +134,25 @@ GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
115 GNUNET_assert (GNUNET_OK == 134 GNUNET_assert (GNUNET_OK ==
116 GNUNET_CONTAINER_multipeermap_put (edc->map, 135 GNUNET_CONTAINER_multipeermap_put (edc->map,
117 &key, 136 &key,
118 (void*) (long) i + 1, 137 (void*) (long) i + max,
138 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
139 }
140 /* negative values */
141 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
142 for (i=1;i<mem;i++)
143 {
144 gcry_mpi_set_ui (fact, i * K);
145 gcry_mpi_sub (fact, n, fact);
146 gcry_mpi_ec_mul (gKi, fact, g, edc->ctx);
147 extract_pk (gKi, edc->ctx, &key);
148 GNUNET_assert (GNUNET_OK ==
149 GNUNET_CONTAINER_multipeermap_put (edc->map,
150 &key,
151 (void*) (long) max - i,
119 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 152 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
120 } 153 }
121 gcry_mpi_release (fact); 154 gcry_mpi_release (fact);
155 gcry_mpi_release (n);
122 gcry_mpi_point_release (gKi); 156 gcry_mpi_point_release (gKi);
123 gcry_mpi_point_release (g); 157 gcry_mpi_point_release (g);
124 return edc; 158 return edc;
@@ -132,7 +166,7 @@ GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
132 * @param input point on the curve to factor 166 * @param input point on the curve to factor
133 * @return `edc->max` if dlog failed, otherwise the factor 167 * @return `edc->max` if dlog failed, otherwise the factor
134 */ 168 */
135unsigned int 169int
136GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, 170GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
137 gcry_mpi_point_t input) 171 gcry_mpi_point_t input)
138{ 172{
@@ -141,7 +175,7 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
141 struct GNUNET_PeerIdentity key; 175 struct GNUNET_PeerIdentity key;
142 gcry_mpi_point_t q; 176 gcry_mpi_point_t q;
143 unsigned int i; 177 unsigned int i;
144 unsigned int res; 178 int res;
145 void *retp; 179 void *retp;
146 180
147 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); 181 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
@@ -159,10 +193,10 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
159 &key); 193 &key);
160 if (NULL != retp) 194 if (NULL != retp)
161 { 195 {
162 res = (((long) retp) - 1) * K - i; 196 res = (((long) retp) - edc->max) * K - i;
163 fprintf (stderr, 197 /* we continue the loop here to make the implementation
164 "Got DLOG %u\n", 198 "constant-time". If we do not care about this, we could just
165 res); 199 'break' here and do fewer operations... */
166 } 200 }
167 if (i == edc->max/edc->mem) 201 if (i == edc->max/edc->mem)
168 break; 202 break;
@@ -180,6 +214,40 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
180 214
181 215
182/** 216/**
217 * Generate a random value mod n.
218 *
219 * @param edc ECC context
220 * @return random value mod n.
221 */
222gcry_mpi_t
223GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc)
224{
225 gcry_mpi_t n;
226 unsigned int highbit;
227 gcry_mpi_t r;
228
229 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
230
231 /* check public key for number of bits, bail out if key is all zeros */
232 highbit = 256; /* Curve25519 */
233 while ( (! gcry_mpi_test_bit (n, highbit)) &&
234 (0 != highbit) )
235 highbit--;
236 GNUNET_assert (0 != highbit);
237 /* generate fact < n (without bias) */
238 GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
239 do {
240 gcry_mpi_randomize (r,
241 highbit + 1,
242 GCRY_STRONG_RANDOM);
243 }
244 while (gcry_mpi_cmp (r, n) >= 0);
245 gcry_mpi_release (n);
246 return r;
247}
248
249
250/**
183 * Release precalculated values. 251 * Release precalculated values.
184 * 252 *
185 * @param edc dlog context 253 * @param edc dlog context
@@ -191,6 +259,147 @@ GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *edc)
191 GNUNET_CONTAINER_multipeermap_destroy (edc->map); 259 GNUNET_CONTAINER_multipeermap_destroy (edc->map);
192 GNUNET_free (edc); 260 GNUNET_free (edc);
193} 261}
262
263
264/**
265 * Multiply the generator g of the elliptic curve by @a val
266 * to obtain the point on the curve representing @a val.
267 * Afterwards, point addition will correspond to integer
268 * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to
269 * convert a point back to an integer (as long as the
270 * integer is smaller than the MAX of the @a edc context).
271 *
272 * @param edc calculation context for ECC operations
273 * @param val value to encode into a point
274 * @return representation of the value as an ECC point,
275 * must be freed using #GNUNET_CRYPTO_ecc_free()
276 */
277gcry_mpi_point_t
278GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc,
279 int val)
280{
281 gcry_mpi_t fact;
282 gcry_mpi_t n;
283 gcry_mpi_point_t g;
284 gcry_mpi_point_t r;
285
286 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
287 GNUNET_assert (NULL != g);
288 fact = gcry_mpi_new (0);
289 if (val < 0)
290 {
291 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
292 gcry_mpi_set_ui (fact, - val);
293 gcry_mpi_sub (fact, n, fact);
294 gcry_mpi_release (n);
295 }
296 else
297 {
298 gcry_mpi_set_ui (fact, val);
299 }
300 r = gcry_mpi_point_new (0);
301 gcry_mpi_ec_mul (r, fact, g, edc->ctx);
302 gcry_mpi_release (fact);
303 gcry_mpi_point_release (g);
304 return r;
305}
306
307
308/**
309 * Multiply the generator g of the elliptic curve by @a val
310 * to obtain the point on the curve representing @a val.
311 *
312 * @param edc calculation context for ECC operations
313 * @param val (positive) value to encode into a point
314 * @return representation of the value as an ECC point,
315 * must be freed using #GNUNET_CRYPTO_ecc_free()
316 */
317gcry_mpi_point_t
318GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc,
319 gcry_mpi_t val)
320{
321 gcry_mpi_point_t g;
322 gcry_mpi_point_t r;
323
324 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
325 GNUNET_assert (NULL != g);
326 r = gcry_mpi_point_new (0);
327 gcry_mpi_ec_mul (r, val, g, edc->ctx);
328 gcry_mpi_point_release (g);
329 return r;
330}
331
332
333/**
334 * Add two points on the elliptic curve.
335 *
336 * @param edc calculation context for ECC operations
337 * @param a some value
338 * @param b some value
339 * @return @a a + @a b, must be freed using #GNUNET_CRYPTO_ecc_free()
340 */
341gcry_mpi_point_t
342GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc,
343 gcry_mpi_point_t a,
344 gcry_mpi_point_t b)
345{
346 gcry_mpi_point_t r;
194 347
348 r = gcry_mpi_point_new (0);
349 gcry_mpi_ec_add (r, a, b, edc->ctx);
350 return r;
351}
352
353
354/**
355 * Obtain a random point on the curve and its
356 * additive inverse. Both returned values
357 * must be freed using #GNUNET_CRYPTO_ecc_free().
358 *
359 * @param edc calculation context for ECC operations
360 * @param[out] r set to a random point on the curve
361 * @param[out] r_inv set to the additive inverse of @a r
362 */
363void
364GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc,
365 gcry_mpi_point_t *r,
366 gcry_mpi_point_t *r_inv)
367{
368 gcry_mpi_t fact;
369 gcry_mpi_t n;
370 gcry_mpi_point_t g;
371
372 fact = GNUNET_CRYPTO_ecc_random_mod_n (edc);
373
374 /* calculate 'r' */
375 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
376 GNUNET_assert (NULL != g);
377 *r = gcry_mpi_point_new (0);
378 gcry_mpi_ec_mul (*r, fact, g, edc->ctx);
379
380 /* calculate 'r_inv' */
381 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
382 gcry_mpi_sub (fact, n, fact); /* fact = n - fact = - fact */
383 *r_inv = gcry_mpi_point_new (0);
384 gcry_mpi_ec_mul (*r_inv, fact, g, edc->ctx);
385
386 gcry_mpi_release (n);
387 gcry_mpi_release (fact);
388 gcry_mpi_point_release (g);
389}
390
391
392/**
393 * Free a point value returned by the API.
394 *
395 * @param p point to free
396 */
397void
398GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p)
399{
400 gcry_mpi_point_release (p);
401}
402
403
195/* end of crypto_ecc_dlog.c */ 404/* end of crypto_ecc_dlog.c */
196 405
diff --git a/src/util/crypto_paillier.c b/src/util/crypto_paillier.c
index 8d5245d3e..e348be80a 100644
--- a/src/util/crypto_paillier.c
+++ b/src/util/crypto_paillier.c
@@ -269,7 +269,7 @@ GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *pu
269 } 269 }
270 270
271 /* generate r < n (without bias) */ 271 /* generate r < n (without bias) */
272 GNUNET_assert (0 != (r = gcry_mpi_new (0))); 272 GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
273 do { 273 do {
274 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM); 274 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM);
275 } 275 }
diff --git a/src/util/gnunet-ecc.c b/src/util/gnunet-ecc.c
index 5585ae85c..081cd0525 100644
--- a/src/util/gnunet-ecc.c
+++ b/src/util/gnunet-ecc.c
@@ -28,6 +28,9 @@
28#include "gnunet_testing_lib.h" 28#include "gnunet_testing_lib.h"
29#include <gcrypt.h> 29#include <gcrypt.h>
30 30
31/**
32 * Number of characters a Base32-encoded public key requires.
33 */
31#define KEY_STR_LEN sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)*8/5+1 34#define KEY_STR_LEN sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)*8/5+1
32 35
33/** 36/**
@@ -69,9 +72,9 @@ create_keys (const char *fn, const char *prefix)
69 struct GNUNET_CRYPTO_EddsaPrivateKey *pk; 72 struct GNUNET_CRYPTO_EddsaPrivateKey *pk;
70 struct GNUNET_CRYPTO_EddsaPublicKey target_pub; 73 struct GNUNET_CRYPTO_EddsaPublicKey target_pub;
71 static char vanity[KEY_STR_LEN + 1]; 74 static char vanity[KEY_STR_LEN + 1];
72 int len; 75 size_t len;
73 int n; 76 size_t n;
74 int rest; 77 size_t rest;
75 unsigned char mask; 78 unsigned char mask;
76 unsigned target_byte; 79 unsigned target_byte;
77 char *s; 80 char *s;
@@ -119,9 +122,9 @@ create_keys (const char *fn, const char *prefix)
119 s); 122 s);
120 GNUNET_free (s); 123 GNUNET_free (s);
121 fprintf (stderr, 124 fprintf (stderr,
122 "\nattempt %s [%d, %X]\n", 125 "\nattempt %s [%u, %X]\n",
123 vanity, 126 vanity,
124 n, 127 (unsigned int) n,
125 mask); 128 mask);
126 } 129 }
127 else 130 else
diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c
index 7d7c74ad6..8d2986c7b 100644
--- a/src/util/resolver_api.c
+++ b/src/util/resolver_api.c
@@ -1028,7 +1028,10 @@ GNUNET_RESOLVER_local_fqdn_get ()
1028 gai_strerror (ret)); 1028 gai_strerror (ret));
1029 return NULL; 1029 return NULL;
1030 } 1030 }
1031 rval = GNUNET_strdup (ai->ai_canonname); 1031 if (NULL != ai->ai_canonname)
1032 rval = GNUNET_strdup (ai->ai_canonname);
1033 else
1034 rval = GNUNET_strdup (hostname);
1032 freeaddrinfo (ai); 1035 freeaddrinfo (ai);
1033 return rval; 1036 return rval;
1034 } 1037 }
diff --git a/src/util/test_crypto_ecc_dlog.c b/src/util/test_crypto_ecc_dlog.c
index a594e5795..2101b28f1 100644
--- a/src/util/test_crypto_ecc_dlog.c
+++ b/src/util/test_crypto_ecc_dlog.c
@@ -22,9 +22,6 @@
22 * @file util/test_crypto_ecc_dlog.c 22 * @file util/test_crypto_ecc_dlog.c
23 * @brief testcase for ECC DLOG calculation 23 * @brief testcase for ECC DLOG calculation
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - test negative numbers
28 */ 25 */
29#include "platform.h" 26#include "platform.h"
30#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
@@ -42,52 +39,132 @@
42/** 39/**
43 * Maximum value we test dlog for. 40 * Maximum value we test dlog for.
44 */ 41 */
45#define MAX_FACT 1000000 42#define MAX_FACT 100
46 43
47/** 44/**
48 * Maximum memory to use, sqrt(MAX_FACT) is a good choice. 45 * Maximum memory to use, sqrt(MAX_FACT) is a good choice.
49 */ 46 */
50#define MAX_MEM 1000 47#define MAX_MEM 10
48
49/**
50 * How many values do we test?
51 */
52#define TEST_ITER 10
51 53
54/**
55 * Range of values to use for MATH tests.
56 */
57#define MATH_MAX 5
52 58
59
60/**
61 * Do some DLOG operations for testing.
62 *
63 * @param edc context for ECC operations
64 */
53static void 65static void
54test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc) 66test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc)
55{ 67{
56 gcry_mpi_t fact; 68 gcry_mpi_t fact;
69 gcry_mpi_t n;
57 gcry_ctx_t ctx; 70 gcry_ctx_t ctx;
58 gcry_mpi_point_t q; 71 gcry_mpi_point_t q;
59 gcry_mpi_point_t g; 72 gcry_mpi_point_t g;
60 unsigned int i; 73 unsigned int i;
61 unsigned int x; 74 int x;
75 int iret;
62 76
63 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); 77 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
64 g = gcry_mpi_ec_get_point ("g", ctx, 0); 78 g = gcry_mpi_ec_get_point ("g", ctx, 0);
65 GNUNET_assert (NULL != g); 79 GNUNET_assert (NULL != g);
80 n = gcry_mpi_ec_get_mpi ("n", ctx, 0);
66 q = gcry_mpi_point_new (0); 81 q = gcry_mpi_point_new (0);
67 fact = gcry_mpi_new (0); 82 fact = gcry_mpi_new (0);
68 for (i=0;i<10;i++) 83 for (i=0;i<TEST_ITER;i++)
69 { 84 {
85 fprintf (stderr, ".");
70 x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 86 x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
71 MAX_FACT); 87 MAX_FACT);
72 gcry_mpi_set_ui (fact, x); 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 }
73 gcry_mpi_ec_mul (q, fact, g, ctx); 99 gcry_mpi_ec_mul (q, fact, g, ctx);
74 if (x != 100 if (x !=
75 GNUNET_CRYPTO_ecc_dlog (edc, 101 (iret = GNUNET_CRYPTO_ecc_dlog (edc,
76 q)) 102 q)))
77 { 103 {
78 fprintf (stderr, 104 fprintf (stderr,
79 "DLOG failed for value %u\n", 105 "DLOG failed for value %d (%d)\n",
80 x); 106 x,
107 iret);
81 GNUNET_assert (0); 108 GNUNET_assert (0);
82 } 109 }
83 } 110 }
84 gcry_mpi_release (fact); 111 gcry_mpi_release (fact);
112 gcry_mpi_release (n);
85 gcry_mpi_point_release (g); 113 gcry_mpi_point_release (g);
86 gcry_mpi_point_release (q); 114 gcry_mpi_point_release (q);
87 gcry_ctx_release (ctx); 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 */
125static void
126test_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");
88} 164}
89 165
90 166
167
91int 168int
92main (int argc, char *argv[]) 169main (int argc, char *argv[])
93{ 170{
@@ -109,6 +186,7 @@ main (int argc, char *argv[])
109 edc = GNUNET_CRYPTO_ecc_dlog_prepare (MAX_FACT, 186 edc = GNUNET_CRYPTO_ecc_dlog_prepare (MAX_FACT,
110 MAX_MEM); 187 MAX_MEM);
111 test_dlog (edc); 188 test_dlog (edc);
189 test_math (edc);
112 GNUNET_CRYPTO_ecc_dlog_release (edc); 190 GNUNET_CRYPTO_ecc_dlog_release (edc);
113 return 0; 191 return 0;
114} 192}