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