- gnunet-secretsharing-profiler.c should not have exec flag set
[oweals/gnunet.git] / src / secretsharing / gnunet-service-secretsharing.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file secretsharing/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   gcry_mpi_t paillier_n;
54
55   /**
56    * The peer's commitment to his presecret.
57    */
58   gcry_mpi_t presecret_commitment;
59
60   /**
61    * The peer's preshare that we decrypted
62    * with out private key.
63    */
64   gcry_mpi_t decrypted_preshare;
65
66   /**
67    * Multiplicative share of the public key.
68    */
69   gcry_mpi_t public_key_share;
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  * Session to establish a threshold-shared secret.
113  */
114 struct KeygenSession
115 {
116   /**
117    * Keygen sessions are held in a linked list.
118    */
119   struct KeygenSession *next;
120
121   /**
122    * Keygen sessions are held in a linked list.
123    */
124   struct KeygenSession *prev;
125
126   /**
127    * Current consensus, used for both DKG rounds.
128    */
129   struct GNUNET_CONSENSUS_Handle *consensus;
130
131   /**
132    * Client that is interested in the result
133    * of this key generation session.
134    */
135   struct GNUNET_SERVER_Client *client;
136
137   /**
138    * Message queue for 'client'
139    */
140   struct GNUNET_MQ_Handle *client_mq;
141
142   /**
143    * Randomly generated coefficients of the polynomial for sharing our
144    * pre-secret, where 'preshares[0]' is our pre-secret.  Contains 'threshold'
145    * elements, thus represents a polynomial of degree 'threshold-1', which can
146    * be interpolated with 'threshold' data points.
147    *
148    * The pre-secret-shares 'i=1,...,num_peers' are given by evaluating this
149    * polyomial at 'i' for share i.
150    */
151   gcry_mpi_t *presecret_polynomial;
152
153   /**
154    * Minimum number of shares required to restore the secret.
155    * Also the number of coefficients for the polynomial representing
156    * the sharing.  Obviously, the polynomial then has degree threshold-1.
157    */
158   unsigned int threshold;
159
160   /**
161    * Total number of peers.
162    */
163   unsigned int num_peers;
164
165   /**
166    * Index of the local peer.
167    */
168   unsigned int local_peer;
169
170   /**
171    * Information about all participating peers.
172    * Array of size 'num_peers'.
173    */
174   struct KeygenPeerInfo *info;
175
176   /**
177    * List of all peers involved in the secret sharing session.
178    */
179   struct GNUNET_PeerIdentity *peers;
180
181   /**
182    * Identifier for this session.
183    */
184   struct GNUNET_HashCode session_id;
185
186   /**
187    * lambda-component of our peer's paillier private key.
188    */
189   gcry_mpi_t paillier_lambda;
190
191   /**
192    * mu-component of our peer's paillier private key.
193    */
194   gcry_mpi_t paillier_mu;
195
196   /**
197    * When would we like the key to be established?
198    */
199   struct GNUNET_TIME_Absolute deadline;
200
201   /**
202    * When does the DKG start?  Necessary to compute fractions of the
203    * operation's desired time interval.
204    */
205   struct GNUNET_TIME_Absolute start_time;
206
207   /**
208    * Index of the local peer in the ordered list
209    * of peers in the session.
210    */
211   unsigned int local_peer_idx;
212 };
213
214
215 /**
216  * Session to cooperatively decrypt a value.
217  */
218 struct DecryptSession
219 {
220   /**
221    * Decrypt sessions are stored in a linked list.
222    */
223   struct DecryptSession *next;
224
225   /**
226    * Decrypt sessions are stored in a linked list.
227    */
228   struct DecryptSession *prev;
229
230   /**
231    * Handle to the consensus over partial decryptions.
232    */
233   struct GNUNET_CONSENSUS_Handle *consensus;
234
235   /**
236    * Client connected to us.
237    */
238   struct GNUNET_SERVER_Client *client;
239
240   /**
241    * Message queue for 'client'.
242    */
243   struct GNUNET_MQ_Handle *client_mq;
244
245   /**
246    * When would we like the ciphertext to be
247    * decrypted?
248    */
249   struct GNUNET_TIME_Absolute deadline;
250
251   /**
252    * Ciphertext we want to decrypt.
253    */
254   struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
255
256   /**
257    * Share of the local peer.
258    * Containts other important information, such as
259    * the list of other peers.
260    */
261   struct GNUNET_SECRETSHARING_Share *share;
262
263   /**
264    * State information about other peers.
265    */
266   struct DecryptPeerInfo *info;
267 };
268
269
270 /**
271  * Decrypt sessions are held in a linked list.
272  */
273 static struct DecryptSession *decrypt_sessions_head;
274
275 /**
276  * Decrypt sessions are held in a linked list.
277  */
278 static struct DecryptSession *decrypt_sessions_tail;
279
280 /**
281  * Decrypt sessions are held in a linked list.
282  */
283 static struct KeygenSession *keygen_sessions_head;
284
285 /**
286  * Decrypt sessions are held in a linked list.
287  */
288 static struct KeygenSession *keygen_sessions_tail;
289
290 /**
291  * The ElGamal prime field order as libgcrypt mpi.
292  * Initialized in #init_crypto_constants.
293  */
294 static gcry_mpi_t elgamal_q;
295
296 /**
297  * Modulus of the prime field used for ElGamal.
298  * Initialized in #init_crypto_constants.
299  */
300 static gcry_mpi_t elgamal_p;
301
302 /**
303  * Generator for prime field of order 'elgamal_q'.
304  * Initialized in #init_crypto_constants.
305  */
306 static gcry_mpi_t elgamal_g;
307
308 /**
309  * Peer that runs this service.
310  */
311 static struct GNUNET_PeerIdentity my_peer;
312
313 /**
314  * Peer that runs this service.
315  */
316 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_peer_private_key;
317
318 /**
319  * Configuration of this service.
320  */
321 static const struct GNUNET_CONFIGURATION_Handle *cfg;
322
323 /**
324  * Server for this service.
325  */
326 static struct GNUNET_SERVER_Handle *srv;
327
328
329 /**
330  * Get the peer info belonging to a peer identity in a keygen session.
331  *
332  * @param ks The keygen session.
333  * @param peer The peer identity.
334  * @return The Keygen peer info, or NULL if the peer could not be found.
335  */
336 static struct KeygenPeerInfo *
337 get_keygen_peer_info (const struct KeygenSession *ks,
338                       const struct GNUNET_PeerIdentity *peer)
339 {
340   unsigned int i;
341   for (i = 0; i < ks->num_peers; i++)
342     if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
343       return &ks->info[i];
344   return NULL;
345 }
346
347
348 /**
349  * Get the peer info belonging to a peer identity in a decrypt session.
350  *
351  * @param ds The decrypt session.
352  * @param peer The peer identity.
353  * @return The decrypt peer info, or NULL if the peer could not be found.
354  */
355 static struct DecryptPeerInfo *
356 get_decrypt_peer_info (const struct DecryptSession *ds,
357                        const struct GNUNET_PeerIdentity *peer)
358 {
359   unsigned int i;
360   for (i = 0; i < ds->share->num_peers; i++)
361     if (0 == memcmp (peer, &ds->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
362       return &ds->info[i];
363   return NULL;
364 }
365
366
367 /**
368  * Interpolate between two points in time.
369  *
370  * @param start start time
371  * @param end end time
372  * @param num numerator of the scale factor
373  * @param denum denumerator of the scale factor
374  */
375 static struct GNUNET_TIME_Absolute
376 time_between (struct GNUNET_TIME_Absolute start,
377               struct GNUNET_TIME_Absolute end,
378               int num, int denum)
379 {
380   struct GNUNET_TIME_Absolute result;
381   uint64_t diff;
382
383   GNUNET_assert (start.abs_value_us <= end.abs_value_us);
384   diff = end.abs_value_us - start.abs_value_us;
385   result.abs_value_us = start.abs_value_us + ((diff * num) / denum);
386
387   return result;
388 }
389
390
391 /**
392  * Compare two peer identities.  Indended to be used with qsort or bsearch.
393  *
394  * @param p1 Some peer identity.
395  * @param p2 Some peer identity.
396  * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
397  */
398 static int
399 peer_id_cmp (const void *p1, const void *p2)
400 {
401   return memcmp (p1, p2, sizeof (struct GNUNET_PeerIdentity));
402 }
403
404
405 /**
406  * Get the index of a peer in an array of peers
407  *
408  * @param haystack Array of peers.
409  * @param n Size of @a haystack.
410  * @param needle Peer to find
411  * @return Index of @a needle in @a haystack, or -1 if peer
412  *         is not in the list.
413  */
414 static int
415 peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n,
416            const struct GNUNET_PeerIdentity *needle)
417 {
418   unsigned int i;
419   for (i = 0; i < n; i++)
420     if (0 == memcmp (&haystack[i], needle, sizeof (struct GNUNET_PeerIdentity)))
421       return i;
422   return -1;
423 }
424
425
426 /**
427  * Normalize the given list of peers, by including the local peer
428  * (if it is missing) and sorting the peers by their identity.
429  *
430  * @param listed Peers in the unnormalized list.
431  * @param num_listed Peers in the un-normalized list.
432  * @param[out] num_normalized Number of peers in the normalized list.
433  * @param[out] my_peer_idx Index of the local peer in the normalized list.
434  * @return Normalized list, must be free'd by the caller.
435  */
436 static struct GNUNET_PeerIdentity *
437 normalize_peers (struct GNUNET_PeerIdentity *listed,
438                  unsigned int num_listed,
439                  unsigned int *num_normalized,
440                  unsigned int *my_peer_idx)
441 {
442   unsigned int local_peer_in_list;
443   /* number of peers in the normalized list */
444   unsigned int n;
445   struct GNUNET_PeerIdentity *normalized;
446
447   local_peer_in_list = GNUNET_YES;
448   n = num_listed;
449   if (peer_find (listed, num_listed, &my_peer) < 0)
450   {
451     local_peer_in_list = GNUNET_NO;
452     n += 1;
453   }
454
455   normalized = GNUNET_new_array (n, struct GNUNET_PeerIdentity);
456
457   if (GNUNET_NO == local_peer_in_list)
458     normalized[n - 1] = my_peer;
459
460   memcpy (normalized, listed, num_listed * sizeof (struct GNUNET_PeerIdentity));
461   qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp);
462
463   if (NULL != my_peer_idx)
464     *my_peer_idx = peer_find (normalized, n, &my_peer);
465   if (NULL != num_normalized)
466     *num_normalized = n;
467
468   return normalized;
469 }
470
471
472 /**
473  * Get a the j-th lagrange coefficient for a set of indices.
474  *
475  * @param[out] coeff the lagrange coefficient
476  * @param j lagrange coefficient we want to compute
477  * @param indices indices
478  * @param num number of indices in @a indices
479  */
480 static void
481 compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
482                               unsigned int *indices,
483                               unsigned int num)
484 {
485   unsigned int i;
486   /* numerator */
487   gcry_mpi_t n;
488   /* denominator */
489   gcry_mpi_t d;
490   /* temp value for l-j */
491   gcry_mpi_t tmp;
492
493   GNUNET_assert (0 != coeff);
494
495   GNUNET_assert (0 != (n = gcry_mpi_new (0)));
496   GNUNET_assert (0 != (d = gcry_mpi_new (0)));
497   GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
498
499   gcry_mpi_set_ui (n, 1);
500   gcry_mpi_set_ui (d, 1);
501
502   for (i = 0; i < num; i++)
503   {
504     unsigned int l = indices[i];
505     if (l == j)
506       continue;
507     gcry_mpi_mul_ui (n, n, l + 1);
508     // d <- d * (l-j)
509     gcry_mpi_set_ui (tmp, l + 1);
510     gcry_mpi_sub_ui (tmp, tmp, j + 1);
511     gcry_mpi_mul (d, d, tmp);
512   }
513
514   // gcry_mpi_invm does not like negative numbers ...
515   gcry_mpi_mod (d, d, elgamal_q);
516
517   GNUNET_assert (gcry_mpi_cmp_ui (d, 0) > 0);
518
519   // now we do the actual division, with everything mod q, as we
520   // are not operating on elements from <g>, but on exponents
521   GNUNET_assert (0 != gcry_mpi_invm (d, d, elgamal_q));
522
523   gcry_mpi_mulm (coeff, n, d, elgamal_q);
524
525   gcry_mpi_release (n);
526   gcry_mpi_release (d);
527   gcry_mpi_release (tmp);
528 }
529
530
531 /**
532  * Create a key pair for the paillier crypto system.
533  *
534  * Uses the simplified key generation of Jonathan Katz, Yehuda Lindell,
535  * "Introduction to Modern Cryptography: Principles and Protocols".
536  *
537  * @param n n-component of public key
538  * @param lambda lambda-component of private key
539  * @param mu mu-componenent of private key
540  */
541 static void
542 paillier_create (gcry_mpi_t n, gcry_mpi_t lambda, gcry_mpi_t mu)
543 {
544   gcry_mpi_t p;
545   gcry_mpi_t q;
546   gcry_mpi_t phi;
547   gcry_mpi_t tmp;
548
549   GNUNET_assert (NULL != (phi = gcry_mpi_new (PAILLIER_BITS)));
550   GNUNET_assert (NULL != (tmp = gcry_mpi_new (PAILLIER_BITS)));
551
552   p = q = NULL;
553
554   // Generate two distinct primes.
555   // The probability that the loop body
556   // is executed more than once is very low.
557   do {
558     if (NULL != p)
559       gcry_mpi_release (p);
560     if (NULL != q)
561       gcry_mpi_release (q);
562     // generate rsa modulus
563     GNUNET_assert (0 == gcry_prime_generate (&p, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
564                                              GCRY_WEAK_RANDOM, 0));
565     GNUNET_assert (0 == gcry_prime_generate (&q, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
566                                            GCRY_WEAK_RANDOM, 0));
567   } while (0 == gcry_mpi_cmp (p, q));
568   gcry_mpi_mul (n, p, q);
569   // compute phi(n) = (p-1)(q-1)
570   gcry_mpi_sub_ui (phi, p, 1);
571   gcry_mpi_sub_ui (tmp, q, 1);
572   gcry_mpi_mul (phi, phi, tmp);
573   gcry_mpi_set (lambda, phi);
574   // compute mu
575   GNUNET_assert (0 != gcry_mpi_invm (mu, phi, n));
576
577   gcry_mpi_release (p);
578   gcry_mpi_release (q);
579   gcry_mpi_release (phi);
580   gcry_mpi_release (tmp);
581 }
582
583
584 /**
585  * Encrypt a value using Paillier's scheme.
586  *
587  * @param[out] c resulting ciphertext
588  * @param m plaintext to encrypt
589  * @param n n-component of public key
590  */
591 static void
592 paillier_encrypt (gcry_mpi_t c, gcry_mpi_t m, gcry_mpi_t n)
593 {
594   gcry_mpi_t n_square;
595   gcry_mpi_t r;
596   gcry_mpi_t g;
597
598   GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
599   GNUNET_assert (0 != (r = gcry_mpi_new (0)));
600   GNUNET_assert (0 != (g = gcry_mpi_new (0)));
601
602   gcry_mpi_add_ui (g, n, 1);
603
604   gcry_mpi_mul (n_square, n, n);
605
606   // generate r < n
607   do
608   {
609     gcry_mpi_randomize (r, PAILLIER_BITS, GCRY_WEAK_RANDOM);
610   }
611   while (gcry_mpi_cmp (r, n) >= 0);
612
613   gcry_mpi_powm (c, g, m, n_square);
614   gcry_mpi_powm (r, r, n, n_square);
615   gcry_mpi_mulm (c, r, c, n_square);
616
617   gcry_mpi_release (n_square);
618   gcry_mpi_release (r);
619   gcry_mpi_release (g);
620 }
621
622
623 /**
624  * Decrypt a ciphertext using Paillier's scheme.
625  *
626  * @param[out] m resulting plaintext
627  * @param c ciphertext to decrypt
628  * @param lambda lambda-component of private key
629  * @param mu mu-component of private key
630  * @param n n-component of public key
631  */
632 static void
633 paillier_decrypt (gcry_mpi_t m, gcry_mpi_t c, gcry_mpi_t mu, gcry_mpi_t lambda, gcry_mpi_t n)
634 {
635   gcry_mpi_t n_square;
636
637   GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
638
639   gcry_mpi_mul (n_square, n, n);
640   // m = c^lambda mod n^2
641   gcry_mpi_powm (m, c, lambda, n_square);
642   // m = m - 1
643   gcry_mpi_sub_ui (m, m, 1);
644   // m <- m/n
645   gcry_mpi_div (m, NULL, m, n, 0);
646   gcry_mpi_mulm (m, m, mu, n);
647   gcry_mpi_release (n_square);
648 }
649
650
651 static void
652 decrypt_session_destroy (struct DecryptSession *ds)
653 {
654   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt session\n");
655
656   GNUNET_CONTAINER_DLL_remove (decrypt_sessions_head, decrypt_sessions_tail, ds);
657
658   if (NULL != ds->client_mq)
659   {
660     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt MQ\n");
661     GNUNET_MQ_destroy (ds->client_mq);
662     ds->client_mq = NULL;
663   }
664
665   if (NULL != ds->client)
666   {
667     GNUNET_SERVER_client_disconnect (ds->client);
668     ds->client = NULL;
669   }
670
671   GNUNET_free (ds);
672 }
673
674
675 static void
676 keygen_session_destroy (struct KeygenSession *ks)
677 {
678   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen session\n");
679
680   GNUNET_CONTAINER_DLL_remove (keygen_sessions_head, keygen_sessions_tail, ks);
681
682   if (NULL != ks->client_mq)
683   {
684     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen MQ\n");
685     GNUNET_MQ_destroy (ks->client_mq);
686     ks->client_mq = NULL;
687   }
688
689   if (NULL != ks->client)
690   {
691     GNUNET_SERVER_client_disconnect (ks->client);
692     ks->client = NULL;
693   }
694
695   GNUNET_free (ks);
696 }
697
698
699 /**
700  * Task run during shutdown.
701  *
702  * @param cls unused
703  * @param tc unused
704  */
705 static void
706 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
707 {
708   while (NULL != decrypt_sessions_head)
709     decrypt_session_destroy (decrypt_sessions_head);
710
711   while (NULL != keygen_sessions_head)
712     keygen_session_destroy (keygen_sessions_head);
713 }
714
715
716 /**
717  * Generate the random coefficients of our pre-secret polynomial
718  *
719  * @param ks the session
720  */
721 static void
722 generate_presecret_polynomial (struct KeygenSession *ks)
723 {
724   int i;
725   gcry_mpi_t v;
726
727   GNUNET_assert (NULL == ks->presecret_polynomial);
728   ks->presecret_polynomial = GNUNET_new_array (ks->threshold, gcry_mpi_t);
729   for (i = 0; i < ks->threshold; i++)
730   {
731     v = ks->presecret_polynomial[i] = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS);
732     GNUNET_assert (NULL != v);
733     // Randomize v such that 0 < v < elgamal_q.
734     // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
735     do 
736     {
737       gcry_mpi_randomize (v, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
738     } while ((gcry_mpi_cmp_ui (v, 0) == 0) || (gcry_mpi_cmp (v, elgamal_q) >= 0));
739   }
740 }
741
742
743 /**
744  * Consensus element handler for round one.
745  * We should get one ephemeral key for each peer.
746  *
747  * @param cls Closure (keygen session).
748  * @param element The element from consensus, or
749  *                NULL if consensus failed.
750  */
751 static void
752 keygen_round1_new_element (void *cls,
753                            const struct GNUNET_SET_Element *element)
754 {
755   const struct GNUNET_SECRETSHARING_KeygenCommitData *d;
756   struct KeygenSession *ks = cls;
757   struct KeygenPeerInfo *info;
758
759   if (NULL == element)
760   {
761     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n");
762     return;
763   }
764
765   /* elements have fixed size */
766   if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
767   {
768     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
769                 "keygen commit data with wrong size (%u) in consensus, "
770                 " %u expected\n",
771                 element->size, sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData));
772     return;
773   }
774
775   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
776
777   d = element->data;
778   info = get_keygen_peer_info (ks, &d->peer);
779
780   if (NULL == info)
781   {
782     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
783                 GNUNET_i2s (&d->peer));
784     return;
785   }
786
787   /* Check that the right amount of data has been signed. */
788   if (d->purpose.size !=
789       htonl (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)))
790   {
791     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong signature purpose size in consensus\n");
792     return;
793   }
794
795   if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1,
796                                                &d->purpose, &d->signature, &d->peer.public_key))
797   {
798     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n");
799     return;
800   }
801   GNUNET_CRYPTO_mpi_scan_unsigned (&info->paillier_n, &d->pubkey.n, PAILLIER_BITS / 8);
802   GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->pubkey.n, PAILLIER_BITS / 8);
803   info->round1_valid = GNUNET_YES;
804 }
805
806
807 /**
808  * Evaluate the polynomial with coefficients @a coeff at @a x.
809  * The i-th element in @a coeff corresponds to the coefficient of x^i.
810  *
811  * @param[out] z result of the evaluation
812  * @param coeff array of coefficients
813  * @param num_coeff number of coefficients
814  * @param x where to evaluate the polynomial
815  * @param m what group are we operating in?
816  */
817 static void
818 horner_eval (gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
819 {
820   unsigned int i;
821
822   gcry_mpi_set_ui (z, 0);
823   for (i = 0; i < num_coeff; i++)
824   {
825     // z <- zx + c
826     gcry_mpi_mul (z, z, x);
827     gcry_mpi_addm (z, z, coeff[num_coeff - i - 1], m);
828   }
829 }
830
831
832 static void
833 keygen_round2_conclude (void *cls)
834 {
835   struct KeygenSession *ks = cls;
836   struct GNUNET_SECRETSHARING_SecretReadyMessage *m;
837   struct GNUNET_MQ_Envelope *ev;
838   size_t share_size;
839   unsigned int i;
840   unsigned int j;
841   struct GNUNET_SECRETSHARING_Share *share;
842   /* our share */
843   gcry_mpi_t s;
844   /* public key */
845   gcry_mpi_t h;
846
847   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
848
849   GNUNET_assert (0 != (s = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
850   GNUNET_assert (0 != (h = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
851
852   // multiplicative identity
853   gcry_mpi_set_ui (h, 1);
854   // additive identity
855   gcry_mpi_set_ui (s, 0);
856
857   share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
858
859   share->num_peers = 0;
860
861   for (i = 0; i < ks->num_peers; i++)
862     if (GNUNET_YES == ks->info[i].round2_valid)
863       share->num_peers++;
864
865   share->peers = GNUNET_new_array (share->num_peers, struct GNUNET_PeerIdentity);
866   share->hom_share_commitments =
867       GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement);
868   share->original_indices = GNUNET_new_array (share->num_peers, uint16_t);
869
870   /* maybe we're not even in the list of peers? */
871   share->my_peer = share->num_peers;
872
873   j = 0;
874   for (i = 0; i < ks->num_peers; i++)
875   {
876     if (GNUNET_YES == ks->info[i].round2_valid)
877     {
878       gcry_mpi_addm (s, s, ks->info[i].decrypted_preshare, elgamal_p);
879       gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p);
880       share->peers[i] = ks->info[i].peer;
881       share->original_indices[i] = j++;
882       if (0 == memcmp (&share->peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
883         share->my_peer = i;
884     }
885   }
886
887   GNUNET_CRYPTO_mpi_print_unsigned (&share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, s);
888   GNUNET_CRYPTO_mpi_print_unsigned (&share->public_key, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, h);
889
890   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers);
891
892   /* Write the share. If 0 peers completed the dkg, an empty
893    * share will be sent. */
894
895   m = GNUNET_malloc (sizeof (struct GNUNET_SECRETSHARING_SecretReadyMessage) +
896                      ks->num_peers * sizeof (struct GNUNET_PeerIdentity));
897
898   GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
899
900   ev = GNUNET_MQ_msg_extra (m, share_size,
901                             GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY);
902
903   GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &m[1], share_size, NULL));
904
905   GNUNET_MQ_send (ks->client_mq, ev);
906 }
907
908
909 /**
910  * Insert round 2 element in the consensus, consisting of
911  * (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}}
912  * (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}}
913  * (3) The encrypted pre-shares Y_{i,j}
914  * (4) The zero knowledge proof for correctness of
915  *    the encryption
916  *
917  * @param ks session to use
918  */
919 static void
920 insert_round2_element (struct KeygenSession *ks)
921 {
922   struct GNUNET_SET_Element *element;
923   struct GNUNET_SECRETSHARING_KeygenRevealData *d;
924   unsigned char *pos;
925   unsigned char *last_pos;
926   size_t element_size;
927   unsigned int i;
928   gcry_mpi_t idx;
929   gcry_mpi_t v;
930   gcry_mpi_t c;
931
932   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting round2 element\n",
933               ks->local_peer_idx);
934
935   GNUNET_assert (NULL != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
936   GNUNET_assert (NULL != (idx = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
937   GNUNET_assert (NULL != (c = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
938
939   element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
940                   GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers +
941                   GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold +
942                   PAILLIER_BITS * 2 / 8 * ks->num_peers);
943
944   element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
945   element->size = element_size;
946   element->data = (void *) &element[1];
947
948   d = (void *) element->data;
949   d->peer = my_peer;
950
951   // start inserting vector elements
952   // after the fixed part of the element's data
953   pos = (void *) &d[1];
954   last_pos = pos + element_size;
955
956   // exponentiated pre-shares
957   for (i = 0; i < ks->num_peers; i++)
958   {
959     ptrdiff_t remaining = last_pos - pos;
960     GNUNET_assert (remaining > 0);
961     gcry_mpi_set_ui (idx, i + 1);
962     // evaluate the polynomial
963     horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q);
964     // take g to the result
965     gcry_mpi_powm (v, elgamal_g, v, elgamal_p);
966     GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
967     pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8;
968   }
969
970   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp preshares\n",
971               ks->local_peer_idx);
972
973   // encrypted pre-shares
974   for (i = 0; i < ks->num_peers; i++)
975   {
976     ptrdiff_t remaining = last_pos - pos;
977     GNUNET_assert (remaining > 0);
978     if (GNUNET_NO == ks->info[i].round1_valid)
979     {
980       gcry_mpi_set_ui (c, 0);
981     }
982     else
983     {
984       gcry_mpi_set_ui (idx, i + 1);
985       // evaluate the polynomial
986       horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q);
987       // encrypt the result
988       paillier_encrypt (c, v, ks->info[i].paillier_n);
989     }
990     GNUNET_CRYPTO_mpi_print_unsigned (pos, PAILLIER_BITS * 2 / 8, c);
991     pos += PAILLIER_BITS * 2 / 8;
992   }
993
994   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed enc preshares\n",
995               ks->local_peer_idx);
996
997   // exponentiated coefficients
998   for (i = 0; i < ks->threshold; i++)
999   {
1000     ptrdiff_t remaining = last_pos - pos;
1001     GNUNET_assert (remaining > 0);
1002     gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
1003     GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
1004     pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8;
1005   }
1006
1007   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp coefficients\n",
1008               ks->local_peer_idx);
1009
1010   d->purpose.size = htonl (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
1011   d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2);
1012   GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature);
1013
1014   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1015   GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
1016
1017   gcry_mpi_release (v);
1018   gcry_mpi_release (idx);
1019 }
1020
1021
1022 static void
1023 keygen_round2_new_element (void *cls,
1024                            const struct GNUNET_SET_Element *element)
1025 {
1026   struct KeygenSession *ks = cls;
1027   const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
1028   struct KeygenPeerInfo *info;
1029   unsigned char *pos;
1030   gcry_mpi_t c;
1031   size_t expected_element_size;
1032
1033   if (NULL == element)
1034   {
1035     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n");
1036     return;
1037   }
1038
1039   expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
1040                   GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers +
1041                   PAILLIER_BITS / 8 * 2 * ks->num_peers +
1042                   GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold);
1043
1044   if (element->size != expected_element_size)
1045   {
1046     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1047                 "keygen round2 data with wrong size (%u) in consensus, "
1048                 " %u expected\n",
1049                 element->size, expected_element_size);
1050     return;
1051   }
1052
1053   d = (const void *) element->data;
1054
1055   info = get_keygen_peer_info (ks, &d->peer);
1056
1057   if (NULL == info)
1058   {
1059     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
1060                 GNUNET_i2s (&d->peer));
1061     return;
1062   }
1063
1064   if (GNUNET_NO == info->round1_valid)
1065   {
1066     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1067                 "ignoring round2 element from peer with invalid round1 element (%s)\n",
1068                 GNUNET_i2s (&d->peer));
1069     return;
1070   }
1071
1072   if (GNUNET_YES == info->round2_valid)
1073   {
1074     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1075                 "ignoring duplicate round2 element (%s)\n",
1076                 GNUNET_i2s (&d->peer));
1077     return;
1078   }
1079
1080   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
1081
1082
1083   pos = (void *) &d[1];
1084   // skip exponentiated pre-shares
1085   pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
1086   // skip encrypted pre-shares
1087   pos += PAILLIER_BITS * 2 / 8 * ks->num_peers;
1088   // the first exponentiated coefficient is the public key share
1089   GNUNET_CRYPTO_mpi_scan_unsigned (&info->public_key_share, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1090
1091   pos = (void *) &d[1];
1092   // skip exp. pre-shares
1093   pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
1094   // skip to the encrypted value for our peer
1095   pos += PAILLIER_BITS * 2 / 8 * ks->local_peer_idx;
1096
1097   GNUNET_CRYPTO_mpi_scan_unsigned (&c, pos, PAILLIER_BITS * 2 / 8);
1098
1099   GNUNET_assert (0 != (info->decrypted_preshare = mpi_new (0)));
1100
1101   paillier_decrypt (info->decrypted_preshare, c, ks->paillier_mu, ks->paillier_lambda,
1102                     ks->info[ks->local_peer_idx].paillier_n);
1103   // TODO: validate zero knowledge proofs
1104
1105   if (ntohl (d->purpose.size) !=
1106       element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose))
1107   {
1108     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n");
1109     return;
1110   }
1111
1112   if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2,
1113                                                &d->purpose, &d->signature, &d->peer.public_key))
1114   {
1115     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n");
1116     return;
1117   }
1118   
1119   info->round2_valid = GNUNET_YES;
1120 }
1121
1122
1123 /**
1124  * Called when the first consensus round has concluded.
1125  * Will initiate the second round.
1126  *
1127  * @param cls closure
1128  */
1129 static void
1130 keygen_round1_conclude (void *cls)
1131 {
1132   struct KeygenSession *ks = cls;
1133
1134   GNUNET_CONSENSUS_destroy (ks->consensus);
1135
1136   ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
1137                                            keygen_round2_new_element, ks);
1138
1139   insert_round2_element (ks);
1140
1141   GNUNET_CONSENSUS_conclude (ks->consensus,
1142                              /* last round, thus conclude at DKG deadline */
1143                              ks->deadline,
1144                              keygen_round2_conclude,
1145                              ks);
1146 }
1147
1148
1149 /**
1150  * Insert the ephemeral key and the presecret commitment
1151  * of this peer in the consensus of the given session.
1152  *
1153  * @param ks session to use
1154  */
1155 static void
1156 insert_round1_element (struct KeygenSession *ks)
1157 {
1158   struct GNUNET_SET_Element *element;
1159   struct GNUNET_SECRETSHARING_KeygenCommitData *d;
1160   // g^a_{i,0}
1161   gcry_mpi_t v;
1162   // big-endian representation of 'v'
1163   unsigned char v_data[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
1164
1165   element = GNUNET_malloc (sizeof *element + sizeof *d);
1166   d = (void *) &element[1];
1167   element->data = d;
1168   element->size = sizeof *d;
1169
1170   d->peer = my_peer;
1171
1172   GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1173
1174   gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
1175
1176   GNUNET_CRYPTO_mpi_print_unsigned (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
1177
1178   GNUNET_CRYPTO_hash (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, &d->commitment);
1179
1180   GNUNET_CRYPTO_mpi_print_unsigned (d->pubkey.n, PAILLIER_BITS / 8,
1181                                     ks->info[ks->local_peer_idx].paillier_n);
1182
1183   d->purpose.size = htonl ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
1184   d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
1185   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature));
1186
1187   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1188
1189   gcry_mpi_release (v);
1190   GNUNET_free (element);
1191 }
1192
1193
1194 /**
1195  * Functions with this signature are called whenever a message is
1196  * received.
1197  *
1198  * @param cls closure
1199  * @param client identification of the client
1200  * @param message the actual message
1201  */
1202 static void handle_client_keygen (void *cls,
1203                                   struct GNUNET_SERVER_Client *client,
1204                                   const struct GNUNET_MessageHeader
1205                                   *message)
1206 {
1207   const struct GNUNET_SECRETSHARING_CreateMessage *msg =
1208       (const struct GNUNET_SECRETSHARING_CreateMessage *) message;
1209   struct KeygenSession *ks;
1210   unsigned int i;
1211
1212   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n");
1213
1214   ks = GNUNET_new (struct KeygenSession);
1215
1216   /* FIXME: check if client already has some session */
1217
1218   GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks);
1219
1220   ks->client = client;
1221   ks->client_mq = GNUNET_MQ_queue_for_server_client (client);
1222
1223   ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
1224   ks->threshold = ntohs (msg->threshold);
1225   ks->num_peers = ntohs (msg->num_peers);
1226
1227   ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers,
1228                                &ks->num_peers, &ks->local_peer_idx);
1229
1230
1231   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "first round of consensus with %u peers\n", ks->num_peers);
1232   ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id,
1233                                            keygen_round1_new_element, ks);
1234
1235   ks->info = GNUNET_new_array (ks->num_peers, struct KeygenPeerInfo);
1236
1237   for (i = 0; i < ks->num_peers; i++)
1238     ks->info[i].peer = ks->peers[i];
1239
1240   GNUNET_assert (0 != (ks->info[ks->local_peer_idx].paillier_n = mpi_new (0)));
1241   GNUNET_assert (0 != (ks->paillier_lambda = mpi_new (0)));
1242   GNUNET_assert (0 != (ks->paillier_mu = mpi_new (0)));
1243
1244   paillier_create (ks->info[ks->local_peer_idx].paillier_n,
1245                    ks->paillier_lambda,
1246                    ks->paillier_mu);
1247
1248   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated paillier key pair\n", ks->local_peer_idx);
1249
1250   generate_presecret_polynomial (ks);
1251
1252   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated presecret polynomial\n", ks->local_peer_idx);
1253
1254   insert_round1_element (ks);
1255
1256   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Concluding for round 1\n", ks->local_peer_idx);
1257
1258   GNUNET_CONSENSUS_conclude (ks->consensus,
1259                              /* half the overall time */
1260                              time_between (ks->start_time, ks->deadline, 1, 2),
1261                              keygen_round1_conclude,
1262                              ks);
1263
1264   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1265
1266   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Waiting for round 1 elements ...\n", ks->local_peer_idx);
1267 }
1268
1269
1270 /**
1271  * Called when the partial decryption consensus concludes.
1272  */
1273 static void
1274 decrypt_conclude (void *cls)
1275 {
1276   struct DecryptSession *ds = cls;
1277   struct GNUNET_SECRETSHARING_DecryptResponseMessage *msg;
1278   struct GNUNET_MQ_Envelope *ev;
1279   gcry_mpi_t lagrange;
1280   gcry_mpi_t m;
1281   gcry_mpi_t tmp;
1282   gcry_mpi_t c_2;
1283   gcry_mpi_t prod;
1284   unsigned int *indices;
1285   unsigned int num;
1286   unsigned int i;
1287   unsigned int j;
1288
1289   GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
1290   GNUNET_assert (0 != (m = gcry_mpi_new (0)));
1291   GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
1292   GNUNET_assert (0 != (prod = gcry_mpi_new (0)));
1293
1294   num = 0;
1295   for (i = 0; i < ds->share->num_peers; i++)
1296     if (NULL != ds->info[i].partial_decryption)
1297       num++;
1298
1299   indices = GNUNET_malloc (num * sizeof (unsigned int));
1300   j = 0;
1301   for (i = 0; i < ds->share->num_peers; i++)
1302     if (NULL != ds->info[i].partial_decryption)
1303       indices[j++] = ds->info[i].original_index;
1304
1305   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: decrypt conclude, with %u peers\n",
1306               ds->share->my_peer, num);
1307
1308   gcry_mpi_set_ui (prod, 1);
1309   for (i = 0; i < num; i++)
1310   {
1311
1312     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: index of %u: %u\n",
1313                 ds->share->my_peer, i, indices[i]);
1314     compute_lagrange_coefficient (lagrange, indices[i], indices, num);
1315     // w_i^{\lambda_i}
1316     gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p);
1317
1318     // product of all exponentiated partiel decryptions ...
1319     gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1320   }
1321
1322   GNUNET_CRYPTO_mpi_scan_unsigned (&c_2, ds->ciphertext.c2_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1323
1324   GNUNET_assert (0 != gcry_mpi_invm (prod, prod, elgamal_p));
1325   gcry_mpi_mulm (m, c_2, prod, elgamal_p);
1326   ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE);
1327   GNUNET_CRYPTO_mpi_print_unsigned (&msg->plaintext, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, m);
1328   msg->success = htonl (1);
1329   GNUNET_MQ_send (ds->client_mq, ev);
1330
1331   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sent decrypt done to client\n");
1332
1333   // FIXME: what if not enough peers participated?
1334 }
1335
1336
1337 /**
1338  * Called when a new partial decryption arrives.
1339  */
1340 static void
1341 decrypt_new_element (void *cls,
1342                      const struct GNUNET_SET_Element *element)
1343 {
1344   struct DecryptSession *session = cls;
1345   const struct GNUNET_SECRETSHARING_DecryptData *d;
1346   struct DecryptPeerInfo *info;
1347
1348   if (NULL == element)
1349   {
1350     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1351     /* FIXME: destroy */
1352     return;
1353   }
1354
1355   if (element->size != sizeof *d)
1356   {
1357     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element of wrong size in decrypt consensus\n");
1358     return;
1359   }
1360
1361   d = element->data;
1362
1363   info = get_decrypt_peer_info (session, &d->peer);
1364   
1365   if (NULL == info)
1366   {
1367     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element from invalid peer (%s)\n",
1368                 GNUNET_i2s (&d->peer));
1369     return;
1370   }
1371
1372   if (NULL != info->partial_decryption)
1373   {
1374     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n",
1375                 GNUNET_i2s (&d->peer));
1376     return;
1377   }
1378
1379   // FIXME: check NIZP first
1380
1381   GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption,
1382                                    GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1383 }
1384
1385 static void
1386 insert_decrypt_element (struct DecryptSession *ds)
1387 {
1388   struct GNUNET_SECRETSHARING_DecryptData d;
1389   struct GNUNET_SET_Element element;
1390   gcry_mpi_t x;
1391   gcry_mpi_t s;
1392
1393   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n",
1394               ds->share->my_peer);
1395
1396   GNUNET_CRYPTO_mpi_scan_unsigned (&x, &ds->ciphertext.c1_bits,
1397                                    GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1398   GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share,
1399                                    GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1400
1401   gcry_mpi_powm (x, x, s, elgamal_p);
1402
1403   element.data = (void *) &d;
1404   element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
1405   element.type = 0;
1406
1407   /* make vagrind happy until we implement the real deal ... */
1408   memset (&d.nizk_commit1, 0, sizeof d.nizk_commit1);
1409   memset (&d.nizk_commit2, 0, sizeof d.nizk_commit2);
1410   memset (&d.nizk_response, 0, sizeof d.nizk_response);
1411
1412   d.ciphertext = ds->ciphertext;
1413   d.peer = my_peer;
1414   d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose));
1415   d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
1416   
1417   GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature);
1418
1419   GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, x);
1420
1421   GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
1422   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element done!\n",
1423               ds->share->my_peer);
1424 }
1425
1426
1427 /**
1428  * Functions with this signature are called whenever a message is
1429  * received.
1430  *
1431  * @param cls closure
1432  * @param client identification of the client
1433  * @param message the actual message
1434  */
1435 static void handle_client_decrypt (void *cls,
1436                                    struct GNUNET_SERVER_Client *client,
1437                                    const struct GNUNET_MessageHeader
1438                                    *message)
1439 {
1440   const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg =
1441       (const void *) message;
1442   struct DecryptSession *ds;
1443   struct GNUNET_HashCode session_id;
1444   unsigned int i;
1445
1446   ds = GNUNET_new (struct DecryptSession);
1447   // FIXME: check if session already exists
1448   GNUNET_CONTAINER_DLL_insert (decrypt_sessions_head, decrypt_sessions_tail, ds);
1449   ds->client = client;
1450   ds->client_mq = GNUNET_MQ_queue_for_server_client (client);
1451   ds->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
1452   ds->ciphertext = msg->ciphertext;
1453
1454   ds->share = GNUNET_SECRETSHARING_share_read (&msg[1], ntohs (msg->header.size) - sizeof *msg, NULL);
1455   // FIXME: probably should be break rather than assert
1456   GNUNET_assert (NULL != ds->share);
1457
1458   // FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ...
1459   GNUNET_CRYPTO_hash (&msg->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext), &session_id);
1460
1461   ds->consensus = GNUNET_CONSENSUS_create (cfg,
1462                                            ds->share->num_peers,
1463                                            ds->share->peers,
1464                                            &session_id,
1465                                            &decrypt_new_element,
1466                                            ds);
1467
1468
1469   ds->info = GNUNET_new_array (ds->share->num_peers, struct DecryptPeerInfo);
1470   for (i = 0; i < ds->share->num_peers; i++)
1471   {
1472     ds->info[i].peer = ds->share->peers[i];
1473     ds->info[i].original_index = ds->share->original_indices[i];
1474   }
1475
1476   insert_decrypt_element (ds);
1477
1478   GNUNET_CONSENSUS_conclude (ds->consensus, ds->deadline, decrypt_conclude, ds);
1479
1480   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1481
1482   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypting with %u peers\n",
1483               ds->share->num_peers);
1484 }
1485
1486
1487 static void
1488 init_crypto_constants (void)
1489 {
1490   GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
1491                                      GNUNET_SECRETSHARING_ELGAMAL_Q_HEX, 0, NULL));
1492   GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
1493                                      GNUNET_SECRETSHARING_ELGAMAL_P_HEX, 0, NULL));
1494   GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
1495                                      GNUNET_SECRETSHARING_ELGAMAL_G_HEX, 0, NULL));
1496 }
1497
1498
1499 static struct KeygenSession *
1500 keygen_session_get (struct GNUNET_SERVER_Client *client)
1501 {
1502   struct KeygenSession *ks;
1503   for (ks = keygen_sessions_head; NULL != ks; ks = ks->next)
1504     if (ks->client == client)
1505       return ks;
1506   return NULL;
1507 }
1508
1509 static struct DecryptSession *
1510 decrypt_session_get (struct GNUNET_SERVER_Client *client)
1511 {
1512   struct DecryptSession *ds;
1513   for (ds = decrypt_sessions_head; NULL != ds; ds = ds->next)
1514     if (ds->client == client)
1515       return ds;
1516   return NULL;
1517 }
1518
1519
1520 /**
1521  * Clean up after a client has disconnected
1522  *
1523  * @param cls closure, unused
1524  * @param client the client to clean up after
1525  */
1526 static void
1527 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1528 {
1529   struct KeygenSession *ks;
1530   struct DecryptSession *ds;
1531
1532   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handling client disconnect\n");
1533
1534   ks = keygen_session_get (client);
1535   if (NULL != ks)
1536     keygen_session_destroy (ks);
1537
1538   ds = decrypt_session_get (client);
1539   if (NULL != ds)
1540     decrypt_session_destroy (ds);
1541 }
1542
1543
1544 /**
1545  * Process template requests.
1546  *
1547  * @param cls closure
1548  * @param server the initialized server
1549  * @param c configuration to use
1550  */
1551 static void
1552 run (void *cls, struct GNUNET_SERVER_Handle *server,
1553      const struct GNUNET_CONFIGURATION_Handle *c)
1554 {
1555   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1556     {handle_client_keygen, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, 0},
1557     {handle_client_decrypt, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, 0},
1558     {NULL, NULL, 0, 0}
1559   };
1560   cfg = c;
1561   srv = server;
1562   my_peer_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1563   if (NULL == my_peer_private_key)
1564   {
1565     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not access host private key\n");
1566     GNUNET_break (0);
1567     GNUNET_SCHEDULER_shutdown ();
1568     return;
1569   }
1570   init_crypto_constants ();
1571   if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer))
1572   {
1573     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
1574     GNUNET_break (0);
1575     GNUNET_SCHEDULER_shutdown ();
1576     return;
1577   }
1578   GNUNET_SERVER_add_handlers (server, handlers);
1579   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1580   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1581                                 NULL);
1582 }
1583
1584
1585 /**
1586  * The main function for the template service.
1587  *
1588  * @param argc number of arguments from the command line
1589  * @param argv command line arguments
1590  * @return 0 ok, 1 on error
1591  */
1592 int
1593 main (int argc, char *const *argv)
1594 {
1595   return (GNUNET_OK ==
1596           GNUNET_SERVICE_run (argc, argv, "secretsharing",
1597                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
1598 }
1599