specify proper access control rules for conversation service
[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++; // FIXME: m not initialized here!
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   // FIXME: c is never used...
562   GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
563   GNUNET_assert (0 != (idx = gcry_mpi_new (PAILLIER_BITS)));
564
565   element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
566                   2 * PAILLIER_BITS / 8 * ks->num_peers +
567                   1 * PAILLIER_BITS / 8 * ks->threshold);
568
569   element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
570
571   msg = (void *) element->data;
572   pos = (void *) &msg[1];
573   last_pos = pos + element_size;
574
575   // exponentiated pre-shares
576   for (i = 0; i <= ks->threshold; i++)
577   {
578     ptrdiff_t remaining = last_pos - pos;
579     GNUNET_assert (remaining > 0);
580     gcry_mpi_set_ui (idx, i);
581     // evaluate the polynomial
582     horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_p);
583     // take g to the result
584     gcry_mpi_powm (v, elgamal_g, v, elgamal_p);
585     gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
586     pos += PAILLIER_BITS / 8;
587   }
588
589   // exponentiated coefficients
590   for (i = 0; i < ks->num_peers; i++)
591   {
592     ptrdiff_t remaining = last_pos - pos;
593     GNUNET_assert (remaining > 0);
594     gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
595     gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
596     pos += PAILLIER_BITS / 8;
597   }
598
599   // encrypted pre-shares
600   for (i = 0; i < ks->threshold; i++)
601   {
602     ptrdiff_t remaining = last_pos - pos;
603     GNUNET_assert (remaining > 0);
604     if (GNUNET_YES == ks->info[i].disqualified)
605       gcry_mpi_set_ui (v, 0);
606     else
607       paillier_encrypt (v, ks->presecret_polynomial[0],
608                         ks->info[i].paillier_g, ks->info[i].paillier_g);
609     gcry_mpi_print (GCRYMPI_FMT_USG, pos, (size_t) remaining, NULL, v);
610     pos += PAILLIER_BITS / 8;
611   }
612
613   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
614   GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
615
616   gcry_mpi_release (c);
617   gcry_mpi_release (v);
618   gcry_mpi_release (idx);
619 }
620
621
622 static struct KeygenPeerInfo *
623 get_keygen_peer_info (const struct KeygenSession *ks,
624                struct GNUNET_PeerIdentity *peer)
625 {
626   unsigned int i;
627   for (i = 0; i < ks->num_peers; i++)
628     if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
629       return &ks->info[i];
630   return NULL;
631 }
632
633
634 static void
635 keygen_round2_new_element (void *cls,
636                            const struct GNUNET_SET_Element *element)
637 {
638   struct KeygenSession *ks = cls;
639   struct GNUNET_SECRETSHARING_KeygenRevealData *msg;
640   struct KeygenPeerInfo *info;
641   unsigned char *pos;
642   unsigned char *last_pos;
643   gcry_mpi_t c;
644
645   msg = (void *) element->data;
646   pos = (void *) &msg[1];
647   // skip exp. pre-shares
648   pos += PAILLIER_BITS / 8 * ks->num_peers;
649   // skip exp. coefficients
650   pos += PAILLIER_BITS / 8 * ks->threshold;
651   // skip to the value for our peer
652   pos += PAILLIER_BITS / 8 * ks->local_peer_idx;
653
654   last_pos = element->size + (unsigned char *) element->data;
655
656   if ((pos >= last_pos) || ((last_pos - pos) < (PAILLIER_BITS / 8)))
657   {
658     GNUNET_break_op (0);
659     return;
660   }
661
662   GNUNET_assert (0 == gcry_mpi_scan (&c, GCRYMPI_FMT_USG,
663                                      pos, PAILLIER_BITS / 8, NULL));
664
665   info = get_keygen_peer_info (ks, &msg->peer);
666
667   if (NULL == info)
668   {
669     GNUNET_break_op (0);
670     return;
671   }
672
673   paillier_decrypt (info->decrypted_preshare, c, ks->paillier_lambda, ks->paillier_mu,
674                     ks->info[ks->local_peer_idx].paillier_n);
675
676   // TODO: validate signature and proofs
677
678 }
679
680
681 static void
682 keygen_round1_conclude (void *cls)
683 {
684   struct KeygenSession *ks = cls;
685
686   // TODO: destroy old consensus
687   // TODO: mark peers without keys as disqualified
688
689   ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
690                                            keygen_round2_new_element, ks);
691
692   insert_round2_element (ks);
693
694   GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round2_conclude, ks);
695 }
696
697
698 /**
699  * Insert the ephemeral key and the presecret commitment
700  * of this peer in the consensus of the given session.
701  *
702  * @param ks session to use
703  */
704 static void
705 insert_round1_element (struct KeygenSession *ks)
706 {
707   struct GNUNET_SET_Element *element;
708   struct GNUNET_SECRETSHARING_KeygenCommitData *d;
709   // g^a_{i,0}
710   gcry_mpi_t v;
711   // big-endian representation of 'v'
712   unsigned char v_data[PAILLIER_BITS / 8];
713
714   element = GNUNET_malloc (sizeof *element + sizeof *d);
715   d = (void *) &element[1];
716   element->data = d;
717   element->size = sizeof *d;
718
719   GNUNET_assert (0 != (v = gcry_mpi_new (PAILLIER_BITS)));
720
721   gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
722
723   GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
724                                       v_data, PAILLIER_BITS / 8, NULL,
725                                       v));
726
727   GNUNET_CRYPTO_hash (v_data, PAILLIER_BITS / 8, &d->commitment);
728
729   GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
730                                       (unsigned char *) d->pubkey.g, PAILLIER_BITS / 8, NULL,
731                                       ks->info[ks->local_peer_idx].paillier_g));
732
733   GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
734                                       (unsigned char *) d->pubkey.n, PAILLIER_BITS / 8, NULL,
735                                       ks->info[ks->local_peer_idx].paillier_n));
736
737   // FIXME: sign stuff
738
739   d->peer = my_peer;
740
741   GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
742 }
743
744
745 /**
746  * Functions with this signature are called whenever a message is
747  * received.
748  *
749  * @param cls closure
750  * @param client identification of the client
751  * @param message the actual message
752  */
753 static void handle_client_keygen (void *cls,
754                                   struct GNUNET_SERVER_Client *client,
755                                   const struct GNUNET_MessageHeader
756                                   *message)
757 {
758   const struct GNUNET_SECRETSHARING_CreateMessage *msg =
759       (const struct GNUNET_SECRETSHARING_CreateMessage *) message;
760   struct KeygenSession *ks;
761
762   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n");
763
764   ks = GNUNET_new (struct KeygenSession);
765
766   GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks);
767
768   ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
769   ks->threshold = ntohs (msg->threshold);
770   ks->num_peers = ntohs (msg->num_peers);
771
772   ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers,
773                                &ks->num_peers, &ks->local_peer_idx);
774
775   // TODO: initialize MPIs in peer structure
776
777   ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id,
778                                            keygen_round1_new_element, ks);
779
780   paillier_create (ks->info[ks->local_peer_idx].paillier_g,
781                    ks->info[ks->local_peer_idx].paillier_n,
782                    ks->paillier_lambda,
783                    ks->paillier_mu);
784
785
786   generate_presecret_polynomial (ks);
787
788   insert_round1_element (ks);
789
790   GNUNET_CONSENSUS_conclude (ks->consensus, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME */, keygen_round1_conclude, ks);
791 }
792
793
794 /**
795  * Functions with this signature are called whenever a message is
796  * received.
797  *
798  * @param cls closure
799  * @param client identification of the client
800  * @param message the actual message
801  */
802 static void handle_client_decrypt (void *cls,
803                                   struct GNUNET_SERVER_Client *client,
804                                   const struct GNUNET_MessageHeader
805                                   *message)
806 {
807   GNUNET_assert (0);
808 }
809
810
811 /**
812  * Process template requests.
813  *
814  * @param cls closure
815  * @param server the initialized server
816  * @param c configuration to use
817  */
818 static void
819 run (void *cls, struct GNUNET_SERVER_Handle *server,
820      const struct GNUNET_CONFIGURATION_Handle *c)
821 {
822   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
823     {handle_client_keygen, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, 0},
824     {handle_client_decrypt, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, 0},
825     {NULL, NULL, 0, 0}
826   };
827   cfg = c;
828   srv = server;
829   if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer))
830   {
831     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
832     GNUNET_break (0);
833     GNUNET_SCHEDULER_shutdown ();
834     return;
835   }
836   GNUNET_SERVER_add_handlers (server, handlers);
837   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
838                                 NULL);
839 }
840
841
842 /**
843  * The main function for the template service.
844  *
845  * @param argc number of arguments from the command line
846  * @param argv command line arguments
847  * @return 0 ok, 1 on error
848  */
849 int
850 main (int argc, char *const *argv)
851 {
852   return (GNUNET_OK ==
853           GNUNET_SERVICE_run (argc, argv, "secretsharing",
854                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
855 }
856