mystery solved?
[oweals/gnunet.git] / src / secretsharing / gnunet-service-secretsharing.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21 /**
22  * @file secretsharing/gnunet-service-secretsharing.c
23  * @brief secret sharing service
24  * @author Florian Dold
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_time_lib.h"
29 #include "gnunet_signatures.h"
30 #include "gnunet_consensus_service.h"
31 #include "secretsharing.h"
32 #include "secretsharing_protocol.h"
33 #include <gcrypt.h>
34
35
36 #define EXTRA_CHECKS 1
37
38
39 /**
40  * Info about a peer in a key generation session.
41  */
42 struct KeygenPeerInfo
43 {
44   /**
45    * Peer identity of the peer.
46    */
47   struct GNUNET_PeerIdentity peer;
48
49   /**
50    * The peer's paillier public key.
51    * Freshly generated for each keygen session.
52    */
53   struct GNUNET_CRYPTO_PaillierPublicKey paillier_public_key;
54
55   /**
56    * The peer's commitment to its presecret.
57    */
58   gcry_mpi_t presecret_commitment;
59
60   /**
61    * Commitment to the preshare that is
62    * intended for our peer.
63    */
64   gcry_mpi_t preshare_commitment;
65
66   /**
67    * Sigma (exponentiated share) for this peer.
68    */
69   gcry_mpi_t sigma;
70
71   /**
72    * Did we successfully receive the round1 element
73    * of the peer?
74    */
75   int round1_valid;
76
77   /**
78    * Did we successfully receive the round2 element
79    * of the peer?
80    */
81   int round2_valid;
82 };
83
84
85 /**
86  * Information about a peer in a decrypt session.
87  */
88 struct DecryptPeerInfo
89 {
90   /**
91    * Identity of the peer.
92    */
93   struct GNUNET_PeerIdentity peer;
94
95   /**
96    * Original index in the key generation round.
97    * Necessary for computing the lagrange coefficients.
98    */
99   unsigned int original_index;
100
101   /**
102    * Set to the partial decryption of
103    * this peer, or NULL if we did not
104    * receive a partial decryption from this
105    * peer or the zero knowledge proof failed.
106    */
107   gcry_mpi_t partial_decryption;
108 };
109
110
111 /**
112  * State we keep per client.
113  */
114 struct ClientState;
115
116
117 /**
118  * Session to establish a threshold-shared secret.
119  */
120 struct KeygenSession
121 {
122
123   /**
124    * Current consensus, used for both DKG rounds.
125    */
126   struct GNUNET_CONSENSUS_Handle *consensus;
127
128   /**
129    * Which client is this for?
130    */
131   struct ClientState *cs;
132
133   /**
134    * Randomly generated coefficients of the polynomial for sharing our
135    * pre-secret, where 'preshares[0]' is our pre-secret.  Contains 'threshold'
136    * elements, thus represents a polynomial of degree 'threshold-1', which can
137    * be interpolated with 'threshold' data points.
138    *
139    * The pre-secret-shares 'i=1,...,num_peers' are given by evaluating this
140    * polyomial at 'i' for share i.
141    */
142   gcry_mpi_t *presecret_polynomial;
143
144   /**
145    * Minimum number of shares required to restore the secret.
146    * Also the number of coefficients for the polynomial representing
147    * the sharing.  Obviously, the polynomial then has degree threshold-1.
148    */
149   unsigned int threshold;
150
151   /**
152    * Total number of peers.
153    */
154   unsigned int num_peers;
155
156   /**
157    * Index of the local peer.
158    */
159   unsigned int local_peer;
160
161   /**
162    * Information about all participating peers.
163    * Array of size 'num_peers'.
164    */
165   struct KeygenPeerInfo *info;
166
167   /**
168    * List of all peers involved in the secret sharing session.
169    */
170   struct GNUNET_PeerIdentity *peers;
171
172   /**
173    * Identifier for this session.
174    */
175   struct GNUNET_HashCode session_id;
176
177   /**
178    * Paillier private key of our peer.
179    */
180   struct GNUNET_CRYPTO_PaillierPrivateKey paillier_private_key;
181
182   /**
183    * When would we like the key to be established?
184    */
185   struct GNUNET_TIME_Absolute deadline;
186
187   /**
188    * When does the DKG start?  Necessary to compute fractions of the
189    * operation's desired time interval.
190    */
191   struct GNUNET_TIME_Absolute start_time;
192
193   /**
194    * Index of the local peer in the ordered list
195    * of peers in the session.
196    */
197   unsigned int local_peer_idx;
198
199   /**
200    * Share of our peer.  Once preshares from other peers are received, they
201    * will be added to 'my'share.
202    */
203   gcry_mpi_t my_share;
204
205   /**
206    * Public key, will be updated when a round2 element arrives.
207    */
208   gcry_mpi_t public_key;
209 };
210
211
212 /**
213  * Session to cooperatively decrypt a value.
214  */
215 struct DecryptSession
216 {
217
218   /**
219    * Handle to the consensus over partial decryptions.
220    */
221   struct GNUNET_CONSENSUS_Handle *consensus;
222
223   /**
224    * Which client is this for?
225    */
226   struct ClientState *cs;
227
228   /**
229    * When should we start communicating for decryption?
230    */
231   struct GNUNET_TIME_Absolute start;
232
233   /**
234    * When would we like the ciphertext to be
235    * decrypted?
236    */
237   struct GNUNET_TIME_Absolute deadline;
238
239   /**
240    * Ciphertext we want to decrypt.
241    */
242   struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
243
244   /**
245    * Share of the local peer.
246    * Containts other important information, such as
247    * the list of other peers.
248    */
249   struct GNUNET_SECRETSHARING_Share *share;
250
251   /**
252    * State information about other peers.
253    */
254   struct DecryptPeerInfo *info;
255 };
256
257
258 /**
259  * State we keep per client.
260  */
261 struct ClientState
262 {
263   /**
264    * Decrypt session of the client, if any.
265    */
266   struct DecryptSession *decrypt_session;
267
268   /**
269    * Keygen session of the client, if any.
270    */
271   struct KeygenSession *keygen_session;
272
273   /**
274    * Client this is about.
275    */
276   struct GNUNET_SERVICE_Client *client;
277
278   /**
279    * MQ to talk to @a client.
280    */
281   struct GNUNET_MQ_Handle *mq;
282
283 };
284
285
286 /**
287  * The ElGamal prime field order as libgcrypt mpi.
288  * Initialized in #init_crypto_constants.
289  */
290 static gcry_mpi_t elgamal_q;
291
292 /**
293  * Modulus of the prime field used for ElGamal.
294  * Initialized in #init_crypto_constants.
295  */
296 static gcry_mpi_t elgamal_p;
297
298 /**
299  * Generator for prime field of order 'elgamal_q'.
300  * Initialized in #init_crypto_constants.
301  */
302 static gcry_mpi_t elgamal_g;
303
304 /**
305  * Peer that runs this service.
306  */
307 static struct GNUNET_PeerIdentity my_peer;
308
309 /**
310  * Peer that runs this service.
311  */
312 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_peer_private_key;
313
314 /**
315  * Configuration of this service.
316  */
317 static const struct GNUNET_CONFIGURATION_Handle *cfg;
318
319
320 /**
321  * Get the peer info belonging to a peer identity in a keygen session.
322  *
323  * @param ks The keygen session.
324  * @param peer The peer identity.
325  * @return The Keygen peer info, or NULL if the peer could not be found.
326  */
327 static struct KeygenPeerInfo *
328 get_keygen_peer_info (const struct KeygenSession *ks,
329                       const struct GNUNET_PeerIdentity *peer)
330 {
331   unsigned int i;
332   for (i = 0; i < ks->num_peers; i++)
333     if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
334       return &ks->info[i];
335   return NULL;
336 }
337
338
339 /**
340  * Get the peer info belonging to a peer identity in a decrypt session.
341  *
342  * @param ds The decrypt session.
343  * @param peer The peer identity.
344  * @return The decrypt peer info, or NULL if the peer could not be found.
345  */
346 static struct DecryptPeerInfo *
347 get_decrypt_peer_info (const struct DecryptSession *ds,
348                        const struct GNUNET_PeerIdentity *peer)
349 {
350   unsigned int i;
351   for (i = 0; i < ds->share->num_peers; i++)
352     if (0 == memcmp (peer, &ds->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
353       return &ds->info[i];
354   return NULL;
355 }
356
357
358 /**
359  * Interpolate between two points in time.
360  *
361  * @param start start time
362  * @param end end time
363  * @param num numerator of the scale factor
364  * @param denum denumerator of the scale factor
365  */
366 static struct GNUNET_TIME_Absolute
367 time_between (struct GNUNET_TIME_Absolute start,
368               struct GNUNET_TIME_Absolute end,
369               int num, int denum)
370 {
371   struct GNUNET_TIME_Absolute result;
372   uint64_t diff;
373
374   GNUNET_assert (start.abs_value_us <= end.abs_value_us);
375   diff = end.abs_value_us - start.abs_value_us;
376   result.abs_value_us = start.abs_value_us + ((diff * num) / denum);
377
378   return result;
379 }
380
381
382 /**
383  * Compare two peer identities.  Indended to be used with qsort or bsearch.
384  *
385  * @param p1 Some peer identity.
386  * @param p2 Some peer identity.
387  * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
388  */
389 static int
390 peer_id_cmp (const void *p1, const void *p2)
391 {
392   return memcmp (p1,
393                  p2,
394                  sizeof (struct GNUNET_PeerIdentity));
395 }
396
397
398 /**
399  * Get the index of a peer in an array of peers
400  *
401  * @param haystack Array of peers.
402  * @param n Size of @a haystack.
403  * @param needle Peer to find
404  * @return Index of @a needle in @a haystack, or -1 if peer
405  *         is not in the list.
406  */
407 static int
408 peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n,
409            const struct GNUNET_PeerIdentity *needle)
410 {
411   unsigned int i;
412
413   for (i = 0; i < n; i++)
414     if (0 == memcmp (&haystack[i],
415                      needle,
416                      sizeof (struct GNUNET_PeerIdentity)))
417       return i;
418   return -1;
419 }
420
421
422 /**
423  * Normalize the given list of peers, by including the local peer
424  * (if it is missing) and sorting the peers by their identity.
425  *
426  * @param listed Peers in the unnormalized list.
427  * @param num_listed Peers in the un-normalized list.
428  * @param[out] num_normalized Number of peers in the normalized list.
429  * @param[out] my_peer_idx Index of the local peer in the normalized list.
430  * @return Normalized list, must be free'd by the caller.
431  */
432 static struct GNUNET_PeerIdentity *
433 normalize_peers (struct GNUNET_PeerIdentity *listed,
434                  unsigned int num_listed,
435                  unsigned int *num_normalized,
436                  unsigned int *my_peer_idx)
437 {
438   unsigned int local_peer_in_list;
439   /* number of peers in the normalized list */
440   unsigned int n;
441   struct GNUNET_PeerIdentity *normalized;
442
443   local_peer_in_list = GNUNET_YES;
444   n = num_listed;
445   if (peer_find (listed, num_listed, &my_peer) < 0)
446   {
447     local_peer_in_list = GNUNET_NO;
448     n += 1;
449   }
450
451   normalized = GNUNET_new_array (n,
452                                  struct GNUNET_PeerIdentity);
453
454   if (GNUNET_NO == local_peer_in_list)
455     normalized[n - 1] = my_peer;
456
457   GNUNET_memcpy (normalized,
458           listed,
459           num_listed * sizeof (struct GNUNET_PeerIdentity));
460   qsort (normalized,
461          n,
462          sizeof (struct GNUNET_PeerIdentity),
463          &peer_id_cmp);
464
465   if (NULL != my_peer_idx)
466     *my_peer_idx = peer_find (normalized, n, &my_peer);
467   if (NULL != num_normalized)
468     *num_normalized = n;
469
470   return normalized;
471 }
472
473
474 /**
475  * Get a the j-th lagrange coefficient for a set of indices.
476  *
477  * @param[out] coeff the lagrange coefficient
478  * @param j lagrange coefficient we want to compute
479  * @param indices indices
480  * @param num number of indices in @a indices
481  */
482 static void
483 compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
484                               unsigned int *indices,
485                               unsigned int num)
486 {
487   unsigned int i;
488   /* numerator */
489   gcry_mpi_t n;
490   /* denominator */
491   gcry_mpi_t d;
492   /* temp value for l-j */
493   gcry_mpi_t tmp;
494
495   GNUNET_assert (0 != coeff);
496
497   GNUNET_assert (0 != (n = gcry_mpi_new (0)));
498   GNUNET_assert (0 != (d = gcry_mpi_new (0)));
499   GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
500
501   gcry_mpi_set_ui (n, 1);
502   gcry_mpi_set_ui (d, 1);
503
504   for (i = 0; i < num; i++)
505   {
506     unsigned int l = indices[i];
507     if (l == j)
508       continue;
509     gcry_mpi_mul_ui (n, n, l + 1);
510     // d <- d * (l-j)
511     gcry_mpi_set_ui (tmp, l + 1);
512     gcry_mpi_sub_ui (tmp, tmp, j + 1);
513     gcry_mpi_mul (d, d, tmp);
514   }
515
516   // gcry_mpi_invm does not like negative numbers ...
517   gcry_mpi_mod (d, d, elgamal_q);
518
519   GNUNET_assert (gcry_mpi_cmp_ui (d, 0) > 0);
520
521   // now we do the actual division, with everything mod q, as we
522   // are not operating on elements from <g>, but on exponents
523   GNUNET_assert (0 != gcry_mpi_invm (d, d, elgamal_q));
524
525   gcry_mpi_mulm (coeff, n, d, elgamal_q);
526
527   gcry_mpi_release (n);
528   gcry_mpi_release (d);
529   gcry_mpi_release (tmp);
530 }
531
532
533 /**
534  * Destroy a decrypt session, removing it from
535  * the linked list of decrypt sessions.
536  *
537  * @param ds decrypt session to destroy
538  */
539 static void
540 decrypt_session_destroy (struct DecryptSession *ds)
541 {
542   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
543               "destroying decrypt session\n");
544   if (NULL != ds->cs)
545   {
546     ds->cs->decrypt_session = NULL;
547     ds->cs = NULL;
548   }
549   if (NULL != ds->consensus)
550   {
551     GNUNET_CONSENSUS_destroy (ds->consensus);
552     ds->consensus = NULL;
553   }
554
555   if (NULL != ds->info)
556   {
557     for (unsigned int i = 0; i < ds->share->num_peers; i++)
558     {
559       if (NULL != ds->info[i].partial_decryption)
560       {
561         gcry_mpi_release (ds->info[i].partial_decryption);
562         ds->info[i].partial_decryption = NULL;
563       }
564     }
565     GNUNET_free (ds->info);
566     ds->info = NULL;
567   }
568   if (NULL != ds->share)
569   {
570     GNUNET_SECRETSHARING_share_destroy (ds->share);
571     ds->share = NULL;
572   }
573
574   GNUNET_free (ds);
575 }
576
577
578 static void
579 keygen_info_destroy (struct KeygenPeerInfo *info)
580 {
581   if (NULL != info->sigma)
582   {
583     gcry_mpi_release (info->sigma);
584     info->sigma = NULL;
585   }
586   if (NULL != info->presecret_commitment)
587   {
588     gcry_mpi_release (info->presecret_commitment);
589     info->presecret_commitment = NULL;
590   }
591   if (NULL != info->preshare_commitment)
592   {
593     gcry_mpi_release (info->preshare_commitment);
594     info->preshare_commitment = NULL;
595   }
596 }
597
598
599 static void
600 keygen_session_destroy (struct KeygenSession *ks)
601 {
602   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
603               "destroying keygen session\n");
604
605   if (NULL != ks->cs)
606   {
607     ks->cs->keygen_session = NULL;
608     ks->cs = NULL;
609   }
610   if (NULL != ks->info)
611   {
612     for (unsigned int i = 0; i < ks->num_peers; i++)
613       keygen_info_destroy (&ks->info[i]);
614     GNUNET_free (ks->info);
615     ks->info = NULL;
616   }
617
618   if (NULL != ks->consensus)
619   {
620     GNUNET_CONSENSUS_destroy (ks->consensus);
621     ks->consensus = NULL;
622   }
623
624   if (NULL != ks->presecret_polynomial)
625   {
626     for (unsigned int i = 0; i < ks->threshold; i++)
627     {
628       GNUNET_assert (NULL != ks->presecret_polynomial[i]);
629       gcry_mpi_release (ks->presecret_polynomial[i]);
630       ks->presecret_polynomial[i] = NULL;
631     }
632     GNUNET_free (ks->presecret_polynomial);
633     ks->presecret_polynomial = NULL;
634   }
635   if (NULL != ks->my_share)
636   {
637     gcry_mpi_release (ks->my_share);
638     ks->my_share = NULL;
639   }
640   if (NULL != ks->public_key)
641   {
642     gcry_mpi_release (ks->public_key);
643     ks->public_key = NULL;
644   }
645   if (NULL != ks->peers)
646   {
647     GNUNET_free (ks->peers);
648     ks->peers = NULL;
649   }
650   GNUNET_free (ks);
651 }
652
653
654 /**
655  * Task run during shutdown.
656  *
657  * @param cls unused
658  * @param tc unused
659  */
660 static void
661 cleanup_task (void *cls)
662 {
663   /* Nothing to do! */
664 }
665
666
667
668 /**
669  * Generate the random coefficients of our pre-secret polynomial
670  *
671  * @param ks the session
672  */
673 static void
674 generate_presecret_polynomial (struct KeygenSession *ks)
675 {
676   int i;
677   gcry_mpi_t v;
678
679   GNUNET_assert (NULL == ks->presecret_polynomial);
680   ks->presecret_polynomial = GNUNET_new_array (ks->threshold,
681                                                gcry_mpi_t);
682   for (i = 0; i < ks->threshold; i++)
683   {
684     v = ks->presecret_polynomial[i] = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS);
685     GNUNET_assert (NULL != v);
686     // Randomize v such that 0 < v < elgamal_q.
687     // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
688     do
689     {
690       gcry_mpi_randomize (v, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
691     } while ((gcry_mpi_cmp_ui (v, 0) == 0) || (gcry_mpi_cmp (v, elgamal_q) >= 0));
692   }
693 }
694
695
696 /**
697  * Consensus element handler for round one.
698  * We should get one ephemeral key for each peer.
699  *
700  * @param cls Closure (keygen session).
701  * @param element The element from consensus, or
702  *                NULL if consensus failed.
703  */
704 static void
705 keygen_round1_new_element (void *cls,
706                            const struct GNUNET_SET_Element *element)
707 {
708   const struct GNUNET_SECRETSHARING_KeygenCommitData *d;
709   struct KeygenSession *ks = cls;
710   struct KeygenPeerInfo *info;
711
712   if (NULL == element)
713   {
714     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n");
715     return;
716   }
717
718   /* elements have fixed size */
719   if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
720   {
721     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
722                 "keygen commit data with wrong size (%u) in consensus, %u expected\n",
723                 (unsigned int) element->size,
724                 (unsigned int) sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData));
725     return;
726   }
727
728   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
729
730   d = element->data;
731   info = get_keygen_peer_info (ks, &d->peer);
732
733   if (NULL == info)
734   {
735     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
736                 GNUNET_i2s (&d->peer));
737     return;
738   }
739
740   /* Check that the right amount of data has been signed. */
741   if (d->purpose.size !=
742       htonl (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)))
743   {
744     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong signature purpose size in consensus\n");
745     return;
746   }
747
748   if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1,
749                                                &d->purpose, &d->signature, &d->peer.public_key))
750   {
751     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n");
752     return;
753   }
754   info->paillier_public_key = d->pubkey;
755   GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->commitment, 512 / 8);
756   info->round1_valid = GNUNET_YES;
757 }
758
759
760 /**
761  * Evaluate the polynomial with coefficients @a coeff at @a x.
762  * The i-th element in @a coeff corresponds to the coefficient of x^i.
763  *
764  * @param[out] z result of the evaluation
765  * @param coeff array of coefficients
766  * @param num_coeff number of coefficients
767  * @param x where to evaluate the polynomial
768  * @param m what group are we operating in?
769  */
770 static void
771 horner_eval (gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
772 {
773   unsigned int i;
774
775   gcry_mpi_set_ui (z, 0);
776   for (i = 0; i < num_coeff; i++)
777   {
778     // z <- zx + c
779     gcry_mpi_mul (z, z, x);
780     gcry_mpi_addm (z, z, coeff[num_coeff - i - 1], m);
781   }
782 }
783
784
785 static void
786 keygen_round2_conclude (void *cls)
787 {
788   struct KeygenSession *ks = cls;
789   struct GNUNET_SECRETSHARING_SecretReadyMessage *m;
790   struct GNUNET_MQ_Envelope *ev;
791   size_t share_size;
792   unsigned int i;
793   unsigned int j;
794   struct GNUNET_SECRETSHARING_Share *share;
795
796   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
797
798   GNUNET_CONSENSUS_destroy (ks->consensus);
799   ks->consensus = NULL;
800
801   share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
802
803   share->num_peers = 0;
804
805   for (i = 0; i < ks->num_peers; i++)
806     if (GNUNET_YES == ks->info[i].round2_valid)
807       share->num_peers++;
808
809   share->peers = GNUNET_new_array (share->num_peers,
810                                    struct GNUNET_PeerIdentity);
811   share->sigmas =
812       GNUNET_new_array (share->num_peers,
813                         struct GNUNET_SECRETSHARING_FieldElement);
814   share->original_indices = GNUNET_new_array (share->num_peers,
815                                               uint16_t);
816
817   /* maybe we're not even in the list of peers? */
818   share->my_peer = share->num_peers;
819
820   j = 0; /* running index of valid peers */
821   for (i = 0; i < ks->num_peers; i++)
822   {
823     if (GNUNET_YES == ks->info[i].round2_valid)
824     {
825       share->peers[j] = ks->info[i].peer;
826       GNUNET_CRYPTO_mpi_print_unsigned (&share->sigmas[j],
827                                         GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
828                                         ks->info[i].sigma);
829       share->original_indices[i] = j;
830       if (0 == memcmp (&share->peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
831         share->my_peer = j;
832       j += 1;
833     }
834   }
835
836   if (share->my_peer == share->num_peers)
837   {
838     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: peer identity not in share\n", ks->local_peer_idx);
839   }
840
841   GNUNET_CRYPTO_mpi_print_unsigned (&share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
842                                     ks->my_share);
843   GNUNET_CRYPTO_mpi_print_unsigned (&share->public_key, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
844                                     ks->public_key);
845
846   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers);
847
848   /* Write the share. If 0 peers completed the dkg, an empty
849    * share will be sent. */
850
851   GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
852
853   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "writing share of size %u\n",
854               (unsigned int) share_size);
855
856   ev = GNUNET_MQ_msg_extra (m, share_size,
857                             GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY);
858
859   GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &m[1], share_size, NULL));
860
861   GNUNET_SECRETSHARING_share_destroy (share);
862   share = NULL;
863
864   GNUNET_MQ_send (ks->cs->mq,
865                   ev);
866 }
867
868
869
870 static void
871 restore_fair (const struct GNUNET_CRYPTO_PaillierPublicKey *ppub,
872               const struct GNUNET_SECRETSHARING_FairEncryption *fe,
873               gcry_mpi_t x, gcry_mpi_t xres)
874 {
875   gcry_mpi_t a_1;
876   gcry_mpi_t a_2;
877   gcry_mpi_t b_1;
878   gcry_mpi_t b_2;
879   gcry_mpi_t big_a;
880   gcry_mpi_t big_b;
881   gcry_mpi_t big_t;
882   gcry_mpi_t n;
883   gcry_mpi_t t_1;
884   gcry_mpi_t t_2;
885   gcry_mpi_t t;
886   gcry_mpi_t r;
887   gcry_mpi_t v;
888
889
890   GNUNET_assert (NULL != (n = gcry_mpi_new (0)));
891   GNUNET_assert (NULL != (t = gcry_mpi_new (0)));
892   GNUNET_assert (NULL != (t_1 = gcry_mpi_new (0)));
893   GNUNET_assert (NULL != (t_2 = gcry_mpi_new (0)));
894   GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
895   GNUNET_assert (NULL != (big_t = gcry_mpi_new (0)));
896   GNUNET_assert (NULL != (v = gcry_mpi_new (0)));
897   GNUNET_assert (NULL != (big_a = gcry_mpi_new (0)));
898   GNUNET_assert (NULL != (big_b = gcry_mpi_new (0)));
899
900   // a = (N,0)^T
901   GNUNET_CRYPTO_mpi_scan_unsigned (&a_1, ppub, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
902   GNUNET_assert (NULL != (a_2 = gcry_mpi_new (0)));
903   gcry_mpi_set_ui (a_2, 0);
904   // b = (x,1)^T
905   GNUNET_assert (NULL != (b_1 = gcry_mpi_new (0)));
906   gcry_mpi_set (b_1, x);
907   GNUNET_assert (NULL != (b_2 = gcry_mpi_new (0)));
908   gcry_mpi_set_ui (b_2, 1);
909
910   // A = a DOT a
911   gcry_mpi_mul (t, a_1, a_1);
912   gcry_mpi_mul (big_a, a_2, a_2);
913   gcry_mpi_add (big_a, big_a, t);
914
915   // B = b DOT b
916   gcry_mpi_mul (t, b_1, b_1);
917   gcry_mpi_mul (big_b, b_2, b_2);
918   gcry_mpi_add (big_b, big_b, t);
919
920   while (1)
921   {
922     // n = a DOT b
923     gcry_mpi_mul (t, a_1, b_1);
924     gcry_mpi_mul (n, a_2, b_2);
925     gcry_mpi_add (n, n, t);
926
927     // r = nearest(n/B)
928     gcry_mpi_div (r, NULL, n, big_b, 0);
929
930     // T := A - 2rn + rrB
931     gcry_mpi_mul (v, r, n);
932     gcry_mpi_mul_ui (v, v, 2);
933     gcry_mpi_sub (big_t, big_a, v);
934     gcry_mpi_mul (v, r, r);
935     gcry_mpi_mul (v, v, big_b);
936     gcry_mpi_add (big_t, big_t, v);
937
938     if (gcry_mpi_cmp (big_t, big_b) >= 0)
939     {
940       break;
941     }
942
943     // t = a - rb
944     gcry_mpi_mul (v, r, b_1);
945     gcry_mpi_sub (t_1, a_1, v);
946     gcry_mpi_mul (v, r, b_2);
947     gcry_mpi_sub (t_2, a_2, v);
948
949     // a = b
950     gcry_mpi_set (a_1, b_1);
951     gcry_mpi_set (a_2, b_2);
952     // b = t
953     gcry_mpi_set (b_1, t_1);
954     gcry_mpi_set (b_2, t_2);
955
956     gcry_mpi_set (big_a, big_b);
957     gcry_mpi_set (big_b, big_t);
958   }
959
960   {
961     gcry_mpi_t paillier_n;
962
963     GNUNET_CRYPTO_mpi_scan_unsigned (&paillier_n, ppub, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
964
965     gcry_mpi_set (xres, b_2);
966     gcry_mpi_invm (xres, xres, elgamal_q);
967     gcry_mpi_mulm (xres, xres, b_1, elgamal_q);
968   }
969
970   gcry_mpi_release (a_1);
971   gcry_mpi_release (a_2);
972   gcry_mpi_release (b_1);
973   gcry_mpi_release (b_2);
974   gcry_mpi_release (big_a);
975   gcry_mpi_release (big_b);
976   gcry_mpi_release (big_t);
977   gcry_mpi_release (n);
978   gcry_mpi_release (t_1);
979   gcry_mpi_release (t_2);
980   gcry_mpi_release (t);
981   gcry_mpi_release (r);
982   gcry_mpi_release (v);
983 }
984
985
986 static void
987 get_fair_encryption_challenge (const struct GNUNET_SECRETSHARING_FairEncryption *fe,
988                                gcry_mpi_t *e)
989 {
990   struct {
991     struct GNUNET_CRYPTO_PaillierCiphertext c;
992     char h[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
993     char t1[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
994     char t2[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8];
995   } hash_data;
996   struct GNUNET_HashCode e_hash;
997
998   memset (&hash_data,
999           0,
1000           sizeof (hash_data));
1001   GNUNET_memcpy (&hash_data.c, &fe->c, sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
1002   GNUNET_memcpy (&hash_data.h, &fe->h, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1003   GNUNET_memcpy (&hash_data.t1, &fe->t1, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1004   GNUNET_memcpy (&hash_data.t2, &fe->t2, GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8);
1005   GNUNET_CRYPTO_hash (&hash_data,
1006                       sizeof (hash_data),
1007                       &e_hash);
1008   /* This allocates "e" */
1009   GNUNET_CRYPTO_mpi_scan_unsigned (e,
1010                                    &e_hash,
1011                                    sizeof (struct GNUNET_HashCode));
1012   gcry_mpi_mod (*e, *e, elgamal_q);
1013 }
1014
1015
1016 static int
1017 verify_fair (const struct GNUNET_CRYPTO_PaillierPublicKey *ppub,
1018              const struct GNUNET_SECRETSHARING_FairEncryption *fe)
1019 {
1020   gcry_mpi_t n;
1021   gcry_mpi_t n_sq;
1022   gcry_mpi_t z;
1023   gcry_mpi_t t1;
1024   gcry_mpi_t t2;
1025   gcry_mpi_t e;
1026   gcry_mpi_t w;
1027   gcry_mpi_t tmp1;
1028   gcry_mpi_t tmp2;
1029   gcry_mpi_t y;
1030   gcry_mpi_t big_y;
1031   int res;
1032
1033   GNUNET_assert (NULL != (n_sq = gcry_mpi_new (0)));
1034   GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0)));
1035   GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0)));
1036
1037   get_fair_encryption_challenge (fe,
1038                                  &e /* this allocates e */);
1039
1040   GNUNET_CRYPTO_mpi_scan_unsigned (&n,
1041                                    ppub,
1042                                    sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
1043   GNUNET_CRYPTO_mpi_scan_unsigned (&t1, fe->t1, GNUNET_CRYPTO_PAILLIER_BITS / 8);
1044   GNUNET_CRYPTO_mpi_scan_unsigned (&z, fe->z, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1045   GNUNET_CRYPTO_mpi_scan_unsigned (&y, fe->h, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1046   GNUNET_CRYPTO_mpi_scan_unsigned (&w, fe->w, GNUNET_CRYPTO_PAILLIER_BITS / 8);
1047   GNUNET_CRYPTO_mpi_scan_unsigned (&big_y, fe->c.bits, GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8);
1048   GNUNET_CRYPTO_mpi_scan_unsigned (&t2, fe->t2, GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8);
1049   gcry_mpi_mul (n_sq, n, n);
1050
1051   // tmp1 = g^z
1052   gcry_mpi_powm (tmp1, elgamal_g, z, elgamal_p);
1053   // tmp2 = y^{-e}
1054   gcry_mpi_powm (tmp1, y, e, elgamal_p);
1055   gcry_mpi_invm (tmp1, tmp1, elgamal_p);
1056   // tmp1 = tmp1 * tmp2
1057   gcry_mpi_mulm (tmp1, tmp1, tmp2, elgamal_p);
1058
1059   if (0 == gcry_mpi_cmp (t1, tmp1))
1060   {
1061     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "fair encryption invalid (t1)\n");
1062     res = GNUNET_NO;
1063     goto cleanup;
1064   }
1065
1066   gcry_mpi_powm (big_y, big_y, e, n_sq);
1067   gcry_mpi_invm (big_y, big_y, n_sq);
1068
1069   gcry_mpi_add_ui (tmp1, n, 1);
1070   gcry_mpi_powm (tmp1, tmp1, z, n_sq);
1071
1072   gcry_mpi_powm (tmp2, w, n, n_sq);
1073
1074   gcry_mpi_mulm (tmp1, tmp1, tmp2, n_sq);
1075   gcry_mpi_mulm (tmp1, tmp1, big_y, n_sq);
1076
1077
1078   if (0 == gcry_mpi_cmp (t2, tmp1))
1079   {
1080     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "fair encryption invalid (t2)\n");
1081     res = GNUNET_NO;
1082     goto cleanup;
1083   }
1084
1085   res = GNUNET_YES;
1086
1087 cleanup:
1088
1089   gcry_mpi_release (n);
1090   gcry_mpi_release (n_sq);
1091   gcry_mpi_release (z);
1092   gcry_mpi_release (t1);
1093   gcry_mpi_release (t2);
1094   gcry_mpi_release (e);
1095   gcry_mpi_release (w);
1096   gcry_mpi_release (tmp1);
1097   gcry_mpi_release (tmp2);
1098   gcry_mpi_release (y);
1099   gcry_mpi_release (big_y);
1100   return res;
1101 }
1102
1103
1104 /**
1105  * Create a fair Paillier encryption of then given ciphertext.
1106  *
1107  * @param v the ciphertext
1108  * @param[out] fe the fair encryption
1109  */
1110 static void
1111 encrypt_fair (gcry_mpi_t v,
1112               const struct GNUNET_CRYPTO_PaillierPublicKey *ppub,
1113               struct GNUNET_SECRETSHARING_FairEncryption *fe)
1114 {
1115   gcry_mpi_t r;
1116   gcry_mpi_t s;
1117   gcry_mpi_t t1;
1118   gcry_mpi_t t2;
1119   gcry_mpi_t z;
1120   gcry_mpi_t w;
1121   gcry_mpi_t n;
1122   gcry_mpi_t e;
1123   gcry_mpi_t n_sq;
1124   gcry_mpi_t u;
1125   gcry_mpi_t Y;
1126   gcry_mpi_t G;
1127   gcry_mpi_t h;
1128
1129   GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
1130   GNUNET_assert (NULL != (s = gcry_mpi_new (0)));
1131   GNUNET_assert (NULL != (t1 = gcry_mpi_new (0)));
1132   GNUNET_assert (NULL != (t2 = gcry_mpi_new (0)));
1133   GNUNET_assert (NULL != (z = gcry_mpi_new (0)));
1134   GNUNET_assert (NULL != (w = gcry_mpi_new (0)));
1135   GNUNET_assert (NULL != (n_sq = gcry_mpi_new (0)));
1136   GNUNET_assert (NULL != (u = gcry_mpi_new (0)));
1137   GNUNET_assert (NULL != (Y = gcry_mpi_new (0)));
1138   GNUNET_assert (NULL != (G = gcry_mpi_new (0)));
1139   GNUNET_assert (NULL != (h = gcry_mpi_new (0)));
1140
1141   GNUNET_CRYPTO_mpi_scan_unsigned (&n,
1142                                    ppub,
1143                                    sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
1144   gcry_mpi_mul (n_sq, n, n);
1145   gcry_mpi_add_ui (G, n, 1);
1146
1147   do {
1148     gcry_mpi_randomize (u, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM);
1149   }
1150   while (gcry_mpi_cmp (u, n) >= 0);
1151
1152   gcry_mpi_powm (t1, G, v, n_sq);
1153   gcry_mpi_powm (t2, u, n, n_sq);
1154   gcry_mpi_mulm (Y, t1, t2, n_sq);
1155
1156   GNUNET_CRYPTO_mpi_print_unsigned (fe->c.bits,
1157                                     sizeof fe->c.bits,
1158                                     Y);
1159
1160
1161   gcry_mpi_randomize (r, 2048, GCRY_WEAK_RANDOM);
1162   do {
1163     gcry_mpi_randomize (s, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM);
1164   }
1165   while (gcry_mpi_cmp (s, n) >= 0);
1166
1167   // compute t1
1168   gcry_mpi_mulm (t1, elgamal_g, r, elgamal_p);
1169   // compute t2 (use z and w as temp)
1170   gcry_mpi_powm (z, G, r, n_sq);
1171   gcry_mpi_powm (w, s, n, n_sq);
1172   gcry_mpi_mulm (t2, z, w, n_sq);
1173
1174
1175   gcry_mpi_powm (h, elgamal_g, v, elgamal_p);
1176
1177   GNUNET_CRYPTO_mpi_print_unsigned (fe->h,
1178                                     GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
1179                                     h);
1180
1181   GNUNET_CRYPTO_mpi_print_unsigned (fe->t1,
1182                                     GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
1183                                     t1);
1184
1185   GNUNET_CRYPTO_mpi_print_unsigned (fe->t2,
1186                                     GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8,
1187                                     t2);
1188
1189   get_fair_encryption_challenge (fe,
1190                                  &e /* This allocates "e" */);
1191
1192   // compute z
1193   gcry_mpi_mul (z, e, v);
1194   gcry_mpi_addm (z, z, r, elgamal_q);
1195   // compute w
1196   gcry_mpi_powm (w, u, e, n);
1197   gcry_mpi_mulm (w, w, s, n);
1198
1199   GNUNET_CRYPTO_mpi_print_unsigned (fe->z,
1200                                     GNUNET_SECRETSHARING_ELGAMAL_BITS / 8,
1201                                     z);
1202
1203   GNUNET_CRYPTO_mpi_print_unsigned (fe->w,
1204                                     GNUNET_CRYPTO_PAILLIER_BITS / 8,
1205                                     w);
1206
1207   gcry_mpi_release (n);
1208   gcry_mpi_release (r);
1209   gcry_mpi_release (s);
1210   gcry_mpi_release (t1);
1211   gcry_mpi_release (t2);
1212   gcry_mpi_release (z);
1213   gcry_mpi_release (w);
1214   gcry_mpi_release (e);
1215   gcry_mpi_release (n_sq);
1216   gcry_mpi_release (u);
1217   gcry_mpi_release (Y);
1218   gcry_mpi_release (G);
1219   gcry_mpi_release (h);
1220 }
1221
1222
1223 /**
1224  * Insert round 2 element in the consensus, consisting of
1225  * (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}}
1226  * (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}}
1227  * (3) The encrypted pre-shares Y_{i,j}
1228  * (4) The zero knowledge proof for fairness of
1229  *     the encryption
1230  *
1231  * @param ks session to use
1232  */
1233 static void
1234 insert_round2_element (struct KeygenSession *ks)
1235 {
1236   struct GNUNET_SET_Element *element;
1237   struct GNUNET_SECRETSHARING_KeygenRevealData *d;
1238   unsigned char *pos;
1239   unsigned char *last_pos;
1240   size_t element_size;
1241   unsigned int i;
1242   gcry_mpi_t idx;
1243   gcry_mpi_t v;
1244
1245   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting round2 element\n",
1246               ks->local_peer_idx);
1247
1248   GNUNET_assert (NULL != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1249   GNUNET_assert (NULL != (idx = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1250
1251   element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
1252                   sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * ks->num_peers +
1253                   GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold);
1254
1255   element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
1256   element->size = element_size;
1257   element->data = (void *) &element[1];
1258
1259   d = (void *) element->data;
1260   d->peer = my_peer;
1261
1262   // start inserting vector elements
1263   // after the fixed part of the element's data
1264   pos = (void *) &d[1];
1265   last_pos = pos + element_size;
1266
1267   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp preshares\n",
1268               ks->local_peer_idx);
1269
1270   // encrypted pre-shares
1271   // and fair encryption proof
1272   {
1273     for (i = 0; i < ks->num_peers; i++)
1274     {
1275       ptrdiff_t remaining = last_pos - pos;
1276       struct GNUNET_SECRETSHARING_FairEncryption *fe = (void *) pos;
1277
1278       GNUNET_assert (remaining > 0);
1279       memset (fe, 0, sizeof *fe);
1280       if (GNUNET_YES == ks->info[i].round1_valid)
1281       {
1282         gcry_mpi_set_ui (idx, i + 1);
1283         // evaluate the polynomial
1284         horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q);
1285         // encrypt the result
1286         encrypt_fair (v, &ks->info[i].paillier_public_key, fe);
1287       }
1288       pos += sizeof *fe;
1289     }
1290   }
1291
1292   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed enc preshares\n",
1293               ks->local_peer_idx);
1294
1295   // exponentiated coefficients
1296   for (i = 0; i < ks->threshold; i++)
1297   {
1298     ptrdiff_t remaining = last_pos - pos;
1299     GNUNET_assert (remaining > 0);
1300     gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
1301     GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
1302     pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8;
1303   }
1304
1305   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp coefficients\n",
1306               ks->local_peer_idx);
1307
1308
1309   d->purpose.size = htonl (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
1310   d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2);
1311   GNUNET_assert (GNUNET_OK ==
1312                  GNUNET_CRYPTO_eddsa_sign (my_peer_private_key,
1313                                            &d->purpose,
1314                                            &d->signature));
1315
1316   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1317   GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
1318
1319   gcry_mpi_release (v);
1320   gcry_mpi_release (idx);
1321 }
1322
1323
1324 static gcry_mpi_t
1325 keygen_reveal_get_exp_coeff (struct KeygenSession *ks,
1326                              const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
1327                              unsigned int idx)
1328 {
1329   unsigned char *pos;
1330   gcry_mpi_t exp_coeff;
1331
1332   GNUNET_assert (idx < ks->threshold);
1333
1334   pos = (void *) &d[1];
1335   // skip encrypted pre-shares
1336   pos += sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * ks->num_peers;
1337   // skip exp. coeffs we are not interested in
1338   pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * idx;
1339   // the first exponentiated coefficient is the public key share
1340   GNUNET_CRYPTO_mpi_scan_unsigned (&exp_coeff, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1341   return exp_coeff;
1342 }
1343
1344
1345 static struct GNUNET_SECRETSHARING_FairEncryption *
1346 keygen_reveal_get_enc_preshare (struct KeygenSession *ks,
1347                                 const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
1348                                 unsigned int idx)
1349 {
1350   unsigned char *pos;
1351
1352   GNUNET_assert (idx < ks->num_peers);
1353
1354   pos = (void *) &d[1];
1355   // skip encrypted pre-shares we're not interested in
1356   pos += sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * idx;
1357   return (struct GNUNET_SECRETSHARING_FairEncryption *) pos;
1358 }
1359
1360
1361 static gcry_mpi_t
1362 keygen_reveal_get_exp_preshare (struct KeygenSession *ks,
1363                                 const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
1364                                 unsigned int idx)
1365 {
1366   gcry_mpi_t exp_preshare;
1367   struct GNUNET_SECRETSHARING_FairEncryption *fe;
1368
1369   GNUNET_assert (idx < ks->num_peers);
1370   fe = keygen_reveal_get_enc_preshare (ks, d, idx);
1371   GNUNET_CRYPTO_mpi_scan_unsigned (&exp_preshare, fe->h, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1372   return exp_preshare;
1373 }
1374
1375
1376 static void
1377 keygen_round2_new_element (void *cls,
1378                            const struct GNUNET_SET_Element *element)
1379 {
1380   struct KeygenSession *ks = cls;
1381   const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
1382   struct KeygenPeerInfo *info;
1383   size_t expected_element_size;
1384   unsigned int j;
1385   int cmp_result;
1386   gcry_mpi_t tmp;
1387   gcry_mpi_t public_key_share;
1388   gcry_mpi_t preshare;
1389
1390   if (NULL == element)
1391   {
1392     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n");
1393     return;
1394   }
1395
1396   expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
1397                   sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * ks->num_peers +
1398                   GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold);
1399
1400   if (element->size != expected_element_size)
1401   {
1402     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1403                 "keygen round2 data with wrong size (%u) in consensus, %u expected\n",
1404                 (unsigned int) element->size,
1405                 (unsigned int) expected_element_size);
1406     return;
1407   }
1408
1409   d = (const void *) element->data;
1410
1411   info = get_keygen_peer_info (ks, &d->peer);
1412
1413   if (NULL == info)
1414   {
1415     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
1416                 GNUNET_i2s (&d->peer));
1417     return;
1418   }
1419
1420   if (GNUNET_NO == info->round1_valid)
1421   {
1422     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1423                 "ignoring round2 element from peer with invalid round1 element (%s)\n",
1424                 GNUNET_i2s (&d->peer));
1425     return;
1426   }
1427
1428   if (GNUNET_YES == info->round2_valid)
1429   {
1430     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1431                 "ignoring duplicate round2 element (%s)\n",
1432                 GNUNET_i2s (&d->peer));
1433     return;
1434   }
1435
1436   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
1437
1438   if (ntohl (d->purpose.size) !=
1439       element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose))
1440   {
1441     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n");
1442     return;
1443   }
1444
1445   if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2,
1446                                                &d->purpose, &d->signature, &d->peer.public_key))
1447   {
1448     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n");
1449     return;
1450   }
1451
1452   public_key_share = keygen_reveal_get_exp_coeff (ks, d, 0);
1453   info->preshare_commitment = keygen_reveal_get_exp_preshare (ks, d, ks->local_peer_idx);
1454
1455   if (NULL == ks->public_key)
1456   {
1457     GNUNET_assert (NULL != (ks->public_key = gcry_mpi_new (0)));
1458     gcry_mpi_set_ui (ks->public_key, 1);
1459   }
1460   gcry_mpi_mulm (ks->public_key, ks->public_key, public_key_share, elgamal_p);
1461
1462   gcry_mpi_release (public_key_share);
1463   public_key_share = NULL;
1464
1465   {
1466     struct GNUNET_SECRETSHARING_FairEncryption *fe = keygen_reveal_get_enc_preshare (ks, d, ks->local_peer_idx);
1467     GNUNET_assert (NULL != (preshare = gcry_mpi_new (0)));
1468     GNUNET_CRYPTO_paillier_decrypt (&ks->paillier_private_key,
1469                                     &ks->info[ks->local_peer_idx].paillier_public_key,
1470                                     &fe->c,
1471                                     preshare);
1472
1473     // FIXME: not doing the restoration is less expensive
1474     restore_fair (&ks->info[ks->local_peer_idx].paillier_public_key,
1475                   fe,
1476                   preshare,
1477                   preshare);
1478   }
1479
1480   GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
1481   gcry_mpi_powm (tmp, elgamal_g, preshare, elgamal_p);
1482
1483   cmp_result = gcry_mpi_cmp (tmp, info->preshare_commitment);
1484   gcry_mpi_release (tmp);
1485   tmp = NULL;
1486   if (0 != cmp_result)
1487   {
1488     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Got invalid presecret from P%u\n",
1489                 (unsigned int) ks->local_peer_idx, (unsigned int) (info - ks->info));
1490     return;
1491   }
1492
1493   if (NULL == ks->my_share)
1494   {
1495     GNUNET_assert (NULL != (ks->my_share = gcry_mpi_new (0)));
1496   }
1497   gcry_mpi_addm (ks->my_share, ks->my_share, preshare, elgamal_q);
1498
1499   for (j = 0; j < ks->num_peers; j++)
1500   {
1501     gcry_mpi_t presigma;
1502     if (NULL == ks->info[j].sigma)
1503     {
1504       GNUNET_assert (NULL != (ks->info[j].sigma = gcry_mpi_new (0)));
1505       gcry_mpi_set_ui (ks->info[j].sigma, 1);
1506     }
1507     presigma = keygen_reveal_get_exp_preshare (ks, d, j);
1508     gcry_mpi_mulm (ks->info[j].sigma, ks->info[j].sigma, presigma, elgamal_p);
1509     gcry_mpi_release (presigma);
1510   }
1511
1512   gcry_mpi_t prod;
1513   GNUNET_assert (NULL != (prod = gcry_mpi_new (0)));
1514   gcry_mpi_t j_to_k;
1515   GNUNET_assert (NULL != (j_to_k = gcry_mpi_new (0)));
1516   // validate that the polynomial sharing matches the additive sharing
1517   for (j = 0; j < ks->num_peers; j++)
1518   {
1519     unsigned int k;
1520     int cmp_result;
1521     gcry_mpi_t exp_preshare;
1522     gcry_mpi_set_ui (prod, 1);
1523     for (k = 0; k < ks->threshold; k++)
1524     {
1525       // Using pow(double,double) is a bit sketchy.
1526       // We count players from 1, but shares from 0.
1527       gcry_mpi_t tmp;
1528       gcry_mpi_set_ui (j_to_k, (unsigned int) pow(j+1, k));
1529       tmp = keygen_reveal_get_exp_coeff (ks, d, k);
1530       gcry_mpi_powm (tmp, tmp, j_to_k, elgamal_p);
1531       gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1532       gcry_mpi_release (tmp);
1533     }
1534     exp_preshare = keygen_reveal_get_exp_preshare (ks, d, j);
1535     gcry_mpi_mod (exp_preshare, exp_preshare, elgamal_p);
1536     cmp_result = gcry_mpi_cmp (prod, exp_preshare);
1537     gcry_mpi_release (exp_preshare);
1538     exp_preshare = NULL;
1539     if (0 != cmp_result)
1540     {
1541       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: reveal data from P%u incorrect\n",
1542                   ks->local_peer_idx, j);
1543       /* no need for further verification, round2 stays invalid ... */
1544       return;
1545     }
1546   }
1547
1548   // TODO: verify proof of fair encryption (once implemented)
1549   for (j = 0; j < ks->num_peers; j++)
1550   {
1551     struct GNUNET_SECRETSHARING_FairEncryption *fe = keygen_reveal_get_enc_preshare (ks, d, j);
1552     if (GNUNET_YES != verify_fair (&ks->info[j].paillier_public_key, fe))
1553     {
1554       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: reveal data from P%u incorrect (fair encryption)\n",
1555                   ks->local_peer_idx, j);
1556       return;
1557     }
1558
1559   }
1560
1561   info->round2_valid = GNUNET_YES;
1562
1563   gcry_mpi_release (preshare);
1564   gcry_mpi_release (prod);
1565   gcry_mpi_release (j_to_k);
1566 }
1567
1568
1569 /**
1570  * Called when the first consensus round has concluded.
1571  * Will initiate the second round.
1572  *
1573  * @param cls closure
1574  */
1575 static void
1576 keygen_round1_conclude (void *cls)
1577 {
1578   struct KeygenSession *ks = cls;
1579
1580   GNUNET_CONSENSUS_destroy (ks->consensus);
1581
1582   ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
1583                                            time_between (ks->start_time, ks->deadline, 1, 2),
1584                                            ks->deadline,
1585                                            keygen_round2_new_element, ks);
1586
1587   insert_round2_element (ks);
1588
1589   GNUNET_CONSENSUS_conclude (ks->consensus,
1590                              keygen_round2_conclude,
1591                              ks);
1592 }
1593
1594
1595 /**
1596  * Insert the ephemeral key and the presecret commitment
1597  * of this peer in the consensus of the given session.
1598  *
1599  * @param ks session to use
1600  */
1601 static void
1602 insert_round1_element (struct KeygenSession *ks)
1603 {
1604   struct GNUNET_SET_Element *element;
1605   struct GNUNET_SECRETSHARING_KeygenCommitData *d;
1606   // g^a_{i,0}
1607   gcry_mpi_t v;
1608   // big-endian representation of 'v'
1609   unsigned char v_data[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
1610
1611   element = GNUNET_malloc (sizeof *element + sizeof *d);
1612   d = (void *) &element[1];
1613   element->data = d;
1614   element->size = sizeof *d;
1615
1616   d->peer = my_peer;
1617
1618   GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1619
1620   gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
1621
1622   GNUNET_CRYPTO_mpi_print_unsigned (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
1623
1624   GNUNET_CRYPTO_hash (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, &d->commitment);
1625
1626   d->pubkey = ks->info[ks->local_peer_idx].paillier_public_key;
1627
1628   d->purpose.size = htonl ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
1629   d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
1630   GNUNET_assert (GNUNET_OK ==
1631                  GNUNET_CRYPTO_eddsa_sign (my_peer_private_key,
1632                                            &d->purpose,
1633                                            &d->signature));
1634
1635   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1636
1637   gcry_mpi_release (v);
1638   GNUNET_free (element);
1639 }
1640
1641
1642 /**
1643  * Check that @a msg is well-formed.
1644  *
1645  * @param cls identification of the client
1646  * @param msg the actual message
1647  * @return #GNUNET_OK if @a msg is well-formed
1648  */
1649 static int
1650 check_client_keygen (void *cls,
1651                      const struct GNUNET_SECRETSHARING_CreateMessage *msg)
1652 {
1653   unsigned int num_peers = ntohs (msg->num_peers);
1654
1655   if (ntohs (msg->header.size) - sizeof (*msg) !=
1656       num_peers * sizeof (struct GNUNET_PeerIdentity))
1657   {
1658     GNUNET_break (0);
1659     return GNUNET_SYSERR;
1660   }
1661   return GNUNET_OK;
1662 }
1663
1664
1665 /**
1666  * Functions with this signature are called whenever a message is
1667  * received.
1668  *
1669  * @param cls identification of the client
1670  * @param msg the actual message
1671  */
1672 static void
1673 handle_client_keygen (void *cls,
1674                       const struct GNUNET_SECRETSHARING_CreateMessage *msg)
1675 {
1676   struct ClientState *cs = cls;
1677   struct KeygenSession *ks;
1678
1679   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1680               "client requested key generation\n");
1681   if (NULL != cs->keygen_session)
1682   {
1683     GNUNET_break (0);
1684     GNUNET_SERVICE_client_drop (cs->client);
1685     return;
1686   }
1687   ks = GNUNET_new (struct KeygenSession);
1688   ks->cs = cs;
1689   cs->keygen_session = ks;
1690   ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
1691   ks->threshold = ntohs (msg->threshold);
1692   ks->num_peers = ntohs (msg->num_peers);
1693
1694   ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1],
1695                                ks->num_peers,
1696                                &ks->num_peers,
1697                                &ks->local_peer_idx);
1698
1699
1700   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1701               "first round of consensus with %u peers\n",
1702               ks->num_peers);
1703   ks->consensus = GNUNET_CONSENSUS_create (cfg,
1704                                            ks->num_peers,
1705                                            ks->peers,
1706                                            &msg->session_id,
1707                                            GNUNET_TIME_absolute_ntoh (msg->start),
1708                                            GNUNET_TIME_absolute_ntoh (msg->deadline),
1709                                            keygen_round1_new_element,
1710                                            ks);
1711
1712   ks->info = GNUNET_new_array (ks->num_peers,
1713                                struct KeygenPeerInfo);
1714
1715   for (unsigned int i = 0; i < ks->num_peers; i++)
1716     ks->info[i].peer = ks->peers[i];
1717
1718   GNUNET_CRYPTO_paillier_create (&ks->info[ks->local_peer_idx].paillier_public_key,
1719                                  &ks->paillier_private_key);
1720
1721   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1722               "P%u: Generated paillier key pair\n",
1723               ks->local_peer_idx);
1724   generate_presecret_polynomial (ks);
1725   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1726               "P%u: Generated presecret polynomial\n",
1727               ks->local_peer_idx);
1728   insert_round1_element (ks);
1729   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1730               "P%u: Concluding for round 1\n",
1731               ks->local_peer_idx);
1732   GNUNET_CONSENSUS_conclude (ks->consensus,
1733                              keygen_round1_conclude,
1734                              ks);
1735   GNUNET_SERVICE_client_continue (cs->client);
1736   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1737               "P%u: Waiting for round 1 elements ...\n",
1738               ks->local_peer_idx);
1739 }
1740
1741
1742 /**
1743  * Called when the partial decryption consensus concludes.
1744  */
1745 static void
1746 decrypt_conclude (void *cls)
1747 {
1748   struct DecryptSession *ds = cls;
1749   struct GNUNET_SECRETSHARING_DecryptResponseMessage *msg;
1750   struct GNUNET_MQ_Envelope *ev;
1751   gcry_mpi_t lagrange;
1752   gcry_mpi_t m;
1753   gcry_mpi_t tmp;
1754   gcry_mpi_t c_2;
1755   gcry_mpi_t prod;
1756   unsigned int *indices;
1757   unsigned int num;
1758   unsigned int i;
1759   unsigned int j;
1760
1761   GNUNET_CONSENSUS_destroy (ds->consensus);
1762   ds->consensus = NULL;
1763
1764   GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
1765   GNUNET_assert (0 != (m = gcry_mpi_new (0)));
1766   GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
1767   GNUNET_assert (0 != (prod = gcry_mpi_new (0)));
1768
1769   num = 0;
1770   for (i = 0; i < ds->share->num_peers; i++)
1771     if (NULL != ds->info[i].partial_decryption)
1772       num++;
1773
1774   indices = GNUNET_new_array (num,
1775                               unsigned int);
1776   j = 0;
1777   for (i = 0; i < ds->share->num_peers; i++)
1778     if (NULL != ds->info[i].partial_decryption)
1779       indices[j++] = ds->info[i].original_index;
1780
1781   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1782               "P%u: decrypt conclude, with %u peers\n",
1783               ds->share->my_peer,
1784               num);
1785
1786   gcry_mpi_set_ui (prod, 1);
1787   for (i = 0; i < num; i++)
1788   {
1789
1790     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1791                 "P%u: index of %u: %u\n",
1792                 ds->share->my_peer, i, indices[i]);
1793     compute_lagrange_coefficient (lagrange, indices[i], indices, num);
1794     // w_i^{\lambda_i}
1795     gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p);
1796
1797     // product of all exponentiated partiel decryptions ...
1798     gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1799   }
1800
1801   GNUNET_CRYPTO_mpi_scan_unsigned (&c_2, ds->ciphertext.c2_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1802
1803   GNUNET_assert (0 != gcry_mpi_invm (prod, prod, elgamal_p));
1804   gcry_mpi_mulm (m, c_2, prod, elgamal_p);
1805   ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE);
1806   GNUNET_CRYPTO_mpi_print_unsigned (&msg->plaintext, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, m);
1807   msg->success = htonl (1);
1808   GNUNET_MQ_send (ds->cs->mq,
1809                   ev);
1810
1811   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sent decrypt done to client\n");
1812
1813   GNUNET_free (indices);
1814
1815   gcry_mpi_release(lagrange);
1816   gcry_mpi_release(m);
1817   gcry_mpi_release(tmp);
1818   gcry_mpi_release(prod);
1819   gcry_mpi_release(c_2);
1820
1821   // FIXME: what if not enough peers participated?
1822 }
1823
1824
1825 /**
1826  * Get a string representation of an MPI.
1827  * The caller must free the returned string.
1828  *
1829  * @param mpi mpi to convert to a string
1830  * @return string representation of @a mpi, must be free'd by the caller
1831  */
1832 static char *
1833 mpi_to_str (gcry_mpi_t mpi)
1834 {
1835   unsigned char *buf;
1836
1837   GNUNET_assert (0 == gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, mpi));
1838   return (char *) buf;
1839 }
1840
1841
1842 /**
1843  * Called when a new partial decryption arrives.
1844  */
1845 static void
1846 decrypt_new_element (void *cls,
1847                      const struct GNUNET_SET_Element *element)
1848 {
1849   struct DecryptSession *session = cls;
1850   const struct GNUNET_SECRETSHARING_DecryptData *d;
1851   struct DecryptPeerInfo *info;
1852   struct GNUNET_HashCode challenge_hash;
1853
1854   /* nizk response */
1855   gcry_mpi_t r;
1856   /* nizk challenge */
1857   gcry_mpi_t challenge;
1858   /* nizk commit1, g^\beta */
1859   gcry_mpi_t commit1;
1860   /* nizk commit2, c_1^\beta */
1861   gcry_mpi_t commit2;
1862   /* homomorphic commitment to the peer's share,
1863    * public key share */
1864   gcry_mpi_t sigma;
1865   /* partial decryption we received */
1866   gcry_mpi_t w;
1867   /* ciphertext component #1 */
1868   gcry_mpi_t c1;
1869   /* temporary variable (for comparision) #1 */
1870   gcry_mpi_t tmp1;
1871   /* temporary variable (for comparision) #2 */
1872   gcry_mpi_t tmp2;
1873
1874   if (NULL == element)
1875   {
1876     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1877     /* FIXME: destroy */
1878     return;
1879   }
1880
1881   if (element->size != sizeof *d)
1882   {
1883     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element of wrong size in decrypt consensus\n");
1884     return;
1885   }
1886
1887   d = element->data;
1888
1889   info = get_decrypt_peer_info (session, &d->peer);
1890
1891   if (NULL == info)
1892   {
1893     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element from invalid peer (%s)\n",
1894                 GNUNET_i2s (&d->peer));
1895     return;
1896   }
1897
1898   if (NULL != info->partial_decryption)
1899   {
1900     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n");
1901     return;
1902   }
1903
1904   if (0 != memcmp (&d->ciphertext, &session->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext)))
1905   {
1906     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: got decrypt element with non-matching ciphertext from P%u\n",
1907                 (unsigned int) session->share->my_peer, (unsigned int) (info - session->info));
1908
1909     return;
1910   }
1911
1912
1913   GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) d,
1914                       offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) -
1915                           offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext),
1916                       &challenge_hash);
1917
1918   GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
1919                                    sizeof (struct GNUNET_HashCode));
1920
1921   GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &session->share->sigmas[info - session->info],
1922                                    sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1923
1924   GNUNET_CRYPTO_mpi_scan_unsigned (&c1, session->ciphertext.c1_bits,
1925                                    sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1926
1927   GNUNET_CRYPTO_mpi_scan_unsigned (&commit1, &d->nizk_commit1,
1928                                    sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1929
1930   GNUNET_CRYPTO_mpi_scan_unsigned (&commit2, &d->nizk_commit2,
1931                                    sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1932
1933   GNUNET_CRYPTO_mpi_scan_unsigned (&r, &d->nizk_response,
1934                                    sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1935
1936   GNUNET_CRYPTO_mpi_scan_unsigned (&w, &d->partial_decryption,
1937                                    sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1938
1939   GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0)));
1940   GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0)));
1941
1942   // tmp1 = g^r
1943   gcry_mpi_powm (tmp1, elgamal_g, r, elgamal_p);
1944
1945   // tmp2 = g^\beta * \sigma^challenge
1946   gcry_mpi_powm (tmp2, sigma, challenge, elgamal_p);
1947   gcry_mpi_mulm (tmp2, tmp2, commit1, elgamal_p);
1948
1949   if (0 != gcry_mpi_cmp (tmp1, tmp2))
1950   {
1951     char *tmp1_str;
1952     char *tmp2_str;
1953
1954     tmp1_str = mpi_to_str (tmp1);
1955     tmp2_str = mpi_to_str (tmp2);
1956     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1957                 "P%u: Received invalid partial decryption from P%u (eqn 1), expected %s got %s\n",
1958                 session->share->my_peer,
1959                 (unsigned int) (info - session->info),
1960                 tmp1_str,
1961                 tmp2_str);
1962     GNUNET_free (tmp1_str);
1963     GNUNET_free (tmp2_str);
1964     goto cleanup;
1965   }
1966
1967
1968   gcry_mpi_powm (tmp1, c1, r, elgamal_p);
1969
1970   gcry_mpi_powm (tmp2, w, challenge, elgamal_p);
1971   gcry_mpi_mulm (tmp2, tmp2, commit2, elgamal_p);
1972
1973
1974   if (0 != gcry_mpi_cmp (tmp1, tmp2))
1975   {
1976     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1977                 "P%u: Received invalid partial decryption from P%u (eqn 2)\n",
1978                 session->share->my_peer,
1979                 (unsigned int) (info - session->info));
1980     goto cleanup;
1981   }
1982
1983
1984   GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption,
1985                                    GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1986 cleanup:
1987   gcry_mpi_release (tmp1);
1988   gcry_mpi_release (tmp2);
1989   gcry_mpi_release (sigma);
1990   gcry_mpi_release (commit1);
1991   gcry_mpi_release (commit2);
1992   gcry_mpi_release (r);
1993   gcry_mpi_release (w);
1994   gcry_mpi_release (challenge);
1995   gcry_mpi_release (c1);
1996 }
1997
1998
1999 static void
2000 insert_decrypt_element (struct DecryptSession *ds)
2001 {
2002   struct GNUNET_SECRETSHARING_DecryptData d;
2003   struct GNUNET_SET_Element element;
2004   /* our share */
2005   gcry_mpi_t s;
2006   /* partial decryption with our share */
2007   gcry_mpi_t w;
2008   /* first component of the elgamal ciphertext */
2009   gcry_mpi_t c1;
2010   /* nonce for dlog zkp */
2011   gcry_mpi_t beta;
2012   gcry_mpi_t tmp;
2013   gcry_mpi_t challenge;
2014   gcry_mpi_t sigma;
2015   struct GNUNET_HashCode challenge_hash;
2016
2017   /* make vagrind happy until we implement the real deal ... */
2018   memset (&d, 0, sizeof d);
2019
2020   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n",
2021               ds->share->my_peer);
2022
2023   GNUNET_assert (ds->share->my_peer < ds->share->num_peers);
2024
2025   GNUNET_CRYPTO_mpi_scan_unsigned (&c1, &ds->ciphertext.c1_bits,
2026                                    GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
2027   GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share,
2028                                    GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
2029   GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &ds->share->sigmas[ds->share->my_peer],
2030                                    GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
2031
2032   GNUNET_assert (NULL != (w = gcry_mpi_new (0)));
2033   GNUNET_assert (NULL != (beta = gcry_mpi_new (0)));
2034   GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
2035
2036   // FIXME: unnecessary, remove once crypto works
2037   gcry_mpi_powm (tmp, elgamal_g, s, elgamal_p);
2038   if (0 != gcry_mpi_cmp (tmp, sigma))
2039   {
2040     char *sigma_str = mpi_to_str (sigma);
2041     char *tmp_str = mpi_to_str (tmp);
2042     char *s_str = mpi_to_str (s);
2043     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Share of P%u is invalid, ref sigma %s, "
2044                 "computed sigma %s, s %s\n",
2045                 ds->share->my_peer,
2046                 sigma_str, tmp_str, s_str);
2047     GNUNET_free (sigma_str);
2048     GNUNET_free (tmp_str);
2049     GNUNET_free (s_str);
2050   }
2051
2052   gcry_mpi_powm (w, c1, s, elgamal_p);
2053
2054   element.data = (void *) &d;
2055   element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
2056   element.element_type = 0;
2057
2058   d.ciphertext = ds->ciphertext;
2059   d.peer = my_peer;
2060   GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, w);
2061
2062   // create the zero knowledge proof
2063   // randomly choose beta such that 0 < beta < q
2064   do
2065   {
2066     gcry_mpi_randomize (beta, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
2067   } while ((gcry_mpi_cmp_ui (beta, 0) == 0) || (gcry_mpi_cmp (beta, elgamal_q) >= 0));
2068   // tmp = g^beta
2069   gcry_mpi_powm (tmp, elgamal_g, beta, elgamal_p);
2070   GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit1, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp);
2071   // tmp = (c_1)^beta
2072   gcry_mpi_powm (tmp, c1, beta, elgamal_p);
2073   GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit2, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp);
2074
2075   // the challenge is the hash of everything up to the response
2076   GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) &d,
2077                       offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) -
2078                           offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext),
2079                       &challenge_hash);
2080
2081   GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
2082                                    sizeof (struct GNUNET_HashCode));
2083
2084   // compute the response in tmp,
2085   // tmp = (c * s + beta) mod q
2086   gcry_mpi_mulm (tmp, challenge, s, elgamal_q);
2087   gcry_mpi_addm (tmp, tmp, beta, elgamal_q);
2088
2089   GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_response, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp);
2090
2091   d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose));
2092   d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
2093
2094   GNUNET_assert (GNUNET_OK ==
2095                  GNUNET_CRYPTO_eddsa_sign (my_peer_private_key,
2096                                            &d.purpose,
2097                                            &d.signature));
2098
2099   GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
2100   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2101               "P%u: Inserting decrypt element done!\n",
2102               ds->share->my_peer);
2103
2104   gcry_mpi_release (s);
2105   gcry_mpi_release (w);
2106   gcry_mpi_release (c1);
2107   gcry_mpi_release (beta);
2108   gcry_mpi_release (tmp);
2109   gcry_mpi_release (challenge);
2110   gcry_mpi_release (sigma);
2111 }
2112
2113
2114 /**
2115  * Check that @a msg is well-formed.
2116  *
2117  * @param cls identification of the client
2118  * @param msg the actual message
2119  * @return #GNUNET_OK (check deferred a bit)
2120  */
2121 static int
2122 check_client_decrypt (void *cls,
2123                       const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg)
2124 {
2125   /* we check later, it's complicated */
2126   return GNUNET_OK;
2127 }
2128
2129
2130 /**
2131  * Functions with this signature are called whenever a message is
2132  * received.
2133  *
2134  * @param cls identification of the client
2135  * @param msg the actual message
2136  */
2137 static void
2138 handle_client_decrypt (void *cls,
2139                        const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg)
2140 {
2141   struct ClientState *cs = cls;
2142   struct DecryptSession *ds;
2143   struct GNUNET_HashCode session_id;
2144
2145   if (NULL != cs->decrypt_session)
2146   {
2147     GNUNET_break (0);
2148     GNUNET_SERVICE_client_drop (cs->client);
2149     return;
2150   }
2151   ds = GNUNET_new (struct DecryptSession);
2152   cs->decrypt_session = ds;
2153   ds->cs = cs;
2154   ds->start = GNUNET_TIME_absolute_ntoh (msg->start);
2155   ds->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
2156   ds->ciphertext = msg->ciphertext;
2157
2158   ds->share = GNUNET_SECRETSHARING_share_read (&msg[1],
2159                                                ntohs (msg->header.size) - sizeof (*msg),
2160                                                NULL);
2161   if (NULL == ds->share)
2162   {
2163     GNUNET_break (0);
2164     GNUNET_SERVICE_client_drop (cs->client);
2165     return;
2166   }
2167
2168   /* FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ... */
2169   GNUNET_CRYPTO_hash (&msg->ciphertext,
2170                       sizeof (struct GNUNET_SECRETSHARING_Ciphertext),
2171                       &session_id);
2172   ds->consensus = GNUNET_CONSENSUS_create (cfg,
2173                                            ds->share->num_peers,
2174                                            ds->share->peers,
2175                                            &session_id,
2176                                            ds->start,
2177                                            ds->deadline,
2178                                            &decrypt_new_element,
2179                                            ds);
2180
2181
2182   ds->info = GNUNET_new_array (ds->share->num_peers,
2183                                struct DecryptPeerInfo);
2184   for (unsigned int i = 0; i < ds->share->num_peers; i++)
2185   {
2186     ds->info[i].peer = ds->share->peers[i];
2187     ds->info[i].original_index = ds->share->original_indices[i];
2188   }
2189   insert_decrypt_element (ds);
2190   GNUNET_CONSENSUS_conclude (ds->consensus,
2191                              decrypt_conclude,
2192                              ds);
2193   GNUNET_SERVICE_client_continue (cs->client);
2194   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2195               "decrypting with %u peers\n",
2196               ds->share->num_peers);
2197 }
2198
2199
2200 static void
2201 init_crypto_constants (void)
2202 {
2203   GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
2204                                      GNUNET_SECRETSHARING_ELGAMAL_Q_HEX, 0, NULL));
2205   GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
2206                                      GNUNET_SECRETSHARING_ELGAMAL_P_HEX, 0, NULL));
2207   GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
2208                                      GNUNET_SECRETSHARING_ELGAMAL_G_HEX, 0, NULL));
2209 }
2210
2211
2212 /**
2213  * Initialize secretsharing service.
2214  *
2215  * @param cls closure
2216  * @param c configuration to use
2217  * @param service the initialized service
2218  */
2219 static void
2220 run (void *cls,
2221      const struct GNUNET_CONFIGURATION_Handle *c,
2222      struct GNUNET_SERVICE_Handle *service)
2223 {
2224   cfg = c;
2225   my_peer_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
2226   if (NULL == my_peer_private_key)
2227   {
2228     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2229                 "could not access host private key\n");
2230     GNUNET_break (0);
2231     GNUNET_SCHEDULER_shutdown ();
2232     return;
2233   }
2234   init_crypto_constants ();
2235   if (GNUNET_OK !=
2236       GNUNET_CRYPTO_get_peer_identity (cfg,
2237                                        &my_peer))
2238   {
2239     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2240                 "could not retrieve host identity\n");
2241     GNUNET_break (0);
2242     GNUNET_SCHEDULER_shutdown ();
2243     return;
2244   }
2245   GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
2246                                  NULL);
2247 }
2248
2249
2250 /**
2251  * Callback called when a client connects to the service.
2252  *
2253  * @param cls closure for the service
2254  * @param c the new client that connected to the service
2255  * @param mq the message queue used to send messages to the client
2256  * @return @a c
2257  */
2258 static void *
2259 client_connect_cb (void *cls,
2260                    struct GNUNET_SERVICE_Client *c,
2261                    struct GNUNET_MQ_Handle *mq)
2262 {
2263   struct ClientState *cs = GNUNET_new (struct ClientState);;
2264
2265   cs->client = c;
2266   cs->mq = mq;
2267   return cs;
2268 }
2269
2270
2271 /**
2272  * Callback called when a client disconnected from the service
2273  *
2274  * @param cls closure for the service
2275  * @param c the client that disconnected
2276  * @param internal_cls should be equal to @a c
2277  */
2278 static void
2279 client_disconnect_cb (void *cls,
2280                       struct GNUNET_SERVICE_Client *c,
2281                       void *internal_cls)
2282 {
2283   struct ClientState *cs = internal_cls;
2284
2285   if (NULL != cs->keygen_session)
2286     keygen_session_destroy (cs->keygen_session);
2287
2288   if (NULL != cs->decrypt_session)
2289     decrypt_session_destroy (cs->decrypt_session);
2290   GNUNET_free (cs);
2291 }
2292
2293
2294 /**
2295  * Define "main" method using service macro.
2296  */
2297 GNUNET_SERVICE_MAIN
2298 ("secretsharing",
2299  GNUNET_SERVICE_OPTION_NONE,
2300  &run,
2301  &client_connect_cb,
2302  &client_disconnect_cb,
2303  NULL,
2304  GNUNET_MQ_hd_var_size (client_keygen,
2305                         GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE,
2306                         struct GNUNET_SECRETSHARING_CreateMessage,
2307                         NULL),
2308  GNUNET_MQ_hd_var_size (client_decrypt,
2309                         GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT,
2310                         struct GNUNET_SECRETSHARING_DecryptRequestMessage,
2311                         NULL),
2312  GNUNET_MQ_handler_end ());