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