diff options
Diffstat (limited to 'src/secretsharing/gnunet-service-secretsharing.c')
-rw-r--r-- | src/secretsharing/gnunet-service-secretsharing.c | 772 |
1 files changed, 657 insertions, 115 deletions
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 | |||
86 | struct 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 | ||
171 | struct DecryptSession | 213 | struct 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; | 266 | static 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; | 271 | static 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; | |||
222 | static struct GNUNET_PeerIdentity my_peer; | 304 | static struct GNUNET_PeerIdentity my_peer; |
223 | 305 | ||
224 | /** | 306 | /** |
307 | * Peer that runs this service. | ||
308 | */ | ||
309 | static struct GNUNET_CRYPTO_EddsaPrivateKey *my_peer_private_key; | ||
310 | |||
311 | /** | ||
225 | * Configuration of this service. | 312 | * Configuration of this service. |
226 | */ | 313 | */ |
227 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 314 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
@@ -231,20 +318,79 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; | |||
231 | */ | 318 | */ |
232 | static struct GNUNET_SERVER_Handle *srv; | 319 | static struct GNUNET_SERVER_Handle *srv; |
233 | 320 | ||
321 | /** | ||
322 | * Print a field element in a fixed-size buffer. | ||
323 | */ | ||
324 | static void | ||
325 | print_field_element (void *buf, gcry_mpi_t x) | ||
326 | { | ||
327 | GNUNET_assert (0); | ||
328 | } | ||
329 | |||
330 | |||
331 | static struct KeygenPeerInfo * | ||
332 | get_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 | |||
343 | static struct DecryptPeerInfo * | ||
344 | get_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 | |||
355 | static struct GNUNET_TIME_Absolute | ||
356 | time_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 | */ |
244 | static int | 378 | static int |
245 | hash_cmp (const void *h1, const void *h2) | 379 | peer_id_cmp (const void *p1, const void *p2) |
380 | { | ||
381 | return memcmp (p1, p2, sizeof (struct GNUNET_PeerIdentity)); | ||
382 | } | ||
383 | |||
384 | |||
385 | int | ||
386 | peer_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 | */ | ||
450 | static void | ||
451 | compute_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 | */ | ||
442 | static void | 634 | static void |
443 | keygen_round1_new_element (void *cls, | 635 | keygen_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 | |||
548 | insert_round2_element (struct KeygenSession *ks) | 795 | insert_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 | ||
622 | static struct KeygenPeerInfo * | ||
623 | get_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 | |||
634 | static void | 873 | static void |
635 | keygen_round2_new_element (void *cls, | 874 | keygen_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 | */ | ||
681 | static void | 982 | static void |
682 | keygen_round1_conclude (void *cls) | 983 | keygen_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 | */ | ||
1127 | static void | ||
1128 | decrypt_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 | */ | ||
1186 | static void | ||
1187 | decrypt_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 | |||
1231 | static void | ||
1232 | insert_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 | */ |
802 | static void handle_client_decrypt (void *cls, | 1266 | static 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 | |||
1304 | static void | ||
1305 | init_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"); |