-removing code that just dereferenced uninitialized 'm' and then decided to randomly...
[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_consensus_service.h"
30 #include "secretsharing.h"
31 #include "secretsharing_protocol.h"
32 #include <gcrypt.h>
33
34
35 /**
36  * Info about a peer in a key generation session.
37  */
38 struct KeygenPeerInfo
39 {
40   /**
41    * Peer identity of the peer.
42    */
43   struct GNUNET_PeerIdentity peer;
44
45   /**
46    * g-component of the peer's paillier public key.
47    */
48   gcry_mpi_t paillier_g;
49
50   /**
51    * mu-component of the peer's paillier public key.
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 could decrypt
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    * GNUNET_YES if the peer has been disqualified,
73    * GNUNET_NO otherwise.
74    */
75   int disqualified;
76 };
77
78
79 /**
80  * Session to establish a threshold-shared secret.
81  */
82 struct KeygenSession
83 {
84   /**
85    * Keygen sessions are held in a linked list.
86    */
87   struct KeygenSession *next;
88
89   /**
90    * Keygen sessions are held in a linked list.
91    */
92   struct KeygenSession *prev;
93
94   /**
95    * Current consensus, used for both DKG rounds.
96    */
97   struct GNUNET_CONSENSUS_Handle *consensus;
98
99   /**
100    * Client that is interested in the result
101    * of this key generation session.
102    */
103   struct GNUNET_SERVER_Client *client;
104
105   /**
106    * Message queue for 'client'
107    */
108   struct GNUNET_MQ_Handle *client_mq;
109
110   /**
111    * Randomly generated coefficients of the polynomial for sharing our
112    * pre-secret, where 'preshares[0]' is our pre-secret.  Contains 'threshold'
113    * elements, thus represents a polynomial of degree 'threshold-1', which can
114    * be interpolated with 'threshold' data points.
115    *
116    * The pre-secret-shares 'i=1,...,num_peers' are given by evaluating this
117    * polyomial at 'i' for share i.
118    */
119   gcry_mpi_t *presecret_polynomial;
120
121   /**
122    * Minimum number of shares required to restore the secret.
123    */
124   unsigned int threshold;
125
126   /**
127    * Total number of peers.
128    */
129   unsigned int num_peers;
130
131   /**
132    * Index of the local peer.
133    */
134   unsigned int local_peer;
135
136   /**
137    * Information about all participating peers.
138    */
139   struct KeygenPeerInfo *info;
140
141   /**
142    * List of all peers involved in the secret sharing session.
143    */
144   struct GNUNET_PeerIdentity *peers;
145
146   /**
147    * Identifier for this session.
148    */
149   struct GNUNET_HashCode session_id;
150
151   /**
152    * g-component of our peer's paillier private key.
153    */
154   gcry_mpi_t paillier_lambda;
155
156   /**
157    * g-component of our peer's paillier private key.
158    */
159   gcry_mpi_t paillier_mu;
160
161   struct GNUNET_TIME_Absolute deadline;
162
163   /**
164    * Index of the local peer in the ordered list
165    * of peers in the session.
166    */
167   unsigned int local_peer_idx;
168 };
169
170
171 struct DecryptSession
172 {
173   struct DecryptSession *next;
174   struct DecryptSession *prev;
175
176   struct GNUNET_CONSENSUS_Handle *consensus;
177
178   struct GNUNET_SERVER_Client *client;
179 };
180
181 /**
182  * Decrypt sessions are held in a linked list.
183  */
184 //static struct DecryptSession *decrypt_sessions_head;
185
186 /**
187  * Decrypt sessions are held in a linked list.
188  */
189 //static struct DecryptSession *decrypt_sessions_tail;
190
191 /**
192  * Decrypt sessions are held in a linked list.
193  */
194 static struct KeygenSession *keygen_sessions_head;
195
196 /**
197  * Decrypt sessions are held in a linked list.
198  */
199 static struct KeygenSession *keygen_sessions_tail;
200
201 /**
202  * The ElGamal prime field order as libgcrypt mpi.
203  * Will be initialized to 'ELGAMAL_Q_DATA'.
204  */
205 static gcry_mpi_t elgamal_q;
206
207 /**
208  * Modulus of the prime field used for ElGamal.
209  * Will be initialized to 'ELGAMAL_P_DATA'.
210  */
211 static gcry_mpi_t elgamal_p;
212
213 /**
214  * Generator for prime field of order 'elgamal_q'.
215  * Will be initialized to 'ELGAMAL_G_DATA'.
216  */
217 static gcry_mpi_t elgamal_g;
218
219 /**
220  * Peer that runs this service.
221  */
222 static struct GNUNET_PeerIdentity my_peer;
223
224 /**
225  * Configuration of this service.
226  */
227 static const struct GNUNET_CONFIGURATION_Handle *cfg;
228
229 /**
230  * Server for this service.
231  */
232 static struct GNUNET_SERVER_Handle *srv;
233
234
235 /**
236  * Although GNUNET_CRYPTO_hash_cmp exisits, it does not have
237  * the correct signature to be used with e.g. qsort.
238  * We use this function instead.
239  *
240  * @param h1 some hash code
241  * @param h2 some hash code
242  * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2.
243  */
244 static int
245 hash_cmp (const void *h1, const void *h2)
246 {
247   return GNUNET_CRYPTO_hash_cmp ((struct GNUNET_HashCode *) h1, (struct GNUNET_HashCode *) h2);
248 }
249
250
251 /**
252  * Normalize the given list of peers, by including the local peer
253  * (if it is missing) and sorting the peers by their identity.
254  *
255  * @param listed peers in the unnormalized list
256  * @param num_listed peers in the un-normalized list
257  * @param[out] num_normalized number of peers in the normalized list
258  * @param[out] my_peer_idx index of the local peer in the normalized list
259  * @return normalized list, must be free'd by the caller
260  */
261 static struct GNUNET_PeerIdentity *
262 normalize_peers (struct GNUNET_PeerIdentity *listed,
263                  unsigned int num_listed,
264                  unsigned int *num_normalized,
265                  unsigned int *my_peer_idx)
266 {
267   unsigned int local_peer_in_list;
268   unsigned int n;
269   unsigned int i;
270   struct GNUNET_PeerIdentity *normalized;
271
272   local_peer_in_list = GNUNET_NO;
273   for (i = 0; i < num_listed; i++)
274   {
275     if (0 == memcmp (&listed[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
276     {
277       local_peer_in_list = GNUNET_YES;
278       break;
279     }
280   }
281
282   n = num_listed;
283   if (GNUNET_NO == local_peer_in_list)
284     n++;
285
286   normalized = GNUNET_malloc (n * sizeof (struct GNUNET_PeerIdentity));
287
288   if (GNUNET_NO == local_peer_in_list)
289     normalized[n - 1] = my_peer;
290
291   memcpy (normalized, listed, num_listed * sizeof (struct GNUNET_PeerIdentity));
292   qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &hash_cmp);
293
294   if (NULL != my_peer_idx)
295   {
296     for (i = 0; i < num_listed; i++)
297     {
298       if (0 == memcmp (&normalized[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
299       {
300         *my_peer_idx = i;
301         break;
302       }
303     }
304   }
305
306   *num_normalized = n;
307   return normalized;
308 }
309
310
311 /**
312  * Create a key pair for the paillier crypto system.
313  *
314  * Uses the simplified key generation of Jonathan Katz, Yehuda Lindell,
315  * "Introduction to Modern Cryptography: Principles and Protocols".
316  *
317  * @param g g-component of public key
318  * @param n n-component of public key
319  * @param lambda lambda-component of private key
320  * @param mu mu-componenent of private key
321  */
322 static void
323 paillier_create (gcry_mpi_t g, gcry_mpi_t n, gcry_mpi_t lambda, gcry_mpi_t mu)
324 {
325   gcry_mpi_t p;
326   gcry_mpi_t q;
327   gcry_mpi_t phi;
328   gcry_mpi_t tmp;
329
330   GNUNET_assert (0 != (phi = gcry_mpi_new (PAILLIER_BITS)));
331   GNUNET_assert (0 != (tmp = gcry_mpi_new (PAILLIER_BITS)));
332
333   // generate rsa modulus
334   GNUNET_assert (0 == gcry_prime_generate (&p, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
335                                            GCRY_WEAK_RANDOM, 0));
336   GNUNET_assert (0 == gcry_prime_generate (&q, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
337                                            GCRY_WEAK_RANDOM, 0));
338   gcry_mpi_mul (n, p, q);
339   gcry_mpi_add_ui (g, n, 1);
340   // compute phi(n) = (p-1)(q-1)
341   gcry_mpi_sub_ui (phi, p, 1);
342   gcry_mpi_sub_ui (tmp, q, 1);
343   gcry_mpi_mul (phi, phi, tmp);
344   gcry_mpi_set (lambda, phi);
345   // compute mu
346   GNUNET_assert (0 != gcry_mpi_invm (mu, phi, n));
347
348   gcry_mpi_release (p);
349   gcry_mpi_release (q);
350   gcry_mpi_release (phi);
351   gcry_mpi_release (tmp);
352 }
353
354
355 /**
356  * Encrypt a value using Paillier's scheme.
357  *
358  * @param c resulting ciphertext
359  * @param m plaintext to encrypt
360  * @param g g-component of public key
361  * @param n n-component of public key
362  */
363 static void
364 paillier_encrypt (gcry_mpi_t c, gcry_mpi_t m, gcry_mpi_t g, gcry_mpi_t n)
365 {
366   gcry_mpi_t n_square;
367   gcry_mpi_t r;
368
369   GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
370   GNUNET_assert (0 != (r = gcry_mpi_new (0)));
371
372   gcry_mpi_mul (n_square, n, n);
373
374   // generate r < n
375   do
376   {
377     gcry_mpi_randomize (r, PAILLIER_BITS, GCRY_WEAK_RANDOM);
378   }
379   while (gcry_mpi_cmp (r, n) > 0);
380
381   gcry_mpi_powm (c, g, m, n_square);
382   gcry_mpi_powm (r, r, n, n_square);
383   gcry_mpi_mulm (c, r, c, n_square);
384
385   gcry_mpi_release (n_square);
386   gcry_mpi_release (r);
387 }
388
389
390 /**
391  * Decrypt a ciphertext using Paillier's scheme.
392  *
393  * @param[out] m resulting plaintext
394  * @param c ciphertext to decrypt
395  * @param lambda lambda-component of private key
396  * @param mu mu-component of private key
397  * @param n n-component of public key
398  */
399 static void
400 paillier_decrypt (gcry_mpi_t m, gcry_mpi_t c, gcry_mpi_t mu, gcry_mpi_t lambda, gcry_mpi_t n)
401 {
402   gcry_mpi_t n_square;
403   GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
404   gcry_mpi_mul (n_square, n, n);
405   gcry_mpi_powm (m, c, lambda, n_square);
406   gcry_mpi_sub_ui (m, m, 1);
407   // m = m/n
408   gcry_mpi_div (m, NULL, m, n, 0);
409   gcry_mpi_mulm (m, m, mu, n);
410   gcry_mpi_release (n_square);
411 }
412
413
414 /**
415  * Task run during shutdown.
416  *
417  * @param cls unused
418  * @param tc unused
419  */
420 static void
421 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
422 {
423   /* FIXME: do clean up here */
424 }
425
426
427 static void
428 generate_presecret_polynomial (struct KeygenSession *ks)
429 {
430   int i;
431   GNUNET_assert (NULL == ks->presecret_polynomial);
432   ks->presecret_polynomial = GNUNET_malloc (ks->threshold * sizeof (gcry_mpi_t));
433   for (i = 0; i < ks->threshold; i++)
434   {
435     ks->presecret_polynomial[i] = gcry_mpi_new (PAILLIER_BITS);
436     gcry_mpi_randomize (ks->presecret_polynomial[i], PAILLIER_BITS,
437                         GCRY_WEAK_RANDOM);
438   }
439 }
440
441
442 static void
443 keygen_round1_new_element (void *cls,
444                            const struct GNUNET_SET_Element *element)
445 {
446   const struct GNUNET_SECRETSHARING_KeygenCommitData *d;
447   struct KeygenSession *ks = cls;
448   unsigned int i;
449
450   if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
451   {
452     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong size in consensus\n");
453     return;
454   }
455
456   d = element->data;
457
458   for (i = 0; i < ks->num_peers; i++)
459   {
460     if (0 == memcmp (&d->peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
461     {
462       // TODO: check signature
463       GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].paillier_g, GCRYMPI_FMT_USG,
464                                          &d->pubkey.g, sizeof d->pubkey.g, NULL));
465       GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].paillier_n, GCRYMPI_FMT_USG,
466                                          &d->pubkey.n, sizeof d->pubkey.n, NULL));
467       GNUNET_assert (0 == gcry_mpi_scan (&ks->info[i].presecret_commitment, GCRYMPI_FMT_USG,
468                                          &d->commitment, sizeof d->commitment, NULL));
469       return;
470     }
471   }
472
473   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity in consensus\n");
474 }
475
476
477 /**
478  * Evaluate the polynomial with coefficients @a coeff at @a x.
479  * The i-th element in @a coeff corresponds to the coefficient of x^i.
480  *
481  * @param[out] z result of the evaluation
482  * @param coeff array of coefficients
483  * @param num_coeff number of coefficients
484  * @param x where to evaluate the polynomial
485  * @param m what group are we operating in?
486  */
487 static void
488 horner_eval (gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
489 {
490   unsigned int i;
491
492   gcry_mpi_set_ui (z, 0);
493   for (i = 0; i < num_coeff; i++)
494   {
495     // z <- zx + c
496     gcry_mpi_mul (z, z, x);
497     gcry_mpi_addm (z, z, coeff[num_coeff - i - 1], m);
498   }
499 }
500
501
502 static void
503 keygen_round2_conclude (void *cls)
504 {
505   struct KeygenSession *ks = cls;
506   struct GNUNET_SECRETSHARING_SecretReadyMessage *m;
507   struct GNUNET_MQ_Envelope *ev;
508   unsigned int i;
509   gcry_mpi_t s;
510   gcry_mpi_t h;
511
512   GNUNET_assert (0 != (s = gcry_mpi_new (PAILLIER_BITS)));
513   GNUNET_assert (0 != (h = gcry_mpi_new (PAILLIER_BITS)));
514
515   // multiplicative identity
516   gcry_mpi_set_ui (s, 1);
517
518   for (i = 0; i < ks->num_peers; i++)
519   {
520     if (GNUNET_NO == ks->info[i].disqualified)
521     {
522       gcry_mpi_addm (s, s, ks->info[i].decrypted_preshare, elgamal_p);
523       gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p);
524       m->num_secret_peers++;
525     }
526   }
527
528   ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY);
529
530   gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &m->secret, PAILLIER_BITS / 8, NULL, s);
531   gcry_mpi_print (GCRYMPI_FMT_USG, (void *) &m->public_key, PAILLIER_BITS / 8, NULL, s);
532
533   GNUNET_MQ_send (ks->client_mq, ev);
534 }
535
536
537 /**
538  * Insert round 2 element in the consensus, consisting of
539  * (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}}
540  * (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}}
541  * (3) The encrypted pre-shares Y_{i,j}
542  * (4) The zero knowledge proof for correctness of
543  *    the encryption
544  *
545  * @param ks session to use
546  */
547 static void
548 insert_round2_element (struct KeygenSession *ks)
549 {
550   struct GNUNET_SET_Element *element;
551   struct GNUNET_SECRETSHARING_KeygenRevealData *msg;
552   unsigned char *pos;
553   unsigned char *last_pos;
554   size_t element_size;
555   unsigned int i;
556   gcry_mpi_t c;
557   gcry_mpi_t idx;
558   gcry_mpi_t v;
559
560   GNUNET_assert (0 != (c = gcry_mpi_new (PAILLIER_BITS)));
561   GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
562   GNUNET_assert (0 != (idx = gcry_mpi_new (PAILLIER_BITS)));
563
564   element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
565                   2 * PAILLIER_BITS / 8 * ks->num_peers +
566                   1 * PAILLIER_BITS / 8 * ks->threshold);
567
568   element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
569
570   msg = (void *) element->data;
571   pos = (void *) &msg[1];
572   last_pos = pos + element_size;
573
574   // exponentiated pre-shares
575   for (i = 0; i <= ks->threshold; i++)
576   {
577     ptrdiff_t remaining = last_pos - pos;
578     GNUNET_assert (remaining > 0);
579     gcry_mpi_set_ui (idx, i);
580     // evaluate the polynomial
581     horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_p);
582     // take g to the result
583     gcry_mpi_powm (v, elgamal_g, v, elgamal_p);
584     gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
585     pos += PAILLIER_BITS / 8;
586   }
587
588   // exponentiated coefficients
589   for (i = 0; i < ks->num_peers; i++)
590   {
591     ptrdiff_t remaining = last_pos - pos;
592     GNUNET_assert (remaining > 0);
593     gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
594     gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
595     pos += PAILLIER_BITS / 8;
596   }
597
598   // encrypted pre-shares
599   for (i = 0; i < ks->threshold; i++)
600   {
601     ptrdiff_t remaining = last_pos - pos;
602     GNUNET_assert (remaining > 0);
603     if (GNUNET_YES == ks->info[i].disqualified)
604       gcry_mpi_set_ui (v, 0);
605     else
606       paillier_encrypt (v, ks->presecret_polynomial[0],
607                         ks->info[i].paillier_g, ks->info[i].paillier_g);
608     gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
609     pos += PAILLIER_BITS / 8;
610   }
611
612   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
613   GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
614 }
615
616
617 static struct KeygenPeerInfo *
618 get_keygen_peer_info (const struct KeygenSession *ks,
619                struct GNUNET_PeerIdentity *peer)
620 {
621   unsigned int i;
622   for (i = 0; i < ks->num_peers; i++)
623     if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
624       return &ks->info[i];
625   return NULL;
626 }
627
628
629 static void
630 keygen_round2_new_element (void *cls,
631                            const struct GNUNET_SET_Element *element)
632 {
633   struct KeygenSession *ks = cls;
634   struct GNUNET_SECRETSHARING_KeygenRevealData *msg;
635   struct KeygenPeerInfo *info;
636   unsigned char *pos;
637   unsigned char *last_pos;
638   gcry_mpi_t c;
639
640   msg = (void *) element->data;
641   pos = (void *) &msg[1];
642   // skip exp. pre-shares
643   pos += PAILLIER_BITS / 8 * ks->num_peers;
644   // skip exp. coefficients
645   pos += PAILLIER_BITS / 8 * ks->threshold;
646   // skip to the value for our peer
647   pos += PAILLIER_BITS / 8 * ks->local_peer_idx;
648
649   last_pos = element->size + (unsigned char *) element->data;
650
651   if ((pos >= last_pos) || ((last_pos - pos) < (PAILLIER_BITS / 8)))
652   {
653     GNUNET_break_op (0);
654     return;
655   }
656
657   GNUNET_assert (0 == gcry_mpi_scan (&c, GCRYMPI_FMT_USG,
658                                      pos, PAILLIER_BITS / 8, NULL));
659
660   info = get_keygen_peer_info (ks, &msg->peer);
661
662   if (NULL == info)
663   {
664     GNUNET_break_op (0);
665     return;
666   }
667
668   paillier_decrypt (info->decrypted_preshare, c, ks->paillier_lambda, ks->paillier_mu,
669                     ks->info[ks->local_peer_idx].paillier_n);
670
671   // TODO: validate signature and proofs
672
673 }
674
675
676 static void
677 keygen_round1_conclude (void *cls)
678 {
679   struct KeygenSession *ks = cls;
680
681   // TODO: destroy old consensus
682   // TODO: mark peers without keys as disqualified
683
684   ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
685                                            keygen_round2_new_element, ks);
686
687   insert_round2_element (ks);
688
689   GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round2_conclude, ks);
690 }
691
692
693 /**
694  * Insert the ephemeral key and the presecret commitment
695  * of this peer in the consensus of the given session.
696  *
697  * @param ks session to use
698  */
699 static void
700 insert_round1_element (struct KeygenSession *ks)
701 {
702   struct GNUNET_SET_Element *element;
703   struct GNUNET_SECRETSHARING_KeygenCommitData *d;
704   // g^a_{i,0}
705   gcry_mpi_t v;
706   // big-endian representation of 'v'
707   unsigned char v_data[PAILLIER_BITS / 8];
708
709   element = GNUNET_malloc (sizeof *element + sizeof *d);
710   d = (void *) &element[1];
711   element->data = d;
712   element->size = sizeof *d;
713
714   GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
715
716   gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
717
718   GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
719                                       v_data, PAILLIER_BITS / 8, NULL,
720                                       v));
721
722   GNUNET_CRYPTO_hash (v_data, PAILLIER_BITS / 8, &d->commitment);
723
724   GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
725                                       (unsigned char *) d->pubkey.g, PAILLIER_BITS / 8, NULL,
726                                       ks->info[ks->local_peer_idx].paillier_g));
727
728   GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
729                                       (unsigned char *) d->pubkey.n, PAILLIER_BITS / 8, NULL,
730                                       ks->info[ks->local_peer_idx].paillier_n));
731
732   // FIXME: sign stuff
733
734   d->peer = my_peer;
735
736   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
737 }
738
739
740 /**
741  * Functions with this signature are called whenever a message is
742  * received.
743  *
744  * @param cls closure
745  * @param client identification of the client
746  * @param message the actual message
747  */
748 static void handle_client_keygen (void *cls,
749                                   struct GNUNET_SERVER_Client *client,
750                                   const struct GNUNET_MessageHeader
751                                   *message)
752 {
753   const struct GNUNET_SECRETSHARING_CreateMessage *msg =
754       (const struct GNUNET_SECRETSHARING_CreateMessage *) message;
755   struct KeygenSession *ks;
756
757   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n");
758
759   ks = GNUNET_new (struct KeygenSession);
760
761   GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks);
762
763   ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
764   ks->threshold = ntohs (msg->threshold);
765   ks->num_peers = ntohs (msg->num_peers);
766
767   ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers,
768                                &ks->num_peers, &ks->local_peer_idx);
769
770   // TODO: initialize MPIs in peer structure
771
772   ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id,
773                                            keygen_round1_new_element, ks);
774
775   paillier_create (ks->info[ks->local_peer_idx].paillier_g,
776                    ks->info[ks->local_peer_idx].paillier_n,
777                    ks->paillier_lambda,
778                    ks->paillier_mu);
779
780
781   generate_presecret_polynomial (ks);
782
783   insert_round1_element (ks);
784
785   GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round1_conclude, ks);
786 }
787
788
789 /**
790  * Functions with this signature are called whenever a message is
791  * received.
792  *
793  * @param cls closure
794  * @param client identification of the client
795  * @param message the actual message
796  */
797 static void handle_client_decrypt (void *cls,
798                                   struct GNUNET_SERVER_Client *client,
799                                   const struct GNUNET_MessageHeader
800                                   *message)
801 {
802   GNUNET_assert (0);
803 }
804
805
806 /**
807  * Process template requests.
808  *
809  * @param cls closure
810  * @param server the initialized server
811  * @param c configuration to use
812  */
813 static void
814 run (void *cls, struct GNUNET_SERVER_Handle *server,
815      const struct GNUNET_CONFIGURATION_Handle *c)
816 {
817   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
818     {handle_client_keygen, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, 0},
819     {handle_client_decrypt, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, 0},
820     {NULL, NULL, 0, 0}
821   };
822   cfg = c;
823   srv = server;
824   if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer))
825   {
826     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
827     GNUNET_break (0);
828     GNUNET_SCHEDULER_shutdown ();
829     return;
830   }
831   GNUNET_SERVER_add_handlers (server, handlers);
832   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
833                                 NULL);
834 }
835
836
837 /**
838  * The main function for the template service.
839  *
840  * @param argc number of arguments from the command line
841  * @param argv command line arguments
842  * @return 0 ok, 1 on error
843  */
844 int
845 main (int argc, char *const *argv)
846 {
847   return (GNUNET_OK ==
848           GNUNET_SERVICE_run (argc, argv, "secretsharing",
849                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
850 }
851