aboutsummaryrefslogtreecommitdiff
path: root/src/secretsharing
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2014-01-07 00:14:11 +0000
committerFlorian Dold <florian.dold@gmail.com>2014-01-07 00:14:11 +0000
commit6a86f1fc448e219364d547d167d0a655eff2b531 (patch)
tree681e2a680f33f40da4d2235089946a9e4aa0089a /src/secretsharing
parent4d1b8809fe1df0f2524abc0e65f2f770c88adbdf (diff)
downloadgnunet-6a86f1fc448e219364d547d167d0a655eff2b531.tar.gz
gnunet-6a86f1fc448e219364d547d167d0a655eff2b531.zip
- profiler actually added to svn
- test for signature segfault with secretsharing - rudimentary implementation of cooperative decryption - consensus uses absolute time instead of relative - working DKG without zero knowledge proofs
Diffstat (limited to 'src/secretsharing')
-rw-r--r--src/secretsharing/Makefile.am12
-rwxr-xr-xsrc/secretsharing/gnunet-secretsharing-profiler.c316
-rw-r--r--src/secretsharing/gnunet-service-secretsharing.c772
-rw-r--r--src/secretsharing/secretsharing.h121
-rw-r--r--src/secretsharing/secretsharing_api.c125
-rw-r--r--src/secretsharing/secretsharing_protocol.h45
-rw-r--r--src/secretsharing/test_secretsharing.conf36
-rw-r--r--src/secretsharing/test_secretsharing_sig.c45
8 files changed, 1324 insertions, 148 deletions
diff --git a/src/secretsharing/Makefile.am b/src/secretsharing/Makefile.am
index 0473820b2..f2e14a60c 100644
--- a/src/secretsharing/Makefile.am
+++ b/src/secretsharing/Makefile.am
@@ -38,7 +38,9 @@ gnunet_secretsharing_profiler_DEPENDENCIES = \
38 38
39gnunet_service_secretsharing_SOURCES = \ 39gnunet_service_secretsharing_SOURCES = \
40 gnunet-service-secretsharing.c \ 40 gnunet-service-secretsharing.c \
41 secretsharing_common.c \
41 secretsharing_protocol.h 42 secretsharing_protocol.h
43gnunet_service_secretsharing_CFLAGS = $(AM_CFLAGS)
42gnunet_service_secretsharing_LDADD = \ 44gnunet_service_secretsharing_LDADD = \
43 $(top_builddir)/src/util/libgnunetutil.la \ 45 $(top_builddir)/src/util/libgnunetutil.la \
44 $(top_builddir)/src/consensus/libgnunetconsensus.la \ 46 $(top_builddir)/src/consensus/libgnunetconsensus.la \
@@ -49,6 +51,7 @@ gnunet_service_secretsharing_DEPENDENCIES = \
49 51
50libgnunetsecretsharing_la_SOURCES = \ 52libgnunetsecretsharing_la_SOURCES = \
51 secretsharing_api.c \ 53 secretsharing_api.c \
54 secretsharing_common.c \
52 secretsharing.h 55 secretsharing.h
53libgnunetsecretsharing_la_LIBADD = \ 56libgnunetsecretsharing_la_LIBADD = \
54 $(top_builddir)/src/util/libgnunetutil.la \ 57 $(top_builddir)/src/util/libgnunetutil.la \
@@ -57,7 +60,8 @@ libgnunetsecretsharing_la_LDFLAGS = \
57 $(GN_LIB_LDFLAGS) 60 $(GN_LIB_LDFLAGS)
58 61
59check_PROGRAMS = \ 62check_PROGRAMS = \
60 test_secretsharing_api 63 test_secretsharing_api \
64 test_secretsharing_sig
61 65
62if ENABLE_TEST_RUN 66if ENABLE_TEST_RUN
63TESTS = $(check_PROGRAMS) 67TESTS = $(check_PROGRAMS)
@@ -70,6 +74,12 @@ test_secretsharing_api_LDADD = \
70 $(top_builddir)/src/testing/libgnunettesting.la \ 74 $(top_builddir)/src/testing/libgnunettesting.la \
71 $(top_builddir)/src/secretsharing/libgnunetsecretsharing.la 75 $(top_builddir)/src/secretsharing/libgnunetsecretsharing.la
72 76
77test_secretsharing_sig_SOURCES = \
78 test_secretsharing_sig.c \
79 secretsharing_protocol.h
80test_secretsharing_sig_LDADD = \
81 $(top_builddir)/src/util/libgnunetutil.la
82
73EXTRA_DIST = \ 83EXTRA_DIST = \
74 test_secretsharing.conf 84 test_secretsharing.conf
75 85
diff --git a/src/secretsharing/gnunet-secretsharing-profiler.c b/src/secretsharing/gnunet-secretsharing-profiler.c
index a9bce4a14..01eb49a2d 100755
--- a/src/secretsharing/gnunet-secretsharing-profiler.c
+++ b/src/secretsharing/gnunet-secretsharing-profiler.c
@@ -1,5 +1,319 @@
1/*
2 This file is part of GNUnet
3 (C) 2014 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 secretsharing/gnunet-secretsharing-profiler.c
23 * @brief profiling tool for distributed key generation and decryption
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_secretsharing_service.h"
29#include "gnunet_testbed_service.h"
30
31static unsigned int num_peers = 3;
32
33static unsigned int threshold = 2;
34
35static struct GNUNET_TIME_Relative timeout;
36
37static struct GNUNET_SECRETSHARING_Session **session_handles;
38
39static struct GNUNET_TESTBED_Operation **testbed_operations;
40
41static unsigned int num_connected_handles;
42
43static struct GNUNET_TESTBED_Peer **peers;
44
45static struct GNUNET_PeerIdentity *peer_ids;
46
47static unsigned int num_retrieved_peer_ids;
48
49static struct GNUNET_HashCode session_id;
50
51static int verbose;
52
53
54/**
55 * Signature of the event handler function called by the
56 * respective event controller.
57 *
58 * @param cls closure
59 * @param event information about the event
60 */
61static void
62controller_cb (void *cls,
63 const struct GNUNET_TESTBED_EventInformation *event)
64{
65 GNUNET_assert (0);
66}
67
68
69/**
70 * Callback to be called when a service connect operation is completed
71 *
72 * @param cls the callback closure from functions generating an operation
73 * @param op the operation that has been finished
74 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
75 * @param emsg error message in case the operation has failed; will be NULL if
76 * operation has executed successfully.
77 */
78static void
79connect_complete (void *cls,
80 struct GNUNET_TESTBED_Operation *op,
81 void *ca_result,
82 const char *emsg)
83{
84
85 if (NULL != emsg)
86 {
87 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
88 "testbed connect emsg: %s\n",
89 emsg);
90 GNUNET_assert (0);
91 }
92
93 num_connected_handles++;
94
95 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
96 "connect complete\n");
97
98 if (num_connected_handles == num_peers)
99 {
100 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
101 "all peers connected\n");
102 }
103}
104
105
106static void
107secret_ready_cb (void *cls,
108 const struct GNUNET_SECRETSHARING_Share *my_share,
109 const struct GNUNET_SECRETSHARING_PublicKey *public_key,
110 unsigned int num_ready_peers,
111 const struct GNUNET_PeerIdentity *ready_peers)
112{
113 struct GNUNET_SECRETSHARING_Session **sp = cls;
114 unsigned int n = sp - session_handles;
115 if (NULL == my_share || NULL == public_key)
116 {
117 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "key generation failed for peer #%u\n", n);
118 return;
119 }
120 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "secret ready for peer #%u\n", n);
121 // FIXME: end profiler or try decryption if all secrets are ready
122}
123
124
125/**
126 * Adapter function called to establish a connection to
127 * a service.
128 *
129 * @param cls closure
130 * @param cfg configuration of the peer to connect to; will be available until
131 * GNUNET_TESTBED_operation_done() is called on the operation returned
132 * from GNUNET_TESTBED_service_connect()
133 * @return service handle to return in 'op_result', NULL on error
134 */
135static void *
136connect_adapter (void *cls,
137 const struct GNUNET_CONFIGURATION_Handle *cfg)
138{
139 struct GNUNET_SECRETSHARING_Session **sp = cls;
140
141 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
142 "connect adapter, %d peers\n",
143 num_peers);
144 *sp = GNUNET_SECRETSHARING_create_session (cfg,
145 num_peers,
146 peer_ids,
147 &session_id,
148 GNUNET_TIME_relative_to_absolute (timeout),
149 threshold,
150 &secret_ready_cb, sp);
151 return *sp;
152}
153
154
155/**
156 * Adapter function called to destroy a connection to
157 * a service.
158 *
159 * @param cls closure
160 * @param op_result service handle returned from the connect adapter
161 */
162static void
163disconnect_adapter(void *cls, void *op_result)
164{
165 /* FIXME: what to do here? */
166}
167
168
169/**
170 * Callback to be called when the requested peer information is available
171 *
172 * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
173 * @param op the operation this callback corresponds to
174 * @param pinfo the result; will be NULL if the operation has failed
175 * @param emsg error message if the operation has failed; will be NULL if the
176 * operation is successfull
177 */
178static void
179peer_info_cb (void *cb_cls,
180 struct GNUNET_TESTBED_Operation *op,
181 const struct GNUNET_TESTBED_PeerInformation *pinfo,
182 const char *emsg)
183{
184 struct GNUNET_PeerIdentity *p;
185 int i;
186
187 GNUNET_assert (NULL == emsg);
188
189 p = (struct GNUNET_PeerIdentity *) cb_cls;
190
191 if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY)
192 {
193 *p = *pinfo->result.id;
194 num_retrieved_peer_ids++;
195 if (num_retrieved_peer_ids == num_peers)
196 for (i = 0; i < num_peers; i++)
197 testbed_operations[i] =
198 GNUNET_TESTBED_service_connect (NULL, peers[i], "secretsharing", connect_complete, NULL,
199 connect_adapter, disconnect_adapter, &session_handles[i]);
200 }
201 else
202 {
203 GNUNET_assert (0);
204 }
205
206 GNUNET_TESTBED_operation_done (op);
207}
208
209
210/**
211 * Signature of a main function for a testcase.
212 *
213 * @param cls closure
214 * @param h the run handle
215 * @param num_peers number of peers in 'peers'
216 * @param started_peers handle to peers run in the testbed. NULL upon timeout (see
217 * GNUNET_TESTBED_test_run()).
218 * @param links_succeeded the number of overlay link connection attempts that
219 * succeeded
220 * @param links_failed the number of overlay link connection attempts that
221 * failed
222 */
223static void
224test_master (void *cls,
225 struct GNUNET_TESTBED_RunHandle *h,
226 unsigned int num_peers,
227 struct GNUNET_TESTBED_Peer **started_peers,
228 unsigned int links_succeeded,
229 unsigned int links_failed)
230{
231 int i;
232
233 GNUNET_log_setup ("gnunet-secretsharing-profiler", "INFO", NULL);
234
235 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test master\n");
236
237 peers = started_peers;
238
239 peer_ids = GNUNET_malloc (num_peers * sizeof (struct GNUNET_PeerIdentity));
240
241 session_handles = GNUNET_malloc (num_peers * sizeof (struct GNUNET_SECRETSHARING_Session *));
242 testbed_operations = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *));
243
244 for (i = 0; i < num_peers; i++)
245 GNUNET_TESTBED_peer_get_information (peers[i],
246 GNUNET_TESTBED_PIT_IDENTITY,
247 peer_info_cb,
248 &peer_ids[i]);
249}
250
251
252static void
253run (void *cls, char *const *args, const char *cfgfile,
254 const struct GNUNET_CONFIGURATION_Handle *cfg)
255{
256 static char *session_str = "gnunet-secretsharing/test";
257 char *topology;
258 int topology_cmp_result;
259
260 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", "OVERLAY_TOPOLOGY", &topology))
261 {
262 fprintf (stderr,
263 "'OVERLAY_TOPOLOGY' not found in 'testbed' config section, "
264 "seems like you passed the wrong configuration file\n");
265 return;
266 }
267
268 topology_cmp_result = strcasecmp (topology, "NONE");
269 GNUNET_free (topology);
270
271 if (0 == topology_cmp_result)
272 {
273 fprintf (stderr,
274 "'OVERLAY_TOPOLOGY' set to 'NONE', "
275 "seems like you passed the wrong configuration file\n");
276 return;
277 }
278
279 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
280 "running gnunet-secretsharing-profiler\n");
281
282 GNUNET_CRYPTO_hash (session_str, strlen (session_str), &session_id);
283
284 (void) GNUNET_TESTBED_test_run ("gnunet-secretsharing-profiler",
285 cfgfile,
286 num_peers,
287 0,
288 controller_cb,
289 NULL,
290 test_master,
291 NULL);
292}
293
294
1int 295int
2main () 296main (int argc, char **argv)
3{ 297{
298 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
299 { 'n', "num-peers", NULL,
300 gettext_noop ("number of peers in consensus"),
301 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers },
302 { 't', "timeout", NULL,
303 gettext_noop ("dkg timeout"),
304 GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &timeout },
305 { 'k', "threshold", NULL,
306 gettext_noop ("threshold"),
307 GNUNET_YES, &GNUNET_GETOPT_set_uint, &threshold },
308 { 'V', "verbose", NULL,
309 gettext_noop ("be more verbose (print received values)"),
310 GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose },
311 GNUNET_GETOPT_OPTION_END
312 };
313 timeout = GNUNET_TIME_UNIT_SECONDS;
314 GNUNET_PROGRAM_run2 (argc, argv, "gnunet-secretsharing-profiler",
315 "help",
316 options, &run, NULL, GNUNET_YES);
4 return 0; 317 return 0;
5} 318}
319
diff --git a/src/secretsharing/gnunet-service-secretsharing.c b/src/secretsharing/gnunet-service-secretsharing.c
index 3af899352..6c91343d5 100644
--- a/src/secretsharing/gnunet-service-secretsharing.c
+++ b/src/secretsharing/gnunet-service-secretsharing.c
@@ -26,6 +26,7 @@
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_util_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_time_lib.h" 28#include "gnunet_time_lib.h"
29#include "gnunet_signatures.h"
29#include "gnunet_consensus_service.h" 30#include "gnunet_consensus_service.h"
30#include "secretsharing.h" 31#include "secretsharing.h"
31#include "secretsharing_protocol.h" 32#include "secretsharing_protocol.h"
@@ -69,10 +70,39 @@ struct KeygenPeerInfo
69 gcry_mpi_t public_key_share; 70 gcry_mpi_t public_key_share;
70 71
71 /** 72 /**
72 * GNUNET_YES if the peer has been disqualified, 73 * Did we successfully receive the round1 element
73 * GNUNET_NO otherwise. 74 * of the peer?
74 */ 75 */
75 int disqualified; 76 int round1_valid;
77
78 /**
79 * Did we successfully receive the round1 element
80 * of the peer?
81 */
82 int round2_valid;
83};
84
85
86struct DecryptPeerInfo
87{
88 /**
89 * Identity of the peer.
90 */
91 struct GNUNET_PeerIdentity peer;
92
93 /**
94 * Original index in the key generation round.
95 * Necessary for computing the lagrange coefficients.
96 */
97 unsigned int real_index;
98
99 /**
100 * Set to the partial decryption of
101 * this peer, or NULL if we did not
102 * receive a partial decryption from this
103 * peer or the zero knowledge proof failed.
104 */
105 gcry_mpi_t partial_decryption;
76}; 106};
77 107
78 108
@@ -120,6 +150,8 @@ struct KeygenSession
120 150
121 /** 151 /**
122 * Minimum number of shares required to restore the secret. 152 * Minimum number of shares required to restore the secret.
153 * Also the number of coefficients for the polynomial representing
154 * the sharing. Obviously, the polynomial then has degree threshold-1.
123 */ 155 */
124 unsigned int threshold; 156 unsigned int threshold;
125 157
@@ -135,6 +167,7 @@ struct KeygenSession
135 167
136 /** 168 /**
137 * Information about all participating peers. 169 * Information about all participating peers.
170 * Array of size 'num_peers'.
138 */ 171 */
139 struct KeygenPeerInfo *info; 172 struct KeygenPeerInfo *info;
140 173
@@ -158,9 +191,18 @@ struct KeygenSession
158 */ 191 */
159 gcry_mpi_t paillier_mu; 192 gcry_mpi_t paillier_mu;
160 193
194 /**
195 * When would we like the key to be established?
196 */
161 struct GNUNET_TIME_Absolute deadline; 197 struct GNUNET_TIME_Absolute deadline;
162 198
163 /** 199 /**
200 * When does the DKG start? Necessary to compute fractions of the
201 * operation's desired time interval.
202 */
203 struct GNUNET_TIME_Absolute start_time;
204
205 /**
164 * Index of the local peer in the ordered list 206 * Index of the local peer in the ordered list
165 * of peers in the session. 207 * of peers in the session.
166 */ 208 */
@@ -170,23 +212,63 @@ struct KeygenSession
170 212
171struct DecryptSession 213struct DecryptSession
172{ 214{
215 /**
216 * Decrypt sessions are stored in a linked list.
217 */
173 struct DecryptSession *next; 218 struct DecryptSession *next;
219
220 /**
221 * Decrypt sessions are stored in a linked list.
222 */
174 struct DecryptSession *prev; 223 struct DecryptSession *prev;
175 224
225 /**
226 * Handle to the consensus over partial decryptions.
227 */
176 struct GNUNET_CONSENSUS_Handle *consensus; 228 struct GNUNET_CONSENSUS_Handle *consensus;
177 229
230 /**
231 * Client connected to us.
232 */
178 struct GNUNET_SERVER_Client *client; 233 struct GNUNET_SERVER_Client *client;
234
235 /**
236 * Message queue for 'client'.
237 */
238 struct GNUNET_MQ_Handle *client_mq;
239
240 /**
241 * When would we like the ciphertext to be
242 * decrypted?
243 */
244 struct GNUNET_TIME_Absolute deadline;
245
246 /**
247 * Ciphertext we want to decrypt.
248 */
249 struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
250
251 /**
252 * Share of the local peer.
253 */
254 struct GNUNET_SECRETSHARING_Share *share;
255
256 /**
257 * State information about other peers.
258 */
259 struct DecryptPeerInfo *info;
179}; 260};
180 261
262
181/** 263/**
182 * Decrypt sessions are held in a linked list. 264 * Decrypt sessions are held in a linked list.
183 */ 265 */
184//static struct DecryptSession *decrypt_sessions_head; 266static struct DecryptSession *decrypt_sessions_head;
185 267
186/** 268/**
187 * Decrypt sessions are held in a linked list. 269 * Decrypt sessions are held in a linked list.
188 */ 270 */
189//static struct DecryptSession *decrypt_sessions_tail; 271static struct DecryptSession *decrypt_sessions_tail;
190 272
191/** 273/**
192 * Decrypt sessions are held in a linked list. 274 * Decrypt sessions are held in a linked list.
@@ -222,6 +304,11 @@ static gcry_mpi_t elgamal_g;
222static struct GNUNET_PeerIdentity my_peer; 304static struct GNUNET_PeerIdentity my_peer;
223 305
224/** 306/**
307 * Peer that runs this service.
308 */
309static struct GNUNET_CRYPTO_EddsaPrivateKey *my_peer_private_key;
310
311/**
225 * Configuration of this service. 312 * Configuration of this service.
226 */ 313 */
227static const struct GNUNET_CONFIGURATION_Handle *cfg; 314static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -231,20 +318,79 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
231 */ 318 */
232static struct GNUNET_SERVER_Handle *srv; 319static struct GNUNET_SERVER_Handle *srv;
233 320
321/**
322 * Print a field element in a fixed-size buffer.
323 */
324static void
325print_field_element (void *buf, gcry_mpi_t x)
326{
327 GNUNET_assert (0);
328}
329
330
331static struct KeygenPeerInfo *
332get_keygen_peer_info (const struct KeygenSession *ks,
333 const struct GNUNET_PeerIdentity *peer)
334{
335 unsigned int i;
336 for (i = 0; i < ks->num_peers; i++)
337 if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
338 return &ks->info[i];
339 return NULL;
340}
341
342
343static struct DecryptPeerInfo *
344get_decrypt_peer_info (const struct DecryptSession *ds,
345 const struct GNUNET_PeerIdentity *peer)
346{
347 unsigned int i;
348 for (i = 0; i < ds->share->num_peers; i++)
349 if (0 == memcmp (peer, &ds->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
350 return &ds->info[i];
351 return NULL;
352}
353
354
355static struct GNUNET_TIME_Absolute
356time_between (struct GNUNET_TIME_Absolute start,
357 struct GNUNET_TIME_Absolute end,
358 int num, int denum)
359{
360 struct GNUNET_TIME_Absolute result;
361 uint64_t diff;
362
363 GNUNET_assert (start.abs_value_us <= end.abs_value_us);
364 diff = end.abs_value_us - start.abs_value_us;
365 result.abs_value_us = start.abs_value_us + ((diff * num) / denum);
366
367 return result;
368}
369
234 370
235/** 371/**
236 * Although GNUNET_CRYPTO_hash_cmp exisits, it does not have 372 * Compare two peer identities. Indended to be used with qsort or bsearch.
237 * the correct signature to be used with e.g. qsort.
238 * We use this function instead.
239 * 373 *
240 * @param h1 some hash code 374 * @param p1 some peer identity
241 * @param h2 some hash code 375 * @param p2 some peer identity
242 * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. 376 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
243 */ 377 */
244static int 378static int
245hash_cmp (const void *h1, const void *h2) 379peer_id_cmp (const void *p1, const void *p2)
380{
381 return memcmp (p1, p2, sizeof (struct GNUNET_PeerIdentity));
382}
383
384
385int
386peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n,
387 const struct GNUNET_PeerIdentity *needle)
246{ 388{
247 return GNUNET_CRYPTO_hash_cmp ((struct GNUNET_HashCode *) h1, (struct GNUNET_HashCode *) h2); 389 unsigned int i;
390 for (i = 0; i < n; i++)
391 if (0 == memcmp (&haystack[i], needle, sizeof (struct GNUNET_PeerIdentity)))
392 return i;
393 return -1;
248} 394}
249 395
250 396
@@ -266,45 +412,84 @@ normalize_peers (struct GNUNET_PeerIdentity *listed,
266{ 412{
267 unsigned int local_peer_in_list; 413 unsigned int local_peer_in_list;
268 unsigned int n; 414 unsigned int n;
269 unsigned int i;
270 struct GNUNET_PeerIdentity *normalized; 415 struct GNUNET_PeerIdentity *normalized;
271 416
272 local_peer_in_list = GNUNET_NO; 417 local_peer_in_list = GNUNET_YES;
273 for (i = 0; i < num_listed; i++) 418 n = num_listed;
419 if (peer_find (listed, num_listed, &my_peer) < 0)
274 { 420 {
275 if (0 == memcmp (&listed[i], &my_peer, sizeof (struct GNUNET_PeerIdentity))) 421 local_peer_in_list = GNUNET_NO;
276 { 422 n += 1;
277 local_peer_in_list = GNUNET_YES;
278 break;
279 }
280 } 423 }
281 424
282 n = num_listed; 425 normalized = GNUNET_new_array (n, struct GNUNET_PeerIdentity);
283 if (GNUNET_NO == local_peer_in_list)
284 n++;
285
286 normalized = GNUNET_malloc (n * sizeof (struct GNUNET_PeerIdentity));
287 426
288 if (GNUNET_NO == local_peer_in_list) 427 if (GNUNET_NO == local_peer_in_list)
289 normalized[n - 1] = my_peer; 428 normalized[n - 1] = my_peer;
290 429
291 memcpy (normalized, listed, num_listed * sizeof (struct GNUNET_PeerIdentity)); 430 memcpy (normalized, listed, num_listed * sizeof (struct GNUNET_PeerIdentity));
292 qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &hash_cmp); 431 qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp);
293 432
294 if (NULL != my_peer_idx) 433 if (NULL != my_peer_idx)
434 *my_peer_idx = peer_find (normalized, n, &my_peer);
435 if (NULL != num_normalized)
436 *num_normalized = n;
437
438 return normalized;
439}
440
441
442/**
443 * Get a the j-th lagrage coefficient for a set of indices.
444 *
445 * @param[out] coeff the lagrange coefficient
446 * @param j lagrage coefficient we want to compute
447 * @param indices indices
448 * @param num number of indices in @a indices
449 */
450static void
451compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
452 unsigned int *indices,
453 unsigned int num)
454{
455 int i;
456 /* numerator */
457 gcry_mpi_t n;
458 /* denominator */
459 gcry_mpi_t d;
460 /* temp value for l-j */
461 gcry_mpi_t tmp;
462
463 GNUNET_assert (0 != coeff);
464
465 GNUNET_assert (0 != (n = gcry_mpi_new (0)));
466 GNUNET_assert (0 != (d = gcry_mpi_new (0)));
467 GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
468
469 gcry_mpi_set_ui (n, 1);
470 gcry_mpi_set_ui (d, 1);
471
472 gcry_mpi_set_ui (coeff, 0);
473 for (i = 0; i < num; i++)
295 { 474 {
296 for (i = 0; i < num_listed; i++) 475 int l = indices[i];
297 { 476 if (l == j)
298 if (0 == memcmp (&normalized[i], &my_peer, sizeof (struct GNUNET_PeerIdentity))) 477 continue;
299 { 478 gcry_mpi_mul_ui (n, n, l);
300 *my_peer_idx = i; 479 // d <- d * (l-j)
301 break; 480 gcry_mpi_set_ui (tmp, l);
302 } 481 gcry_mpi_sub_ui (tmp, tmp, j);
303 } 482 gcry_mpi_mul (d, d, tmp);
304 } 483 }
305 484
306 *num_normalized = n; 485 // now we do the actual division, with everything mod q, as we
307 return normalized; 486 // are not operating on elemets from <g>, but on exponents
487 GNUNET_assert (0 == gcry_mpi_invm (d, d, elgamal_q));
488 gcry_mpi_mulm (coeff, n, d, elgamal_q);
489
490 gcry_mpi_release (n);
491 gcry_mpi_release (d);
492 gcry_mpi_release (tmp);
308} 493}
309 494
310 495
@@ -433,44 +618,76 @@ generate_presecret_polynomial (struct KeygenSession *ks)
433 for (i = 0; i < ks->threshold; i++) 618 for (i = 0; i < ks->threshold; i++)
434 { 619 {
435 ks->presecret_polynomial[i] = gcry_mpi_new (PAILLIER_BITS); 620 ks->presecret_polynomial[i] = gcry_mpi_new (PAILLIER_BITS);
621 GNUNET_assert (0 != ks->presecret_polynomial[i]);
436 gcry_mpi_randomize (ks->presecret_polynomial[i], PAILLIER_BITS, 622 gcry_mpi_randomize (ks->presecret_polynomial[i], PAILLIER_BITS,
437 GCRY_WEAK_RANDOM); 623 GCRY_WEAK_RANDOM);
438 } 624 }
439} 625}
440 626
441 627
628/**
629 * Consensus element handler for round one.
630 *
631 * @param cls closure (keygen session)
632 * @param element the element from consensus
633 */
442static void 634static void
443keygen_round1_new_element (void *cls, 635keygen_round1_new_element (void *cls,
444 const struct GNUNET_SET_Element *element) 636 const struct GNUNET_SET_Element *element)
445{ 637{
446 const struct GNUNET_SECRETSHARING_KeygenCommitData *d; 638 const struct GNUNET_SECRETSHARING_KeygenCommitData *d;
447 struct KeygenSession *ks = cls; 639 struct KeygenSession *ks = cls;
448 unsigned int i; 640 struct KeygenPeerInfo *info;
641
642 if (NULL == element)
643 {
644 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n");
645 return;
646 }
449 647
450 if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData)) 648 if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
451 { 649 {
452 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong size in consensus\n"); 650 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
651 "keygen commit data with wrong size (%u) in consensus, "
652 " %u expected\n",
653 element->size, sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData));
453 return; 654 return;
454 } 655 }
455 656
657 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
658
456 d = element->data; 659 d = element->data;
457 660
458 for (i = 0; i < ks->num_peers; i++) 661 info = get_keygen_peer_info (ks, &d->peer);
662
663 if (NULL == info)
459 { 664 {
460 if (0 == memcmp (&d->peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity))) 665 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
461 { 666 GNUNET_i2s (&d->peer));
462 // TODO: check signature 667 return;
463 GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].paillier_g, GCRYMPI_FMT_USG, 668 }
464 &d->pubkey.g, sizeof d->pubkey.g, NULL)); 669
465 GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].paillier_n, GCRYMPI_FMT_USG, 670 if (d->purpose.size !=
466 &d->pubkey.n, sizeof d->pubkey.n, NULL)); 671 htons (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)))
467 GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].presecret_commitment, GCRYMPI_FMT_USG, 672 {
468 &d->commitment, sizeof d->commitment, NULL)); 673 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong signature purpose size in consensus\n");
469 return; 674 return;
470 }
471 } 675 }
472 676
473 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity in consensus\n"); 677 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1,
678 &d->purpose, &d->signature, &d->peer.public_key))
679 {
680 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n");
681 return;
682 }
683
684 GNUNET_assert (0 == gcry_mpi_scan (&info->paillier_g, GCRYMPI_FMT_USG,
685 &d->pubkey.g, sizeof d->pubkey.g, NULL));
686 GNUNET_assert (0 == gcry_mpi_scan (&info->paillier_n, GCRYMPI_FMT_USG,
687 &d->pubkey.n, sizeof d->pubkey.n, NULL));
688 GNUNET_assert (0 == gcry_mpi_scan (&info->presecret_commitment, GCRYMPI_FMT_USG,
689 &d->commitment, sizeof d->commitment, NULL));
690 info->round1_valid = GNUNET_YES;
474} 691}
475 692
476 693
@@ -505,30 +722,60 @@ keygen_round2_conclude (void *cls)
505 struct KeygenSession *ks = cls; 722 struct KeygenSession *ks = cls;
506 struct GNUNET_SECRETSHARING_SecretReadyMessage *m; 723 struct GNUNET_SECRETSHARING_SecretReadyMessage *m;
507 struct GNUNET_MQ_Envelope *ev; 724 struct GNUNET_MQ_Envelope *ev;
725 size_t share_size;
508 unsigned int i; 726 unsigned int i;
727 unsigned int j;
728 struct GNUNET_SECRETSHARING_Share *share;
509 gcry_mpi_t s; 729 gcry_mpi_t s;
510 gcry_mpi_t h; 730 gcry_mpi_t h;
511 731
732 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
733
512 GNUNET_assert (0 != (s = gcry_mpi_new (PAILLIER_BITS))); 734 GNUNET_assert (0 != (s = gcry_mpi_new (PAILLIER_BITS)));
513 GNUNET_assert (0 != (h = gcry_mpi_new (PAILLIER_BITS))); 735 GNUNET_assert (0 != (h = gcry_mpi_new (PAILLIER_BITS)));
514 736
515 // multiplicative identity 737 // multiplicative identity
516 gcry_mpi_set_ui (s, 1); 738 gcry_mpi_set_ui (s, 1);
517 739
740 share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
741
742 share->num_peers = 0;
743
744 for (i = 0; i < ks->num_peers; i++)
745 if (GNUNET_YES == ks->info[i].round2_valid)
746 share->num_peers++;
747
748 share->peers = GNUNET_new_array (share->num_peers, struct GNUNET_PeerIdentity);
749 share->hom_share_commitments =
750 GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement);
751 share->original_indices = GNUNET_new_array (share->num_peers, uint16_t);
752
753 j = 0;
518 for (i = 0; i < ks->num_peers; i++) 754 for (i = 0; i < ks->num_peers; i++)
519 { 755 {
520 if (GNUNET_NO == ks->info[i].disqualified) 756 if (GNUNET_YES == ks->info[i].round2_valid)
521 { 757 {
522 gcry_mpi_addm (s, s, ks->info[i].decrypted_preshare, elgamal_p); 758 gcry_mpi_addm (s, s, ks->info[i].decrypted_preshare, elgamal_p);
523 gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p); 759 gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p);
524 // m->num_secret_peers++; // FIXME: m not initialized here! 760 share->peers[i] = ks->info[i].peer;
761 share->original_indices[i] = j++;
525 } 762 }
526 } 763 }
527 764
528 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY); 765 gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &share->my_share, PAILLIER_BITS / 8, NULL, s);
766 gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &share->public_key, PAILLIER_BITS / 8, NULL, s);
767
768 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen successful with %u peers\n", share->num_peers);
769
770 m = GNUNET_malloc (sizeof (struct GNUNET_SECRETSHARING_SecretReadyMessage) +
771 ks->num_peers * sizeof (struct GNUNET_PeerIdentity));
772
773 GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
529 774
530 gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &m->secret, PAILLIER_BITS / 8, NULL, s); 775 ev = GNUNET_MQ_msg_extra (m, share_size,
531 gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &m->public_key, PAILLIER_BITS / 8, NULL, s); 776 GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY);
777
778 GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &m[1], share_size, NULL));
532 779
533 GNUNET_MQ_send (ks->client_mq, ev); 780 GNUNET_MQ_send (ks->client_mq, ev);
534} 781}
@@ -548,17 +795,14 @@ static void
548insert_round2_element (struct KeygenSession *ks) 795insert_round2_element (struct KeygenSession *ks)
549{ 796{
550 struct GNUNET_SET_Element *element; 797 struct GNUNET_SET_Element *element;
551 struct GNUNET_SECRETSHARING_KeygenRevealData *msg; 798 struct GNUNET_SECRETSHARING_KeygenRevealData *d;
552 unsigned char *pos; 799 unsigned char *pos;
553 unsigned char *last_pos; 800 unsigned char *last_pos;
554 size_t element_size; 801 size_t element_size;
555 unsigned int i; 802 unsigned int i;
556 gcry_mpi_t c;
557 gcry_mpi_t idx; 803 gcry_mpi_t idx;
558 gcry_mpi_t v; 804 gcry_mpi_t v;
559 805
560 GNUNET_assert (0 != (c = gcry_mpi_new (PAILLIER_BITS)));
561 // FIXME: c is never used...
562 GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS))); 806 GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
563 GNUNET_assert (0 != (idx = gcry_mpi_new (PAILLIER_BITS))); 807 GNUNET_assert (0 != (idx = gcry_mpi_new (PAILLIER_BITS)));
564 808
@@ -567,13 +811,17 @@ insert_round2_element (struct KeygenSession *ks)
567 1 * PAILLIER_BITS / 8 * ks->threshold); 811 1 * PAILLIER_BITS / 8 * ks->threshold);
568 812
569 element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size); 813 element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
814 element->size = element_size;
815 element->data = (void *) &element[1];
570 816
571 msg = (void *) element->data; 817 d = (void *) element->data;
572 pos = (void *) &msg[1]; 818 d->peer = my_peer;
819
820 pos = (void *) &d[1];
573 last_pos = pos + element_size; 821 last_pos = pos + element_size;
574 822
575 // exponentiated pre-shares 823 // exponentiated pre-shares
576 for (i = 0; i <= ks->threshold; i++) 824 for (i = 0; i < ks->num_peers; i++)
577 { 825 {
578 ptrdiff_t remaining = last_pos - pos; 826 ptrdiff_t remaining = last_pos - pos;
579 GNUNET_assert (remaining > 0); 827 GNUNET_assert (remaining > 0);
@@ -586,112 +834,168 @@ insert_round2_element (struct KeygenSession *ks)
586 pos += PAILLIER_BITS / 8; 834 pos += PAILLIER_BITS / 8;
587 } 835 }
588 836
589 // exponentiated coefficients 837 // encrypted pre-shares
590 for (i = 0; i < ks->num_peers; i++) 838 for (i = 0; i < ks->num_peers; i++)
591 { 839 {
592 ptrdiff_t remaining = last_pos - pos; 840 ptrdiff_t remaining = last_pos - pos;
593 GNUNET_assert (remaining > 0); 841 GNUNET_assert (remaining > 0);
594 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p); 842 if (GNUNET_NO == ks->info[i].round1_valid)
843 gcry_mpi_set_ui (v, 0);
844 else
845 paillier_encrypt (v, ks->presecret_polynomial[0],
846 ks->info[i].paillier_g, ks->info[i].paillier_g);
595 gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v); 847 gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
596 pos += PAILLIER_BITS / 8; 848 pos += PAILLIER_BITS / 8;
597 } 849 }
598 850
599 // encrypted pre-shares 851 // exponentiated coefficients
600 for (i = 0; i < ks->threshold; i++) 852 for (i = 0; i < ks->threshold; i++)
601 { 853 {
602 ptrdiff_t remaining = last_pos - pos; 854 ptrdiff_t remaining = last_pos - pos;
603 GNUNET_assert (remaining > 0); 855 GNUNET_assert (remaining > 0);
604 if (GNUNET_YES == ks->info[i].disqualified) 856 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
605 gcry_mpi_set_ui (v, 0);
606 else
607 paillier_encrypt (v, ks->presecret_polynomial[0],
608 ks->info[i].paillier_g, ks->info[i].paillier_g);
609 gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v); 857 gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
610 pos += PAILLIER_BITS / 8; 858 pos += PAILLIER_BITS / 8;
611 } 859 }
612 860
861 d->purpose.size = htons (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
862 d->purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2);
863 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature);
864
613 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL); 865 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
614 GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */ 866 GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
615 867
616 gcry_mpi_release (c);
617 gcry_mpi_release (v); 868 gcry_mpi_release (v);
618 gcry_mpi_release (idx); 869 gcry_mpi_release (idx);
619} 870}
620 871
621 872
622static struct KeygenPeerInfo *
623get_keygen_peer_info (const struct KeygenSession *ks,
624 struct GNUNET_PeerIdentity *peer)
625{
626 unsigned int i;
627 for (i = 0; i < ks->num_peers; i++)
628 if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
629 return &ks->info[i];
630 return NULL;
631}
632
633
634static void 873static void
635keygen_round2_new_element (void *cls, 874keygen_round2_new_element (void *cls,
636 const struct GNUNET_SET_Element *element) 875 const struct GNUNET_SET_Element *element)
637{ 876{
638 struct KeygenSession *ks = cls; 877 struct KeygenSession *ks = cls;
639 struct GNUNET_SECRETSHARING_KeygenRevealData *msg; 878 const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
640 struct KeygenPeerInfo *info; 879 struct KeygenPeerInfo *info;
641 unsigned char *pos; 880 unsigned char *pos;
642 unsigned char *last_pos;
643 gcry_mpi_t c; 881 gcry_mpi_t c;
882 size_t expected_element_size;
644 883
645 msg = (void *) element->data; 884 if (NULL == element)
646 pos = (void *) &msg[1]; 885 {
647 // skip exp. pre-shares 886 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n");
648 pos += PAILLIER_BITS / 8 * ks->num_peers; 887 return;
649 // skip exp. coefficients 888 }
650 pos += PAILLIER_BITS / 8 * ks->threshold;
651 // skip to the value for our peer
652 pos += PAILLIER_BITS / 8 * ks->local_peer_idx;
653 889
654 last_pos = element->size + (unsigned char *) element->data; 890 expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
891 2 * PAILLIER_BITS / 8 * ks->num_peers +
892 1 * PAILLIER_BITS / 8 * ks->threshold);
655 893
656 if ((pos >= last_pos) || ((last_pos - pos) < (PAILLIER_BITS / 8))) 894 if (element->size != expected_element_size)
657 { 895 {
658 GNUNET_break_op (0); 896 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
897 "keygen round2 data with wrong size (%u) in consensus, "
898 " %u expected\n",
899 element->size, expected_element_size);
659 return; 900 return;
660 } 901 }
661 902
662 GNUNET_assert (0 == gcry_mpi_scan (&c, GCRYMPI_FMT_USG, 903 d = (const void *) element->data;
663 pos, PAILLIER_BITS / 8, NULL));
664 904
665 info = get_keygen_peer_info (ks, &msg->peer); 905 info = get_keygen_peer_info (ks, &d->peer);
666 906
667 if (NULL == info) 907 if (NULL == info)
668 { 908 {
669 GNUNET_break_op (0); 909 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
910 GNUNET_i2s (&d->peer));
911 return;
912 }
913
914 if (GNUNET_NO == info->round1_valid)
915 {
916 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
917 "ignoring round2 element from peer with invalid round1 element (%s)\n",
918 GNUNET_i2s (&d->peer));
670 return; 919 return;
671 } 920 }
672 921
922 if (GNUNET_YES == info->round2_valid)
923 {
924 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
925 "ignoring duplicate round2 element (%s)\n",
926 GNUNET_i2s (&d->peer));
927 return;
928 }
929
930 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
931
932
933 pos = (void *) &d[1];
934 // skip exponentiated pre-shares
935 pos += PAILLIER_BITS / 8 * ks->num_peers;
936 // skip encrypted pre-shares
937 pos += PAILLIER_BITS / 8 * ks->num_peers;
938 // the first exponentiated coefficient is the public key share
939 GNUNET_assert (0 == gcry_mpi_scan (&info->public_key_share, GCRYMPI_FMT_USG,
940 pos, PAILLIER_BITS / 8, NULL));
941
942 pos = (void *) &d[1];
943 // skip exp. pre-shares
944 pos += PAILLIER_BITS / 8 * ks->num_peers;
945 // skip to the encrypted value for our peer
946 pos += PAILLIER_BITS / 8 * ks->local_peer_idx;
947
948 GNUNET_assert (0 == gcry_mpi_scan (&c, GCRYMPI_FMT_USG,
949 pos, PAILLIER_BITS / 8, NULL));
950
951 GNUNET_assert (0 != (info->decrypted_preshare = mpi_new (0)));
952
673 paillier_decrypt (info->decrypted_preshare, c, ks->paillier_lambda, ks->paillier_mu, 953 paillier_decrypt (info->decrypted_preshare, c, ks->paillier_lambda, ks->paillier_mu,
674 ks->info[ks->local_peer_idx].paillier_n); 954 ks->info[ks->local_peer_idx].paillier_n);
675 955
676 // TODO: validate signature and proofs 956 // TODO: validate zero knowledge proofs
957
958 if (d->purpose.size !=
959 htons (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose)))
960 {
961 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n");
962 return;
963 }
677 964
965 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2,
966 &d->purpose, &d->signature, &d->peer.public_key))
967 {
968 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n");
969 return;
970 }
971
972 info->round2_valid = GNUNET_YES;
678} 973}
679 974
680 975
976/**
977 * Called when the first consensus round has concluded.
978 * Will initiate the second round.
979 *
980 * @param cls closure
981 */
681static void 982static void
682keygen_round1_conclude (void *cls) 983keygen_round1_conclude (void *cls)
683{ 984{
684 struct KeygenSession *ks = cls; 985 struct KeygenSession *ks = cls;
685 986
686 // TODO: destroy old consensus 987 GNUNET_CONSENSUS_destroy (ks->consensus);
687 // TODO: mark peers without keys as disqualified
688 988
689 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id, 989 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
690 keygen_round2_new_element, ks); 990 keygen_round2_new_element, ks);
691 991
692 insert_round2_element (ks); 992 insert_round2_element (ks);
693 993
694 GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round2_conclude, ks); 994 GNUNET_CONSENSUS_conclude (ks->consensus,
995 /* last round, thus conclude at DKG deadline */
996 ks->deadline,
997 keygen_round2_conclude,
998 ks);
695} 999}
696 1000
697 1001
@@ -716,6 +1020,8 @@ insert_round1_element (struct KeygenSession *ks)
716 element->data = d; 1020 element->data = d;
717 element->size = sizeof *d; 1021 element->size = sizeof *d;
718 1022
1023 d->peer = my_peer;
1024
719 GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS))); 1025 GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
720 1026
721 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p); 1027 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
@@ -734,9 +1040,9 @@ insert_round1_element (struct KeygenSession *ks)
734 (unsigned char *) d->pubkey.n, PAILLIER_BITS / 8, NULL, 1040 (unsigned char *) d->pubkey.n, PAILLIER_BITS / 8, NULL,
735 ks->info[ks->local_peer_idx].paillier_n)); 1041 ks->info[ks->local_peer_idx].paillier_n));
736 1042
737 // FIXME: sign stuff 1043 d->purpose.size = htons ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
738 1044 d->purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
739 d->peer = my_peer; 1045 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature));
740 1046
741 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL); 1047 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
742} 1048}
@@ -758,13 +1064,19 @@ static void handle_client_keygen (void *cls,
758 const struct GNUNET_SECRETSHARING_CreateMessage *msg = 1064 const struct GNUNET_SECRETSHARING_CreateMessage *msg =
759 (const struct GNUNET_SECRETSHARING_CreateMessage *) message; 1065 (const struct GNUNET_SECRETSHARING_CreateMessage *) message;
760 struct KeygenSession *ks; 1066 struct KeygenSession *ks;
1067 unsigned int i;
761 1068
762 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n"); 1069 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n");
763 1070
764 ks = GNUNET_new (struct KeygenSession); 1071 ks = GNUNET_new (struct KeygenSession);
765 1072
1073 /* FIXME: check if client already has some session */
1074
766 GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks); 1075 GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks);
767 1076
1077 ks->client = client;
1078 ks->client_mq = GNUNET_MQ_queue_for_server_client (client);
1079
768 ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline); 1080 ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
769 ks->threshold = ntohs (msg->threshold); 1081 ks->threshold = ntohs (msg->threshold);
770 ks->num_peers = ntohs (msg->num_peers); 1082 ks->num_peers = ntohs (msg->num_peers);
@@ -772,11 +1084,21 @@ static void handle_client_keygen (void *cls,
772 ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers, 1084 ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers,
773 &ks->num_peers, &ks->local_peer_idx); 1085 &ks->num_peers, &ks->local_peer_idx);
774 1086
775 // TODO: initialize MPIs in peer structure
776 1087
1088 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "first round of consensus with %u peers\n", ks->num_peers);
777 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id, 1089 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id,
778 keygen_round1_new_element, ks); 1090 keygen_round1_new_element, ks);
779 1091
1092 ks->info = GNUNET_malloc (ks->num_peers * sizeof (struct KeygenPeerInfo));
1093
1094 for (i = 0; i < ks->num_peers; i++)
1095 ks->info[i].peer = ks->peers[i];
1096
1097 GNUNET_assert (0 != (ks->info[ks->local_peer_idx].paillier_g = mpi_new (0)));
1098 GNUNET_assert (0 != (ks->info[ks->local_peer_idx].paillier_n = mpi_new (0)));
1099 GNUNET_assert (0 != (ks->paillier_lambda = mpi_new (0)));
1100 GNUNET_assert (0 != (ks->paillier_mu = mpi_new (0)));
1101
780 paillier_create (ks->info[ks->local_peer_idx].paillier_g, 1102 paillier_create (ks->info[ks->local_peer_idx].paillier_g,
781 ks->info[ks->local_peer_idx].paillier_n, 1103 ks->info[ks->local_peer_idx].paillier_n,
782 ks->paillier_lambda, 1104 ks->paillier_lambda,
@@ -787,7 +1109,149 @@ static void handle_client_keygen (void *cls,
787 1109
788 insert_round1_element (ks); 1110 insert_round1_element (ks);
789 1111
790 GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round1_conclude, ks); 1112 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "starting conclude of round 1\n");
1113
1114 GNUNET_CONSENSUS_conclude (ks->consensus,
1115 /* half the overall time */
1116 time_between (ks->start_time, ks->deadline, 1, 2),
1117 keygen_round1_conclude,
1118 ks);
1119
1120 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1121}
1122
1123
1124/**
1125 * Called when the partial decryption consensus concludes.
1126 */
1127static void
1128decrypt_conclude (void *cls)
1129{
1130 struct DecryptSession *ds = cls;
1131 struct GNUNET_SECRETSHARING_DecryptResponseMessage *msg;
1132 struct GNUNET_MQ_Envelope *ev;
1133 gcry_mpi_t lagrange;
1134 gcry_mpi_t m;
1135 gcry_mpi_t tmp;
1136 gcry_mpi_t c_2;
1137 unsigned int *indices;
1138 unsigned int num;
1139 unsigned int i;
1140 unsigned int j;
1141
1142 GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
1143 GNUNET_assert (0 != (m = gcry_mpi_new (0)));
1144 GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
1145
1146 num = 0;
1147 for (i = 0; i < ds->share->num_peers; i++)
1148 if (NULL != ds->info[i].partial_decryption)
1149 num++;
1150
1151 indices = GNUNET_malloc (num * sizeof (unsigned int));
1152 j = 0;
1153 for (i = 0; i < ds->share->num_peers; i++)
1154 if (NULL != ds->info[i].partial_decryption)
1155 indices[j++] = ds->info[i].real_index;
1156
1157 gcry_mpi_set_ui (m, 1);
1158
1159 for (i = 0; i < num; i++)
1160 {
1161 compute_lagrange_coefficient (lagrange, indices[i], indices, num);
1162 // w_j^{\lambda_j}
1163 gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p);
1164 gcry_mpi_mulm (m, m, tmp, elgamal_p);
1165 }
1166
1167 GNUNET_assert (0 == gcry_mpi_scan (&c_2, GCRYMPI_FMT_USG, ds->ciphertext.c2_bits,
1168 PAILLIER_BITS / 8, NULL));
1169
1170 // m <- c_2 / m
1171 gcry_mpi_invm (m, m, elgamal_p);
1172 gcry_mpi_mulm (m, c_2, m, elgamal_p);
1173
1174 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE);
1175 print_field_element (&msg->plaintext, m);
1176 msg->success = htonl (1);
1177 GNUNET_MQ_send (ds->client_mq, ev);
1178
1179 // FIXME: what if not enough peers participated?
1180}
1181
1182
1183/**
1184 * Called when a new partial decryption arrives.
1185 */
1186static void
1187decrypt_new_element (void *cls,
1188 const struct GNUNET_SET_Element *element)
1189{
1190 struct DecryptSession *session = cls;
1191 const struct GNUNET_SECRETSHARING_DecryptData *d;
1192 struct DecryptPeerInfo *info;
1193
1194 if (NULL == element)
1195 {
1196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1197 /* FIXME: destroy */
1198 return;
1199 }
1200
1201 if (element->size != sizeof *d)
1202 {
1203 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element of wrong size in decrypt consensus\n");
1204 return;
1205 }
1206
1207 d = element->data;
1208
1209 info = get_decrypt_peer_info (session, &d->peer);
1210
1211 if (NULL == info)
1212 {
1213 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element from invalid peer (%s)\n",
1214 GNUNET_i2s (&d->peer));
1215 return;
1216 }
1217
1218 if (NULL != info->partial_decryption)
1219 {
1220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n",
1221 GNUNET_i2s (&d->peer));
1222 return;
1223 }
1224
1225 // FIXME: check NIZP first
1226
1227 GNUNET_assert (0 == gcry_mpi_scan (&info->partial_decryption,
1228 GCRYMPI_FMT_USG, &d->partial_decryption, PAILLIER_BITS / 8, NULL));
1229}
1230
1231static void
1232insert_decrypt_element (struct DecryptSession *ds)
1233{
1234 struct GNUNET_SECRETSHARING_DecryptData d;
1235 struct GNUNET_SET_Element element;
1236 gcry_mpi_t x;
1237 gcry_mpi_t s;
1238
1239 GNUNET_assert (0 == gcry_mpi_scan (&x, GCRYMPI_FMT_USG, ds->ciphertext.c1_bits, PAILLIER_BITS / 8, NULL));
1240 GNUNET_assert (0 == gcry_mpi_scan (&s, GCRYMPI_FMT_USG, &ds->share->my_share, PAILLIER_BITS / 8, NULL));
1241
1242 gcry_mpi_powm (x, x, s, elgamal_p);
1243
1244 element.data = (void *) &d;
1245 element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
1246
1247 d.peer = my_peer;
1248 d.purpose.size = htons (element.size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
1249 d.purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
1250 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature);
1251
1252 print_field_element (&d.partial_decryption, x);
1253
1254 GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
791} 1255}
792 1256
793 1257
@@ -800,11 +1264,80 @@ static void handle_client_keygen (void *cls,
800 * @param message the actual message 1264 * @param message the actual message
801 */ 1265 */
802static void handle_client_decrypt (void *cls, 1266static void handle_client_decrypt (void *cls,
803 struct GNUNET_SERVER_Client *client, 1267 struct GNUNET_SERVER_Client *client,
804 const struct GNUNET_MessageHeader 1268 const struct GNUNET_MessageHeader
805 *message) 1269 *message)
806{ 1270{
807 GNUNET_assert (0); 1271 const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg =
1272 (const void *) message;
1273 struct DecryptSession *ds;
1274 struct GNUNET_HashCode session_id;
1275
1276 ds = GNUNET_new (struct DecryptSession);
1277 // FIXME: check if session already exists
1278 GNUNET_CONTAINER_DLL_insert (decrypt_sessions_head, decrypt_sessions_tail, ds);
1279 ds->client = client;
1280 ds->client_mq = GNUNET_MQ_queue_for_server_client (client);
1281 ds->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
1282 ds->ciphertext = msg->ciphertext;
1283
1284 ds->share = GNUNET_SECRETSHARING_share_read (&msg[1], ntohs (msg->header.size) - sizeof *msg, NULL);
1285 // FIXME: probably should be break rather than assert
1286 GNUNET_assert (NULL != ds->share);
1287
1288 // FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ...
1289 GNUNET_CRYPTO_hash (&msg->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext), &session_id);
1290
1291 ds->consensus = GNUNET_CONSENSUS_create (cfg,
1292 ds->share->num_peers,
1293 ds->share->peers,
1294 &session_id,
1295 decrypt_new_element,
1296 ds);
1297
1298 insert_decrypt_element (ds);
1299
1300 GNUNET_CONSENSUS_conclude (ds->consensus, ds->deadline, decrypt_conclude, ds);
1301}
1302
1303
1304static void
1305init_crypto_constants (void)
1306{
1307 /* 1024-bit safe prime */
1308 const char *elgamal_p_hex =
1309 "0x08a347d3d69e8b2dd7d1b12a08dfbccbebf4ca"
1310 "6f4269a0814e158a34312964d946b3ef22882317"
1311 "2bcf30fc08f772774cb404f9bc002a6f66b09a79"
1312 "d810d67c4f8cb3bedc6060e3c8ef874b1b64df71"
1313 "6c7d2b002da880e269438d5a776e6b5f253c8df5"
1314 "6a16b1c7ce58def07c03db48238aadfc52a354a2"
1315 "7ed285b0c1675cad3f3";
1316 /* 1023-bit Sophie Germain prime, q = (p-1)/2 */
1317 const char *elgamal_q_hex =
1318 "0x0451a3e9eb4f4596ebe8d895046fde65f5fa65"
1319 "37a134d040a70ac51a1894b26ca359f79144118b"
1320 "95e7987e047bb93ba65a027cde001537b3584d3c"
1321 "ec086b3e27c659df6e303071e477c3a58db26fb8"
1322 "b63e958016d4407134a1c6ad3bb735af929e46fa"
1323 "b50b58e3e72c6f783e01eda411c556fe2951aa51"
1324 "3f6942d860b3ae569f9";
1325 /* generator of the unique size q subgroup of Z_p^* */
1326 const char *elgamal_g_hex =
1327 "0x05c00c36d2e822950087ef09d8252994adc4e4"
1328 "8fe3ec70269f035b46063aff0c99b633fd64df43"
1329 "02442e1914c829a41505a275438871f365e91c12"
1330 "3d5303ef9e90f4b8cb89bf86cc9b513e74a72634"
1331 "9cfd9f953674fab5d511e1c078fc72d72b34086f"
1332 "c82b4b951989eb85325cb203ff98df76bc366bba"
1333 "1d7024c3650f60d0da";
1334
1335 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
1336 elgamal_q_hex, 0, NULL));
1337 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
1338 elgamal_p_hex, 0, NULL));
1339 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
1340 elgamal_g_hex, 0, NULL));
808} 1341}
809 1342
810 1343
@@ -826,6 +1359,15 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
826 }; 1359 };
827 cfg = c; 1360 cfg = c;
828 srv = server; 1361 srv = server;
1362 my_peer_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1363 if (NULL == my_peer_private_key)
1364 {
1365 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not access host private key\n");
1366 GNUNET_break (0);
1367 GNUNET_SCHEDULER_shutdown ();
1368 return;
1369 }
1370 init_crypto_constants ();
829 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer)) 1371 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer))
830 { 1372 {
831 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n"); 1373 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
diff --git a/src/secretsharing/secretsharing.h b/src/secretsharing/secretsharing.h
index 0af21028d..232721410 100644
--- a/src/secretsharing/secretsharing.h
+++ b/src/secretsharing/secretsharing.h
@@ -27,13 +27,22 @@
27#define SECRETSHARING_H 27#define SECRETSHARING_H
28 28
29#include "platform.h" 29#include "platform.h"
30#include "gnunet_common.h" 30#include "gnunet_util_lib.h"
31#include "gnunet_time_lib.h" 31#include "gnunet_time_lib.h"
32#include "gnunet_common.h"
32#include "gnunet_secretsharing_service.h" 33#include "gnunet_secretsharing_service.h"
33 34
34 35
35GNUNET_NETWORK_STRUCT_BEGIN 36GNUNET_NETWORK_STRUCT_BEGIN
36 37
38struct GNUNET_SECRETSHARING_FieldElement
39{
40 /**
41 * Value of an element in <elgamal_g>.
42 */
43 unsigned char bits[GNUNET_SECRETSHARING_KEY_BITS / 8];
44};
45
37 46
38struct GNUNET_SECRETSHARING_CreateMessage 47struct GNUNET_SECRETSHARING_CreateMessage
39{ 48{
@@ -67,31 +76,46 @@ struct GNUNET_SECRETSHARING_CreateMessage
67}; 76};
68 77
69 78
70struct GNUNET_SECRETSHARING_SecretReadyMessage 79
80struct GNUNET_SECRETSHARING_ShareHeaderNBO
71{ 81{
72 /** 82 /**
73 * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY 83 * Threshold for the key this share belongs to.
74 */ 84 */
75 struct GNUNET_MessageHeader header; 85 uint16_t threshold;
86
87 /**
88 * Peers that have the share.
89 */
90 uint16_t num_peers;
76 91
77 /** 92 /**
78 * Secret share in network byte order. 93 * Index of our peer in the list.
79 */ 94 */
80 unsigned char secret[GNUNET_SECRETSHARING_KEY_BITS / 8]; 95 uint16_t my_peer;
81 96
82 /** 97 /**
83 * Secret share in network byte order. 98 * Public key. Must correspond to the product of
99 * the homomorphic share commitments.
84 */ 100 */
85 struct GNUNET_SECRETSHARING_PublicKey public_key; 101 struct GNUNET_SECRETSHARING_PublicKey public_key;
86 102
87 /** 103 /**
88 * Number of peers at the end of this message. 104 * Share of 'my_peer'
89 * Includes peers that are part of the established
90 * threshold crypto system.
91 */ 105 */
92 uint16_t num_secret_peers GNUNET_PACKED; 106 struct GNUNET_SECRETSHARING_FieldElement my_share;
107};
108
109
110struct GNUNET_SECRETSHARING_SecretReadyMessage
111{
112 /**
113 * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY
114 */
115 struct GNUNET_MessageHeader header;
116
117 /* rest: the serialized share */
93 118
94 /* struct GNUNET_PeerIdentity[num_peers]; */
95}; 119};
96 120
97 121
@@ -103,35 +127,88 @@ struct GNUNET_SECRETSHARING_DecryptRequestMessage
103 struct GNUNET_MessageHeader header; 127 struct GNUNET_MessageHeader header;
104 128
105 /** 129 /**
106 * Ciphertext to request decryption for. 130 * Until when should the decryption be finished?
107 */ 131 */
108 unsigned char ciphertext[GNUNET_SECRETSHARING_KEY_BITS / 8]; 132 struct GNUNET_TIME_AbsoluteNBO deadline;
109 133
110 /** 134 /**
111 * Number of peers at the end of this message. 135 * Ciphertext we want to decrypt.
112 * Includes peers that are part of the established
113 * threshold crypto system.
114 */ 136 */
115 uint16_t num_secret_peers GNUNET_PACKED; 137 struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
116 138
117 /* struct GNUNET_PeerIdentity[num_peers]; */ 139 /* the share with payload */
118}; 140};
119 141
120 142
121struct GNUNET_SECRETSHARING_DecryptResponseMessage 143struct GNUNET_SECRETSHARING_DecryptResponseMessage
122{ 144{
123 /** 145 /**
124 * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_RESPONSE 146 * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE
125 */ 147 */
126 struct GNUNET_MessageHeader header; 148 struct GNUNET_MessageHeader header;
127 149
128 /** 150 /**
129 * Ciphertext to request decryption for. 151 * Zero if decryption failed, non-zero if decryption succeeded.
152 * If the decryption failed, plaintext is also zero.
130 */ 153 */
131 unsigned char plaintext[GNUNET_SECRETSHARING_KEY_BITS / 8]; 154 uint32_t success;
155
156 /**
157 * Decrypted plaintext.
158 */
159 struct GNUNET_SECRETSHARING_FieldElement plaintext;
132}; 160};
133 161
134 162
135GNUNET_NETWORK_STRUCT_END 163GNUNET_NETWORK_STRUCT_END
136 164
165
166/**
167 * A share, with all values in in host byte order.
168 */
169struct GNUNET_SECRETSHARING_Share
170{
171 /**
172 * Threshold for the key this share belongs to.
173 */
174 uint16_t threshold;
175
176 /**
177 * Peers that have the share.
178 */
179 uint16_t num_peers;
180
181 /**
182 * Index of our peer in the list.
183 */
184 uint16_t my_peer;
185
186 /**
187 * Public key. Must correspond to the product of
188 * the homomorphic share commitments.
189 */
190 struct GNUNET_SECRETSHARING_PublicKey public_key;
191
192 /**
193 * Share of 'my_peer'
194 */
195 struct GNUNET_SECRETSHARING_FieldElement my_share;
196
197 /**
198 * Peer identities (includes 'my_peer')
199 */
200 struct GNUNET_PeerIdentity *peers;
201
202 /*
203 * Homomorphic commitments to each peer's share (includes 'my_peer')
204 */
205 struct GNUNET_SECRETSHARING_FieldElement *hom_share_commitments;
206
207 /*
208 * Original indices of peers from the DKG round.
209 */
210 uint16_t *original_indices;
211};
212
213
137#endif 214#endif
diff --git a/src/secretsharing/secretsharing_api.c b/src/secretsharing/secretsharing_api.c
index a44fa2a2f..d2b53acc7 100644
--- a/src/secretsharing/secretsharing_api.c
+++ b/src/secretsharing/secretsharing_api.c
@@ -31,8 +31,6 @@
31 31
32#define LOG(kind,...) GNUNET_log_from (kind, "secretsharing-api",__VA_ARGS__) 32#define LOG(kind,...) GNUNET_log_from (kind, "secretsharing-api",__VA_ARGS__)
33 33
34
35
36/** 34/**
37 * Session that will eventually establish a shared secred between 35 * Session that will eventually establish a shared secred between
38 * the involved peers and allow encryption and cooperative decryption. 36 * the involved peers and allow encryption and cooperative decryption.
@@ -61,6 +59,30 @@ struct GNUNET_SECRETSHARING_Session
61}; 59};
62 60
63 61
62struct GNUNET_SECRETSHARING_DecryptionHandle
63{
64 /**
65 * Client connected to the secretsharing service.
66 */
67 struct GNUNET_CLIENT_Connection *client;
68
69 /**
70 * Message queue for 'client'.
71 */
72 struct GNUNET_MQ_Handle *mq;
73
74 /**
75 * Called when the secret sharing is done.
76 */
77 GNUNET_SECRETSHARING_DecryptCallback decrypt_cb;
78
79 /**
80 * Closure for 'decrypt_cb'.
81 */
82 void *decrypt_cls;
83};
84
85
64static void 86static void
65handle_session_client_error (void *cls, enum GNUNET_MQ_Error error) 87handle_session_client_error (void *cls, enum GNUNET_MQ_Error error)
66{ 88{
@@ -69,16 +91,29 @@ handle_session_client_error (void *cls, enum GNUNET_MQ_Error error)
69 s->secret_ready_cb (s->secret_ready_cls, NULL, NULL, 0, NULL); 91 s->secret_ready_cb (s->secret_ready_cls, NULL, NULL, 0, NULL);
70} 92}
71 93
94
95static void
96handle_decrypt_client_error (void *cls, enum GNUNET_MQ_Error error)
97{
98 GNUNET_assert (0);
99}
100
72static void 101static void
73handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg) 102handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg)
74{ 103{
75 struct GNUNET_SECRETSHARING_Session *s = cls; 104 struct GNUNET_SECRETSHARING_Session *session = cls;
105 struct GNUNET_SECRETSHARING_Share *share;
76 const struct GNUNET_SECRETSHARING_SecretReadyMessage *m = (const void *) msg; 106 const struct GNUNET_SECRETSHARING_SecretReadyMessage *m = (const void *) msg;
107 size_t share_size;
108
109 share_size = ntohs (m->header.size) - sizeof *m;
110
111 share = GNUNET_SECRETSHARING_share_read (&m[1], share_size, NULL);
77 112
78 s->secret_ready_cb (s->secret_ready_cls, 113 session->secret_ready_cb (session->secret_ready_cls,
79 NULL, 114 share, /* FIXME */
80 &m->public_key, 115 &share->public_key,
81 ntohs (m->num_secret_peers), 116 share->num_peers,
82 (struct GNUNET_PeerIdentity *) &m[1]); 117 (struct GNUNET_PeerIdentity *) &m[1]);
83 118
84} 119}
@@ -113,14 +148,86 @@ GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *c
113 handle_session_client_error, s); 148 handle_session_client_error, s);
114 GNUNET_assert (NULL != s->mq); 149 GNUNET_assert (NULL != s->mq);
115 150
116 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE); 151 ev = GNUNET_MQ_msg_extra (msg,
152 num_peers * sizeof (struct GNUNET_PeerIdentity),
153 GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE);
154
117 msg->threshold = htons (threshold); 155 msg->threshold = htons (threshold);
156 msg->num_peers = htons (num_peers);
157 msg->session_id = *session_id;
158 msg->deadline = GNUNET_TIME_absolute_hton (deadline);
159 memcpy (&msg[1], peers, num_peers * sizeof (struct GNUNET_PeerIdentity));
160
118 GNUNET_MQ_send (s->mq, ev); 161 GNUNET_MQ_send (s->mq, ev);
119 162
120 LOG (GNUNET_ERROR_TYPE_DEBUG, "secretsharing session created\n"); 163 LOG (GNUNET_ERROR_TYPE_DEBUG, "secretsharing session created with %u peers\n",
164 num_peers);
121 return s; 165 return s;
166}
167
122 168
169static void
170handle_decrypt_done (void *cls, const struct GNUNET_MessageHeader *msg)
171{
172 GNUNET_assert (0);
123} 173}
124 174
125 175
176/**
177 * Publish the given ciphertext for decryption. Once a sufficient (>=k) number of peers has
178 * published the same value, it will be decrypted.
179 *
180 * When the operation is canceled, the decrypt_cb is not called anymore, but the calling
181 * peer may already have irrevocably contributed his share for the decryption of the value.
182 *
183 * @param share our secret share to use for decryption
184 * @param ciphertext ciphertext to publish in order to decrypt it (if enough peers agree)
185 * @param decrypt_cb callback called once the decryption succeeded
186 * @param decrypt_cb_cls closure for @a decrypt_cb
187 * @return handle to cancel the operation
188 */
189struct GNUNET_SECRETSHARING_DecryptionHandle *
190GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg,
191 struct GNUNET_SECRETSHARING_Share *share,
192 struct GNUNET_SECRETSHARING_Ciphertext *ciphertext,
193 struct GNUNET_TIME_Absolute deadline,
194 GNUNET_SECRETSHARING_DecryptCallback decrypt_cb,
195 void *decrypt_cb_cls)
196{
197 struct GNUNET_SECRETSHARING_DecryptionHandle *s;
198 struct GNUNET_MQ_Envelope *ev;
199 struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg;
200 static const struct GNUNET_MQ_MessageHandler mq_handlers[] = {
201 {handle_decrypt_done, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE, 0},
202 GNUNET_MQ_HANDLERS_END
203 };
204 size_t share_size;
205
206
207 s = GNUNET_new (struct GNUNET_SECRETSHARING_DecryptionHandle);
208 s->client = GNUNET_CLIENT_connect ("secretsharing", cfg);
209 s->decrypt_cb = decrypt_cb;
210 s->decrypt_cls = decrypt_cb_cls;
211 GNUNET_assert (NULL != s->client);
212
213 s->mq = GNUNET_MQ_queue_for_connection_client (s->client, mq_handlers,
214 handle_decrypt_client_error, s);
215 GNUNET_assert (NULL != s->mq);
216
217 GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
218
219 ev = GNUNET_MQ_msg_extra (msg,
220 share_size,
221 GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT);
222
223 GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &msg[1], share_size, NULL));
224
225 msg->deadline = GNUNET_TIME_absolute_hton (deadline);
226
227 GNUNET_MQ_send (s->mq, ev);
228
229 LOG (GNUNET_ERROR_TYPE_DEBUG, "decrypt session created\n");
230 return s;
231}
232
126 233
diff --git a/src/secretsharing/secretsharing_protocol.h b/src/secretsharing/secretsharing_protocol.h
index 470002f10..3778ade41 100644
--- a/src/secretsharing/secretsharing_protocol.h
+++ b/src/secretsharing/secretsharing_protocol.h
@@ -31,6 +31,7 @@
31#include "platform.h" 31#include "platform.h"
32#include "gnunet_common.h" 32#include "gnunet_common.h"
33#include "gnunet_protocols.h" 33#include "gnunet_protocols.h"
34#include "secretsharing.h"
34 35
35/** 36/**
36 * Bit length used for the Paillier crypto system. 37 * Bit length used for the Paillier crypto system.
@@ -113,6 +114,50 @@ struct GNUNET_SECRETSHARING_KeygenRevealData
113 /* values follow */ 114 /* values follow */
114}; 115};
115 116
117
118/**
119 * Data of then element put in consensus
120 * for decrypting a value.
121 */
122struct GNUNET_SECRETSHARING_DecryptData
123{
124 /*
125 * Signature over rest of the message.
126 */
127 struct GNUNET_CRYPTO_EddsaSignature signature;
128 /*
129 * Signature purpose for signing the keygen commit data.
130 */
131 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
132 /**
133 * Ciphertext we want to decrypt.
134 */
135 struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
136 /**
137 * Peer that inserts this element.
138 */
139 struct GNUNET_PeerIdentity peer;
140 /**
141 * Partial decryption, computed as c_1^{s_i}
142 */
143 struct GNUNET_SECRETSHARING_FieldElement partial_decryption;
144 /**
145 * Commitment for the non-interactive zero knowledge proof.
146 * g^\beta, with \beta < q
147 */
148 struct GNUNET_SECRETSHARING_FieldElement nizk_commit1;
149 /**
150 * Commitment for the non-interactive zero knowledge proof.
151 * c_1^\beta, with \beta < q
152 */
153 struct GNUNET_SECRETSHARING_FieldElement nizk_commit2;
154 /**
155 * Reponse to the challenge computed from the protocol transcript.
156 * r = \beta + challenge \cdot share_i
157 */
158 struct GNUNET_SECRETSHARING_FieldElement nizk_response;
159};
160
116GNUNET_NETWORK_STRUCT_END 161GNUNET_NETWORK_STRUCT_END
117 162
118#endif 163#endif
diff --git a/src/secretsharing/test_secretsharing.conf b/src/secretsharing/test_secretsharing.conf
index e69de29bb..9cbb95608 100644
--- a/src/secretsharing/test_secretsharing.conf
+++ b/src/secretsharing/test_secretsharing.conf
@@ -0,0 +1,36 @@
1[secretsharing]
2AUTOSTART = YES
3PREFIX = valgrind
4
5[consensus]
6AUTOSTART = YES
7
8[transport]
9OPTIONS = -LERROR
10
11[arm]
12DEFAULTSERVICES = core consensus set secretsharing
13
14[set]
15OPTIONS = -L INFO
16#PREFIX = valgrind --leak-check=full
17
18[testbed]
19OVERLAY_TOPOLOGY = CLIQUE
20
21[hostlist]
22SERVERS =
23
24[nat]
25# Use addresses from the local network interfaces (inluding loopback, but also others)
26USE_LOCALADDR = YES
27
28# Disable IPv6 support
29DISABLEV6 = NO
30
31# Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8)
32RETURN_LOCAL_ADDRESSES = YES
33
34[nse]
35AUTOSTART = NO
36
diff --git a/src/secretsharing/test_secretsharing_sig.c b/src/secretsharing/test_secretsharing_sig.c
new file mode 100644
index 000000000..da5f0a390
--- /dev/null
+++ b/src/secretsharing/test_secretsharing_sig.c
@@ -0,0 +1,45 @@
1/*
2 This file is part of GNUnet.
3 (C) 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 secretsharing/test_secretsharing_sig.c
23 * @brief ...
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_signatures.h"
28#include "secretsharing_protocol.h"
29
30
31int
32main (int argc, char **argv)
33{
34 struct GNUNET_SECRETSHARING_KeygenCommitData *d;
35 struct GNUNET_CRYPTO_EddsaPrivateKey *private_key;
36
37 private_key = GNUNET_CRYPTO_eddsa_key_create ();
38
39 d = GNUNET_malloc (sizeof *d);
40 d->purpose.size = htons ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
41 d->purpose.purpose = htons (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
42 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (private_key, &d->purpose, &d->signature));
43 return 0;
44}
45