GNUnet  0.10.x
gnunet-service-secretsharing.c
Go to the documentation of this file.
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 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_time_lib.h"
29 #include "gnunet_signatures.h"
31 #include "secretsharing.h"
32 #include "secretsharing_protocol.h"
33 #include <gcrypt.h>
34 
35 
36 #define EXTRA_CHECKS 1
37 
38 
43 {
48 
54 
59 
64  gcry_mpi_t preshare_commitment;
65 
69  gcry_mpi_t sigma;
70 
76 
82 };
83 
84 
89 {
94 
99  unsigned int original_index;
100 
107  gcry_mpi_t partial_decryption;
108 };
109 
110 
114 struct ClientState;
115 
116 
121 {
122 
127 
131  struct ClientState *cs;
132 
142  gcry_mpi_t *presecret_polynomial;
143 
149  unsigned int threshold;
150 
154  unsigned int num_peers;
155 
159  unsigned int local_peer;
160 
166 
171 
176 
180  struct GNUNET_CRYPTO_PaillierPrivateKey paillier_private_key;
181 
186 
192 
197  unsigned int local_peer_idx;
198 
203  gcry_mpi_t my_share;
204 
208  gcry_mpi_t public_key;
209 };
210 
211 
216 {
217 
222 
226  struct ClientState *cs;
227 
232 
238 
243 
250 
255 };
256 
257 
262 {
267 
272 
277 
282 
283 };
284 
285 
290 static gcry_mpi_t elgamal_q;
291 
296 static gcry_mpi_t elgamal_p;
297 
302 static gcry_mpi_t elgamal_g;
303 
308 
313 
317 static const struct GNUNET_CONFIGURATION_Handle *cfg;
318 
319 
327 static struct KeygenPeerInfo *
329  const struct GNUNET_PeerIdentity *peer)
330 {
331  unsigned int i;
332  for (i = 0; i < ks->num_peers; i++)
333  if (0 == GNUNET_memcmp (peer, &ks->info[i].peer))
334  return &ks->info[i];
335  return NULL;
336 }
337 
338 
346 static struct DecryptPeerInfo *
348  const struct GNUNET_PeerIdentity *peer)
349 {
350  unsigned int i;
351  for (i = 0; i < ds->share->num_peers; i++)
352  if (0 == GNUNET_memcmp (peer, &ds->info[i].peer))
353  return &ds->info[i];
354  return NULL;
355 }
356 
357 
366 static struct GNUNET_TIME_Absolute
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 
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 
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 == GNUNET_memcmp (&haystack[i],
415  needle))
416  return i;
417  return -1;
418 }
419 
420 
431 static struct GNUNET_PeerIdentity *
433  unsigned int num_listed,
434  unsigned int *num_normalized,
435  unsigned int *my_peer_idx)
436 {
437  unsigned int local_peer_in_list;
438  /* number of peers in the normalized list */
439  unsigned int n;
440  struct GNUNET_PeerIdentity *normalized;
441 
442  local_peer_in_list = GNUNET_YES;
443  n = num_listed;
444  if (peer_find (listed, num_listed, &my_peer) < 0)
445  {
446  local_peer_in_list = GNUNET_NO;
447  n += 1;
448  }
449 
450  normalized = GNUNET_new_array (n,
451  struct GNUNET_PeerIdentity);
452 
453  if (GNUNET_NO == local_peer_in_list)
454  normalized[n - 1] = my_peer;
455 
456  GNUNET_memcpy (normalized,
457  listed,
458  num_listed * sizeof (struct GNUNET_PeerIdentity));
459  qsort (normalized,
460  n,
461  sizeof (struct GNUNET_PeerIdentity),
462  &peer_id_cmp);
463 
464  if (NULL != my_peer_idx)
465  *my_peer_idx = peer_find (normalized, n, &my_peer);
466  if (NULL != num_normalized)
467  *num_normalized = n;
468 
469  return normalized;
470 }
471 
472 
481 static void
482 compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
483  unsigned int *indices,
484  unsigned int num)
485 {
486  unsigned int i;
487  /* numerator */
488  gcry_mpi_t n;
489  /* denominator */
490  gcry_mpi_t d;
491  /* temp value for l-j */
492  gcry_mpi_t tmp;
493 
494  GNUNET_assert (0 != coeff);
495 
496  GNUNET_assert (0 != (n = gcry_mpi_new (0)));
497  GNUNET_assert (0 != (d = gcry_mpi_new (0)));
498  GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
499 
500  gcry_mpi_set_ui (n, 1);
501  gcry_mpi_set_ui (d, 1);
502 
503  for (i = 0; i < num; i++)
504  {
505  unsigned int l = indices[i];
506  if (l == j)
507  continue;
508  gcry_mpi_mul_ui (n, n, l + 1);
509  // d <- d * (l-j)
510  gcry_mpi_set_ui (tmp, l + 1);
511  gcry_mpi_sub_ui (tmp, tmp, j + 1);
512  gcry_mpi_mul (d, d, tmp);
513  }
514 
515  // gcry_mpi_invm does not like negative numbers ...
516  gcry_mpi_mod (d, d, elgamal_q);
517 
518  GNUNET_assert (gcry_mpi_cmp_ui (d, 0) > 0);
519 
520  // now we do the actual division, with everything mod q, as we
521  // are not operating on elements from <g>, but on exponents
522  GNUNET_assert (0 != gcry_mpi_invm (d, d, elgamal_q));
523 
524  gcry_mpi_mulm (coeff, n, d, elgamal_q);
525 
526  gcry_mpi_release (n);
527  gcry_mpi_release (d);
528  gcry_mpi_release (tmp);
529 }
530 
531 
538 static void
540 {
542  "destroying decrypt session\n");
543  if (NULL != ds->cs)
544  {
545  ds->cs->decrypt_session = NULL;
546  ds->cs = NULL;
547  }
548  if (NULL != ds->consensus)
549  {
551  ds->consensus = NULL;
552  }
553 
554  if (NULL != ds->info)
555  {
556  for (unsigned int i = 0; i < ds->share->num_peers; i++)
557  {
558  if (NULL != ds->info[i].partial_decryption)
559  {
560  gcry_mpi_release (ds->info[i].partial_decryption);
561  ds->info[i].partial_decryption = NULL;
562  }
563  }
564  GNUNET_free (ds->info);
565  ds->info = NULL;
566  }
567  if (NULL != ds->share)
568  {
570  ds->share = NULL;
571  }
572 
573  GNUNET_free (ds);
574 }
575 
576 
577 static void
579 {
580  if (NULL != info->sigma)
581  {
582  gcry_mpi_release (info->sigma);
583  info->sigma = NULL;
584  }
585  if (NULL != info->presecret_commitment)
586  {
587  gcry_mpi_release (info->presecret_commitment);
588  info->presecret_commitment = NULL;
589  }
590  if (NULL != info->preshare_commitment)
591  {
592  gcry_mpi_release (info->preshare_commitment);
593  info->preshare_commitment = NULL;
594  }
595 }
596 
597 
598 static void
600 {
602  "destroying keygen session\n");
603 
604  if (NULL != ks->cs)
605  {
606  ks->cs->keygen_session = NULL;
607  ks->cs = NULL;
608  }
609  if (NULL != ks->info)
610  {
611  for (unsigned int i = 0; i < ks->num_peers; i++)
612  keygen_info_destroy (&ks->info[i]);
613  GNUNET_free (ks->info);
614  ks->info = NULL;
615  }
616 
617  if (NULL != ks->consensus)
618  {
620  ks->consensus = NULL;
621  }
622 
623  if (NULL != ks->presecret_polynomial)
624  {
625  for (unsigned int i = 0; i < ks->threshold; i++)
626  {
627  GNUNET_assert (NULL != ks->presecret_polynomial[i]);
628  gcry_mpi_release (ks->presecret_polynomial[i]);
629  ks->presecret_polynomial[i] = NULL;
630  }
632  ks->presecret_polynomial = NULL;
633  }
634  if (NULL != ks->my_share)
635  {
636  gcry_mpi_release (ks->my_share);
637  ks->my_share = NULL;
638  }
639  if (NULL != ks->public_key)
640  {
641  gcry_mpi_release (ks->public_key);
642  ks->public_key = NULL;
643  }
644  if (NULL != ks->peers)
645  {
646  GNUNET_free (ks->peers);
647  ks->peers = NULL;
648  }
649  GNUNET_free (ks);
650 }
651 
652 
659 static void
660 cleanup_task (void *cls)
661 {
662  /* Nothing to do! */
663 }
664 
665 
666 
672 static void
674 {
675  int i;
676  gcry_mpi_t v;
677 
678  GNUNET_assert (NULL == ks->presecret_polynomial);
680  gcry_mpi_t);
681  for (i = 0; i < ks->threshold; i++)
682  {
683  v = ks->presecret_polynomial[i] = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS);
684  GNUNET_assert (NULL != v);
685  // Randomize v such that 0 < v < elgamal_q.
686  // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
687  do
688  {
689  gcry_mpi_randomize (v, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
690  } while ((gcry_mpi_cmp_ui (v, 0) == 0) || (gcry_mpi_cmp (v, elgamal_q) >= 0));
691  }
692 }
693 
694 
703 static void
705  const struct GNUNET_SET_Element *element)
706 {
708  struct KeygenSession *ks = cls;
709  struct KeygenPeerInfo *info;
710 
711  if (NULL == element)
712  {
713  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n");
714  return;
715  }
716 
717  /* elements have fixed size */
718  if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
719  {
721  "keygen commit data with wrong size (%u) in consensus, %u expected\n",
722  (unsigned int) element->size,
723  (unsigned int) sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData));
724  return;
725  }
726 
727  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
728 
729  d = element->data;
730  info = get_keygen_peer_info (ks, &d->peer);
731 
732  if (NULL == info)
733  {
734  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
735  GNUNET_i2s (&d->peer));
736  return;
737  }
738 
739  /* Check that the right amount of data has been signed. */
740  if (d->purpose.size !=
741  htonl (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)))
742  {
743  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong signature purpose size in consensus\n");
744  return;
745  }
746 
748  &d->purpose, &d->signature, &d->peer.public_key))
749  {
750  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n");
751  return;
752  }
753  info->paillier_public_key = d->pubkey;
755  info->round1_valid = GNUNET_YES;
756 }
757 
758 
769 static void
770 horner_eval (gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
771 {
772  unsigned int i;
773 
774  gcry_mpi_set_ui (z, 0);
775  for (i = 0; i < num_coeff; i++)
776  {
777  // z <- zx + c
778  gcry_mpi_mul (z, z, x);
779  gcry_mpi_addm (z, z, coeff[num_coeff - i - 1], m);
780  }
781 }
782 
783 
784 static void
786 {
787  struct KeygenSession *ks = cls;
789  struct GNUNET_MQ_Envelope *ev;
790  size_t share_size;
791  unsigned int i;
792  unsigned int j;
793  struct GNUNET_SECRETSHARING_Share *share;
794 
795  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
796 
798  ks->consensus = NULL;
799 
800  share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
801 
802  share->num_peers = 0;
803 
804  for (i = 0; i < ks->num_peers; i++)
805  if (GNUNET_YES == ks->info[i].round2_valid)
806  share->num_peers++;
807 
808  share->peers = GNUNET_new_array (share->num_peers,
809  struct GNUNET_PeerIdentity);
810  share->sigmas =
811  GNUNET_new_array (share->num_peers,
814  uint16_t);
815 
816  /* maybe we're not even in the list of peers? */
817  share->my_peer = share->num_peers;
818 
819  j = 0; /* running index of valid peers */
820  for (i = 0; i < ks->num_peers; i++)
821  {
822  if (GNUNET_YES == ks->info[i].round2_valid)
823  {
824  share->peers[j] = ks->info[i].peer;
827  ks->info[i].sigma);
828  share->original_indices[i] = j;
829  if (0 == GNUNET_memcmp (&share->peers[i], &my_peer))
830  share->my_peer = j;
831  j += 1;
832  }
833  }
834 
835  if (share->my_peer == share->num_peers)
836  {
837  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: peer identity not in share\n", ks->local_peer_idx);
838  }
839 
841  ks->my_share);
843  ks->public_key);
844 
845  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers);
846 
847  /* Write the share. If 0 peers completed the dkg, an empty
848  * share will be sent. */
849 
850  GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
851 
852  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "writing share of size %u\n",
853  (unsigned int) share_size);
854 
855  ev = GNUNET_MQ_msg_extra (m, share_size,
857 
858  GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &m[1], share_size, NULL));
859 
861  share = NULL;
862 
863  GNUNET_MQ_send (ks->cs->mq,
864  ev);
865 }
866 
867 
868 
869 static void
871  const struct GNUNET_SECRETSHARING_FairEncryption *fe,
872  gcry_mpi_t x, gcry_mpi_t xres)
873 {
874  gcry_mpi_t a_1;
875  gcry_mpi_t a_2;
876  gcry_mpi_t b_1;
877  gcry_mpi_t b_2;
878  gcry_mpi_t big_a;
879  gcry_mpi_t big_b;
880  gcry_mpi_t big_t;
881  gcry_mpi_t n;
882  gcry_mpi_t t_1;
883  gcry_mpi_t t_2;
884  gcry_mpi_t t;
885  gcry_mpi_t r;
886  gcry_mpi_t v;
887 
888 
889  GNUNET_assert (NULL != (n = gcry_mpi_new (0)));
890  GNUNET_assert (NULL != (t = gcry_mpi_new (0)));
891  GNUNET_assert (NULL != (t_1 = gcry_mpi_new (0)));
892  GNUNET_assert (NULL != (t_2 = gcry_mpi_new (0)));
893  GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
894  GNUNET_assert (NULL != (big_t = gcry_mpi_new (0)));
895  GNUNET_assert (NULL != (v = gcry_mpi_new (0)));
896  GNUNET_assert (NULL != (big_a = gcry_mpi_new (0)));
897  GNUNET_assert (NULL != (big_b = gcry_mpi_new (0)));
898 
899  // a = (N,0)^T
901  ppub,
902  sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
903  GNUNET_assert (NULL != (a_2 = gcry_mpi_new (0)));
904  gcry_mpi_set_ui (a_2, 0);
905  // b = (x,1)^T
906  GNUNET_assert (NULL != (b_1 = gcry_mpi_new (0)));
907  gcry_mpi_set (b_1, x);
908  GNUNET_assert (NULL != (b_2 = gcry_mpi_new (0)));
909  gcry_mpi_set_ui (b_2, 1);
910 
911  // A = a DOT a
912  gcry_mpi_mul (t, a_1, a_1);
913  gcry_mpi_mul (big_a, a_2, a_2);
914  gcry_mpi_add (big_a, big_a, t);
915 
916  // B = b DOT b
917  gcry_mpi_mul (t, b_1, b_1);
918  gcry_mpi_mul (big_b, b_2, b_2);
919  gcry_mpi_add (big_b, big_b, t);
920 
921  while (1)
922  {
923  // n = a DOT b
924  gcry_mpi_mul (t, a_1, b_1);
925  gcry_mpi_mul (n, a_2, b_2);
926  gcry_mpi_add (n, n, t);
927 
928  // r = nearest(n/B)
929  gcry_mpi_div (r, NULL, n, big_b, 0);
930 
931  // T := A - 2rn + rrB
932  gcry_mpi_mul (v, r, n);
933  gcry_mpi_mul_ui (v, v, 2);
934  gcry_mpi_sub (big_t, big_a, v);
935  gcry_mpi_mul (v, r, r);
936  gcry_mpi_mul (v, v, big_b);
937  gcry_mpi_add (big_t, big_t, v);
938 
939  if (gcry_mpi_cmp (big_t, big_b) >= 0)
940  {
941  break;
942  }
943 
944  // t = a - rb
945  gcry_mpi_mul (v, r, b_1);
946  gcry_mpi_sub (t_1, a_1, v);
947  gcry_mpi_mul (v, r, b_2);
948  gcry_mpi_sub (t_2, a_2, v);
949 
950  // a = b
951  gcry_mpi_set (a_1, b_1);
952  gcry_mpi_set (a_2, b_2);
953  // b = t
954  gcry_mpi_set (b_1, t_1);
955  gcry_mpi_set (b_2, t_2);
956 
957  gcry_mpi_set (big_a, big_b);
958  gcry_mpi_set (big_b, big_t);
959  }
960 
961  gcry_mpi_set (xres, b_2);
962  gcry_mpi_invm (xres, xres, elgamal_q);
963  gcry_mpi_mulm (xres, xres, b_1, elgamal_q);
964 
965  gcry_mpi_release (a_1);
966  gcry_mpi_release (a_2);
967  gcry_mpi_release (b_1);
968  gcry_mpi_release (b_2);
969  gcry_mpi_release (big_a);
970  gcry_mpi_release (big_b);
971  gcry_mpi_release (big_t);
972  gcry_mpi_release (n);
973  gcry_mpi_release (t_1);
974  gcry_mpi_release (t_2);
975  gcry_mpi_release (t);
976  gcry_mpi_release (r);
977  gcry_mpi_release (v);
978 }
979 
980 
981 static void
983  gcry_mpi_t *e)
984 {
985  struct {
989  char t2[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8];
990  } hash_data;
991  struct GNUNET_HashCode e_hash;
992 
993  memset (&hash_data,
994  0,
995  sizeof (hash_data));
996  GNUNET_memcpy (&hash_data.c, &fe->c, sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
997  GNUNET_memcpy (&hash_data.h, &fe->h, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
998  GNUNET_memcpy (&hash_data.t1, &fe->t1, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
999  GNUNET_memcpy (&hash_data.t2, &fe->t2, GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8);
1000  GNUNET_CRYPTO_hash (&hash_data,
1001  sizeof (hash_data),
1002  &e_hash);
1003  /* This allocates "e" */
1005  &e_hash,
1006  sizeof (struct GNUNET_HashCode));
1007  gcry_mpi_mod (*e, *e, elgamal_q);
1008 }
1009 
1010 
1011 static int
1013  const struct GNUNET_SECRETSHARING_FairEncryption *fe)
1014 {
1015  gcry_mpi_t n;
1016  gcry_mpi_t n_sq;
1017  gcry_mpi_t z;
1018  gcry_mpi_t t1;
1019  gcry_mpi_t t2;
1020  gcry_mpi_t e;
1021  gcry_mpi_t w;
1022  gcry_mpi_t tmp1;
1023  gcry_mpi_t tmp2;
1024  gcry_mpi_t y;
1025  gcry_mpi_t big_y;
1026  int res;
1027 
1028  GNUNET_assert (NULL != (n_sq = gcry_mpi_new (0)));
1029  GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0)));
1030  GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0)));
1031 
1033  &e /* this allocates e */);
1034 
1036  ppub,
1037  sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
1044  gcry_mpi_mul (n_sq, n, n);
1045 
1046  // tmp1 = g^z
1047  gcry_mpi_powm (tmp1, elgamal_g, z, elgamal_p);
1048  // tmp2 = y^{-e}
1049  gcry_mpi_powm (tmp1, y, e, elgamal_p);
1050  gcry_mpi_invm (tmp1, tmp1, elgamal_p);
1051  // tmp1 = tmp1 * tmp2
1052  gcry_mpi_mulm (tmp1, tmp1, tmp2, elgamal_p);
1053 
1054  if (0 == gcry_mpi_cmp (t1, tmp1))
1055  {
1056  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "fair encryption invalid (t1)\n");
1057  res = GNUNET_NO;
1058  goto cleanup;
1059  }
1060 
1061  gcry_mpi_powm (big_y, big_y, e, n_sq);
1062  gcry_mpi_invm (big_y, big_y, n_sq);
1063 
1064  gcry_mpi_add_ui (tmp1, n, 1);
1065  gcry_mpi_powm (tmp1, tmp1, z, n_sq);
1066 
1067  gcry_mpi_powm (tmp2, w, n, n_sq);
1068 
1069  gcry_mpi_mulm (tmp1, tmp1, tmp2, n_sq);
1070  gcry_mpi_mulm (tmp1, tmp1, big_y, n_sq);
1071 
1072 
1073  if (0 == gcry_mpi_cmp (t2, tmp1))
1074  {
1075  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "fair encryption invalid (t2)\n");
1076  res = GNUNET_NO;
1077  goto cleanup;
1078  }
1079 
1080  res = GNUNET_YES;
1081 
1082 cleanup:
1083 
1084  gcry_mpi_release (n);
1085  gcry_mpi_release (n_sq);
1086  gcry_mpi_release (z);
1087  gcry_mpi_release (t1);
1088  gcry_mpi_release (t2);
1089  gcry_mpi_release (e);
1090  gcry_mpi_release (w);
1091  gcry_mpi_release (tmp1);
1092  gcry_mpi_release (tmp2);
1093  gcry_mpi_release (y);
1094  gcry_mpi_release (big_y);
1095  return res;
1096 }
1097 
1098 
1105 static void
1106 encrypt_fair (gcry_mpi_t v,
1107  const struct GNUNET_CRYPTO_PaillierPublicKey *ppub,
1109 {
1110  gcry_mpi_t r;
1111  gcry_mpi_t s;
1112  gcry_mpi_t t1;
1113  gcry_mpi_t t2;
1114  gcry_mpi_t z;
1115  gcry_mpi_t w;
1116  gcry_mpi_t n;
1117  gcry_mpi_t e;
1118  gcry_mpi_t n_sq;
1119  gcry_mpi_t u;
1120  gcry_mpi_t Y;
1121  gcry_mpi_t G;
1122  gcry_mpi_t h;
1123 
1124  GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
1125  GNUNET_assert (NULL != (s = gcry_mpi_new (0)));
1126  GNUNET_assert (NULL != (t1 = gcry_mpi_new (0)));
1127  GNUNET_assert (NULL != (t2 = gcry_mpi_new (0)));
1128  GNUNET_assert (NULL != (z = gcry_mpi_new (0)));
1129  GNUNET_assert (NULL != (w = gcry_mpi_new (0)));
1130  GNUNET_assert (NULL != (n_sq = gcry_mpi_new (0)));
1131  GNUNET_assert (NULL != (u = gcry_mpi_new (0)));
1132  GNUNET_assert (NULL != (Y = gcry_mpi_new (0)));
1133  GNUNET_assert (NULL != (G = gcry_mpi_new (0)));
1134  GNUNET_assert (NULL != (h = gcry_mpi_new (0)));
1135 
1137  ppub,
1138  sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
1139  gcry_mpi_mul (n_sq, n, n);
1140  gcry_mpi_add_ui (G, n, 1);
1141 
1142  do {
1143  gcry_mpi_randomize (u, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM);
1144  }
1145  while (gcry_mpi_cmp (u, n) >= 0);
1146 
1147  gcry_mpi_powm (t1, G, v, n_sq);
1148  gcry_mpi_powm (t2, u, n, n_sq);
1149  gcry_mpi_mulm (Y, t1, t2, n_sq);
1150 
1152  sizeof fe->c.bits,
1153  Y);
1154 
1155 
1156  gcry_mpi_randomize (r, 2048, GCRY_WEAK_RANDOM);
1157  do {
1158  gcry_mpi_randomize (s, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM);
1159  }
1160  while (gcry_mpi_cmp (s, n) >= 0);
1161 
1162  // compute t1
1163  gcry_mpi_mulm (t1, elgamal_g, r, elgamal_p);
1164  // compute t2 (use z and w as temp)
1165  gcry_mpi_powm (z, G, r, n_sq);
1166  gcry_mpi_powm (w, s, n, n_sq);
1167  gcry_mpi_mulm (t2, z, w, n_sq);
1168 
1169 
1170  gcry_mpi_powm (h, elgamal_g, v, elgamal_p);
1171 
1174  h);
1175 
1178  t1);
1179 
1182  t2);
1183 
1185  &e /* This allocates "e" */);
1186 
1187  // compute z
1188  gcry_mpi_mul (z, e, v);
1189  gcry_mpi_addm (z, z, r, elgamal_q);
1190  // compute w
1191  gcry_mpi_powm (w, u, e, n);
1192  gcry_mpi_mulm (w, w, s, n);
1193 
1196  z);
1197 
1200  w);
1201 
1202  gcry_mpi_release (n);
1203  gcry_mpi_release (r);
1204  gcry_mpi_release (s);
1205  gcry_mpi_release (t1);
1206  gcry_mpi_release (t2);
1207  gcry_mpi_release (z);
1208  gcry_mpi_release (w);
1209  gcry_mpi_release (e);
1210  gcry_mpi_release (n_sq);
1211  gcry_mpi_release (u);
1212  gcry_mpi_release (Y);
1213  gcry_mpi_release (G);
1214  gcry_mpi_release (h);
1215 }
1216 
1217 
1228 static void
1230 {
1231  struct GNUNET_SET_Element *element;
1233  unsigned char *pos;
1234  unsigned char *last_pos;
1235  size_t element_size;
1236  unsigned int i;
1237  gcry_mpi_t idx;
1238  gcry_mpi_t v;
1239 
1240  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting round2 element\n",
1241  ks->local_peer_idx);
1242 
1243  GNUNET_assert (NULL != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1244  GNUNET_assert (NULL != (idx = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1245 
1246  element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
1247  sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * ks->num_peers +
1249 
1250  element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
1251  element->size = element_size;
1252  element->data = (void *) &element[1];
1253 
1254  d = (void *) element->data;
1255  d->peer = my_peer;
1256 
1257  // start inserting vector elements
1258  // after the fixed part of the element's data
1259  pos = (void *) &d[1];
1260  last_pos = pos + element_size;
1261 
1262  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp preshares\n",
1263  ks->local_peer_idx);
1264 
1265  // encrypted pre-shares
1266  // and fair encryption proof
1267  {
1268  for (i = 0; i < ks->num_peers; i++)
1269  {
1270  ptrdiff_t remaining = last_pos - pos;
1271  struct GNUNET_SECRETSHARING_FairEncryption *fe = (void *) pos;
1272 
1273  GNUNET_assert (remaining > 0);
1274  memset (fe, 0, sizeof *fe);
1275  if (GNUNET_YES == ks->info[i].round1_valid)
1276  {
1277  gcry_mpi_set_ui (idx, i + 1);
1278  // evaluate the polynomial
1280  // encrypt the result
1281  encrypt_fair (v, &ks->info[i].paillier_public_key, fe);
1282  }
1283  pos += sizeof *fe;
1284  }
1285  }
1286 
1287  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed enc preshares\n",
1288  ks->local_peer_idx);
1289 
1290  // exponentiated coefficients
1291  for (i = 0; i < ks->threshold; i++)
1292  {
1293  ptrdiff_t remaining = last_pos - pos;
1294  GNUNET_assert (remaining > 0);
1295  gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
1298  }
1299 
1300  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp coefficients\n",
1301  ks->local_peer_idx);
1302 
1303 
1304  d->purpose.size = htonl (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
1307  GNUNET_CRYPTO_eddsa_sign (my_peer_private_key,
1308  &d->purpose,
1309  &d->signature));
1310 
1311  GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1312  GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
1313 
1314  gcry_mpi_release (v);
1315  gcry_mpi_release (idx);
1316 }
1317 
1318 
1319 static gcry_mpi_t
1321  const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
1322  unsigned int idx)
1323 {
1324  unsigned char *pos;
1325  gcry_mpi_t exp_coeff;
1326 
1327  GNUNET_assert (idx < ks->threshold);
1328 
1329  pos = (void *) &d[1];
1330  // skip encrypted pre-shares
1331  pos += sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * ks->num_peers;
1332  // skip exp. coeffs we are not interested in
1333  pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * idx;
1334  // the first exponentiated coefficient is the public key share
1336  return exp_coeff;
1337 }
1338 
1339 
1342  const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
1343  unsigned int idx)
1344 {
1345  unsigned char *pos;
1346 
1347  GNUNET_assert (idx < ks->num_peers);
1348 
1349  pos = (void *) &d[1];
1350  // skip encrypted pre-shares we're not interested in
1351  pos += sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * idx;
1352  return (struct GNUNET_SECRETSHARING_FairEncryption *) pos;
1353 }
1354 
1355 
1356 static gcry_mpi_t
1358  const struct GNUNET_SECRETSHARING_KeygenRevealData *d,
1359  unsigned int idx)
1360 {
1361  gcry_mpi_t exp_preshare;
1363 
1364  GNUNET_assert (idx < ks->num_peers);
1365  fe = keygen_reveal_get_enc_preshare (ks, d, idx);
1367  return exp_preshare;
1368 }
1369 
1370 
1371 static void
1373  const struct GNUNET_SET_Element *element)
1374 {
1375  struct KeygenSession *ks = cls;
1376  const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
1377  struct KeygenPeerInfo *info;
1378  size_t expected_element_size;
1379  unsigned int j;
1380  int cmp_result;
1381  gcry_mpi_t tmp;
1382  gcry_mpi_t public_key_share;
1383  gcry_mpi_t preshare;
1384 
1385  if (NULL == element)
1386  {
1387  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n");
1388  return;
1389  }
1390 
1391  expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
1392  sizeof (struct GNUNET_SECRETSHARING_FairEncryption) * ks->num_peers +
1394 
1395  if (element->size != expected_element_size)
1396  {
1398  "keygen round2 data with wrong size (%u) in consensus, %u expected\n",
1399  (unsigned int) element->size,
1400  (unsigned int) expected_element_size);
1401  return;
1402  }
1403 
1404  d = (const void *) element->data;
1405 
1406  info = get_keygen_peer_info (ks, &d->peer);
1407 
1408  if (NULL == info)
1409  {
1410  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
1411  GNUNET_i2s (&d->peer));
1412  return;
1413  }
1414 
1415  if (GNUNET_NO == info->round1_valid)
1416  {
1418  "ignoring round2 element from peer with invalid round1 element (%s)\n",
1419  GNUNET_i2s (&d->peer));
1420  return;
1421  }
1422 
1423  if (GNUNET_YES == info->round2_valid)
1424  {
1426  "ignoring duplicate round2 element (%s)\n",
1427  GNUNET_i2s (&d->peer));
1428  return;
1429  }
1430 
1431  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
1432 
1433  if (ntohl (d->purpose.size) !=
1434  element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose))
1435  {
1436  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n");
1437  return;
1438  }
1439 
1441  &d->purpose, &d->signature, &d->peer.public_key))
1442  {
1443  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n");
1444  return;
1445  }
1446 
1447  public_key_share = keygen_reveal_get_exp_coeff (ks, d, 0);
1449 
1450  if (NULL == ks->public_key)
1451  {
1452  GNUNET_assert (NULL != (ks->public_key = gcry_mpi_new (0)));
1453  gcry_mpi_set_ui (ks->public_key, 1);
1454  }
1455  gcry_mpi_mulm (ks->public_key, ks->public_key, public_key_share, elgamal_p);
1456 
1457  gcry_mpi_release (public_key_share);
1458  public_key_share = NULL;
1459 
1460  {
1461  struct GNUNET_SECRETSHARING_FairEncryption *fe = keygen_reveal_get_enc_preshare (ks, d, ks->local_peer_idx);
1462  GNUNET_assert (NULL != (preshare = gcry_mpi_new (0)));
1465  &fe->c,
1466  preshare);
1467 
1468  // FIXME: not doing the restoration is less expensive
1470  fe,
1471  preshare,
1472  preshare);
1473  }
1474 
1475  GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
1476  gcry_mpi_powm (tmp, elgamal_g, preshare, elgamal_p);
1477 
1478  cmp_result = gcry_mpi_cmp (tmp, info->preshare_commitment);
1479  gcry_mpi_release (tmp);
1480  tmp = NULL;
1481  if (0 != cmp_result)
1482  {
1483  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Got invalid presecret from P%u\n",
1484  (unsigned int) ks->local_peer_idx, (unsigned int) (info - ks->info));
1485  return;
1486  }
1487 
1488  if (NULL == ks->my_share)
1489  {
1490  GNUNET_assert (NULL != (ks->my_share = gcry_mpi_new (0)));
1491  }
1492  gcry_mpi_addm (ks->my_share, ks->my_share, preshare, elgamal_q);
1493 
1494  for (j = 0; j < ks->num_peers; j++)
1495  {
1496  gcry_mpi_t presigma;
1497  if (NULL == ks->info[j].sigma)
1498  {
1499  GNUNET_assert (NULL != (ks->info[j].sigma = gcry_mpi_new (0)));
1500  gcry_mpi_set_ui (ks->info[j].sigma, 1);
1501  }
1502  presigma = keygen_reveal_get_exp_preshare (ks, d, j);
1503  gcry_mpi_mulm (ks->info[j].sigma, ks->info[j].sigma, presigma, elgamal_p);
1504  gcry_mpi_release (presigma);
1505  }
1506 
1507  gcry_mpi_t prod;
1508  GNUNET_assert (NULL != (prod = gcry_mpi_new (0)));
1509  gcry_mpi_t j_to_k;
1510  GNUNET_assert (NULL != (j_to_k = gcry_mpi_new (0)));
1511  // validate that the polynomial sharing matches the additive sharing
1512  for (j = 0; j < ks->num_peers; j++)
1513  {
1514  unsigned int k;
1515  int cmp_result;
1516  gcry_mpi_t exp_preshare;
1517  gcry_mpi_set_ui (prod, 1);
1518  for (k = 0; k < ks->threshold; k++)
1519  {
1520  // Using pow(double,double) is a bit sketchy.
1521  // We count players from 1, but shares from 0.
1522  gcry_mpi_t tmp;
1523  gcry_mpi_set_ui (j_to_k, (unsigned int) pow(j+1, k));
1524  tmp = keygen_reveal_get_exp_coeff (ks, d, k);
1525  gcry_mpi_powm (tmp, tmp, j_to_k, elgamal_p);
1526  gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1527  gcry_mpi_release (tmp);
1528  }
1529  exp_preshare = keygen_reveal_get_exp_preshare (ks, d, j);
1530  gcry_mpi_mod (exp_preshare, exp_preshare, elgamal_p);
1531  cmp_result = gcry_mpi_cmp (prod, exp_preshare);
1532  gcry_mpi_release (exp_preshare);
1533  exp_preshare = NULL;
1534  if (0 != cmp_result)
1535  {
1536  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: reveal data from P%u incorrect\n",
1537  ks->local_peer_idx, j);
1538  /* no need for further verification, round2 stays invalid ... */
1539  return;
1540  }
1541  }
1542 
1543  // TODO: verify proof of fair encryption (once implemented)
1544  for (j = 0; j < ks->num_peers; j++)
1545  {
1546  struct GNUNET_SECRETSHARING_FairEncryption *fe = keygen_reveal_get_enc_preshare (ks, d, j);
1547  if (GNUNET_YES != verify_fair (&ks->info[j].paillier_public_key, fe))
1548  {
1549  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: reveal data from P%u incorrect (fair encryption)\n",
1550  ks->local_peer_idx, j);
1551  return;
1552  }
1553 
1554  }
1555 
1556  info->round2_valid = GNUNET_YES;
1557 
1558  gcry_mpi_release (preshare);
1559  gcry_mpi_release (prod);
1560  gcry_mpi_release (j_to_k);
1561 }
1562 
1563 
1570 static void
1572 {
1573  struct KeygenSession *ks = cls;
1574 
1576 
1577  ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
1578  time_between (ks->start_time, ks->deadline, 1, 2),
1579  ks->deadline,
1581 
1582  insert_round2_element (ks);
1583 
1586  ks);
1587 }
1588 
1589 
1596 static void
1598 {
1599  struct GNUNET_SET_Element *element;
1601  // g^a_{i,0}
1602  gcry_mpi_t v;
1603  // big-endian representation of 'v'
1604  unsigned char v_data[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
1605 
1606  element = GNUNET_malloc (sizeof *element + sizeof *d);
1607  d = (void *) &element[1];
1608  element->data = d;
1609  element->size = sizeof *d;
1610 
1611  d->peer = my_peer;
1612 
1613  GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1614 
1615  gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
1616 
1618 
1620 
1622 
1623  d->purpose.size = htonl ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
1626  GNUNET_CRYPTO_eddsa_sign (my_peer_private_key,
1627  &d->purpose,
1628  &d->signature));
1629 
1630  GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1631 
1632  gcry_mpi_release (v);
1633  GNUNET_free (element);
1634 }
1635 
1636 
1644 static int
1647 {
1648  unsigned int num_peers = ntohs (msg->num_peers);
1649 
1650  if (ntohs (msg->header.size) - sizeof (*msg) !=
1651  num_peers * sizeof (struct GNUNET_PeerIdentity))
1652  {
1653  GNUNET_break (0);
1654  return GNUNET_SYSERR;
1655  }
1656  return GNUNET_OK;
1657 }
1658 
1659 
1667 static void
1670 {
1671  struct ClientState *cs = cls;
1672  struct KeygenSession *ks;
1673 
1675  "client requested key generation\n");
1676  if (NULL != cs->keygen_session)
1677  {
1678  GNUNET_break (0);
1680  return;
1681  }
1682  ks = GNUNET_new (struct KeygenSession);
1683  ks->cs = cs;
1684  cs->keygen_session = ks;
1686  ks->threshold = ntohs (msg->threshold);
1687  ks->num_peers = ntohs (msg->num_peers);
1688 
1689  ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1],
1690  ks->num_peers,
1691  &ks->num_peers,
1692  &ks->local_peer_idx);
1693 
1694 
1696  "first round of consensus with %u peers\n",
1697  ks->num_peers);
1699  ks->num_peers,
1700  ks->peers,
1701  &msg->session_id,
1702  GNUNET_TIME_absolute_ntoh (msg->start),
1703  GNUNET_TIME_absolute_ntoh (msg->deadline),
1705  ks);
1706 
1707  ks->info = GNUNET_new_array (ks->num_peers,
1708  struct KeygenPeerInfo);
1709 
1710  for (unsigned int i = 0; i < ks->num_peers; i++)
1711  ks->info[i].peer = ks->peers[i];
1712 
1714  &ks->paillier_private_key);
1715 
1717  "P%u: Generated paillier key pair\n",
1718  ks->local_peer_idx);
1721  "P%u: Generated presecret polynomial\n",
1722  ks->local_peer_idx);
1723  insert_round1_element (ks);
1725  "P%u: Concluding for round 1\n",
1726  ks->local_peer_idx);
1729  ks);
1732  "P%u: Waiting for round 1 elements ...\n",
1733  ks->local_peer_idx);
1734 }
1735 
1736 
1740 static void
1741 decrypt_conclude (void *cls)
1742 {
1743  struct DecryptSession *ds = cls;
1745  struct GNUNET_MQ_Envelope *ev;
1746  gcry_mpi_t lagrange;
1747  gcry_mpi_t m;
1748  gcry_mpi_t tmp;
1749  gcry_mpi_t c_2;
1750  gcry_mpi_t prod;
1751  unsigned int *indices;
1752  unsigned int num;
1753  unsigned int i;
1754  unsigned int j;
1755 
1757  ds->consensus = NULL;
1758 
1759  GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
1760  GNUNET_assert (0 != (m = gcry_mpi_new (0)));
1761  GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
1762  GNUNET_assert (0 != (prod = gcry_mpi_new (0)));
1763 
1764  num = 0;
1765  for (i = 0; i < ds->share->num_peers; i++)
1766  if (NULL != ds->info[i].partial_decryption)
1767  num++;
1768 
1769  indices = GNUNET_new_array (num,
1770  unsigned int);
1771  j = 0;
1772  for (i = 0; i < ds->share->num_peers; i++)
1773  if (NULL != ds->info[i].partial_decryption)
1774  indices[j++] = ds->info[i].original_index;
1775 
1777  "P%u: decrypt conclude, with %u peers\n",
1778  ds->share->my_peer,
1779  num);
1780 
1781  gcry_mpi_set_ui (prod, 1);
1782  for (i = 0; i < num; i++)
1783  {
1784 
1786  "P%u: index of %u: %u\n",
1787  ds->share->my_peer, i, indices[i]);
1788  compute_lagrange_coefficient (lagrange, indices[i], indices, num);
1789  // w_i^{\lambda_i}
1790  gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p);
1791 
1792  // product of all exponentiated partiel decryptions ...
1793  gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1794  }
1795 
1797 
1798  GNUNET_assert (0 != gcry_mpi_invm (prod, prod, elgamal_p));
1799  gcry_mpi_mulm (m, c_2, prod, elgamal_p);
1802  msg->success = htonl (1);
1803  GNUNET_MQ_send (ds->cs->mq,
1804  ev);
1805 
1806  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sent decrypt done to client\n");
1807 
1808  GNUNET_free (indices);
1809 
1810  gcry_mpi_release(lagrange);
1811  gcry_mpi_release(m);
1812  gcry_mpi_release(tmp);
1813  gcry_mpi_release(prod);
1814  gcry_mpi_release(c_2);
1815 
1816  // FIXME: what if not enough peers participated?
1817 }
1818 
1819 
1827 static char *
1828 mpi_to_str (gcry_mpi_t mpi)
1829 {
1830  unsigned char *buf;
1831 
1832  GNUNET_assert (0 == gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, mpi));
1833  return (char *) buf;
1834 }
1835 
1836 
1840 static void
1842  const struct GNUNET_SET_Element *element)
1843 {
1844  struct DecryptSession *session = cls;
1845  const struct GNUNET_SECRETSHARING_DecryptData *d;
1846  struct DecryptPeerInfo *info;
1847  struct GNUNET_HashCode challenge_hash;
1848 
1849  /* nizk response */
1850  gcry_mpi_t r;
1851  /* nizk challenge */
1852  gcry_mpi_t challenge;
1853  /* nizk commit1, g^\beta */
1854  gcry_mpi_t commit1;
1855  /* nizk commit2, c_1^\beta */
1856  gcry_mpi_t commit2;
1857  /* homomorphic commitment to the peer's share,
1858  * public key share */
1859  gcry_mpi_t sigma;
1860  /* partial decryption we received */
1861  gcry_mpi_t w;
1862  /* ciphertext component #1 */
1863  gcry_mpi_t c1;
1864  /* temporary variable (for comparision) #1 */
1865  gcry_mpi_t tmp1;
1866  /* temporary variable (for comparision) #2 */
1867  gcry_mpi_t tmp2;
1868 
1869  if (NULL == element)
1870  {
1871  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1872  /* FIXME: destroy */
1873  return;
1874  }
1875 
1876  if (element->size != sizeof *d)
1877  {
1878  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element of wrong size in decrypt consensus\n");
1879  return;
1880  }
1881 
1882  d = element->data;
1883 
1884  info = get_decrypt_peer_info (session, &d->peer);
1885 
1886  if (NULL == info)
1887  {
1888  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element from invalid peer (%s)\n",
1889  GNUNET_i2s (&d->peer));
1890  return;
1891  }
1892 
1893  if (NULL != info->partial_decryption)
1894  {
1895  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n");
1896  return;
1897  }
1898 
1899  if (0 != GNUNET_memcmp (&d->ciphertext, &session->ciphertext))
1900  {
1901  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: got decrypt element with non-matching ciphertext from P%u\n",
1902  (unsigned int) session->share->my_peer, (unsigned int) (info - session->info));
1903 
1904  return;
1905  }
1906 
1907 
1908  GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) d,
1909  offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) -
1910  offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext),
1911  &challenge_hash);
1912 
1913  GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
1914  sizeof (struct GNUNET_HashCode));
1915 
1916  GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &session->share->sigmas[info - session->info],
1917  sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1918 
1920  sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1921 
1922  GNUNET_CRYPTO_mpi_scan_unsigned (&commit1, &d->nizk_commit1,
1923  sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1924 
1925  GNUNET_CRYPTO_mpi_scan_unsigned (&commit2, &d->nizk_commit2,
1926  sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1927 
1928  GNUNET_CRYPTO_mpi_scan_unsigned (&r, &d->nizk_response,
1929  sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1930 
1931  GNUNET_CRYPTO_mpi_scan_unsigned (&w, &d->partial_decryption,
1932  sizeof (struct GNUNET_SECRETSHARING_FieldElement));
1933 
1934  GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0)));
1935  GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0)));
1936 
1937  // tmp1 = g^r
1938  gcry_mpi_powm (tmp1, elgamal_g, r, elgamal_p);
1939 
1940  // tmp2 = g^\beta * \sigma^challenge
1941  gcry_mpi_powm (tmp2, sigma, challenge, elgamal_p);
1942  gcry_mpi_mulm (tmp2, tmp2, commit1, elgamal_p);
1943 
1944  if (0 != gcry_mpi_cmp (tmp1, tmp2))
1945  {
1946  char *tmp1_str;
1947  char *tmp2_str;
1948 
1949  tmp1_str = mpi_to_str (tmp1);
1950  tmp2_str = mpi_to_str (tmp2);
1952  "P%u: Received invalid partial decryption from P%u (eqn 1), expected %s got %s\n",
1953  session->share->my_peer,
1954  (unsigned int) (info - session->info),
1955  tmp1_str,
1956  tmp2_str);
1957  GNUNET_free (tmp1_str);
1958  GNUNET_free (tmp2_str);
1959  goto cleanup;
1960  }
1961 
1962 
1963  gcry_mpi_powm (tmp1, c1, r, elgamal_p);
1964 
1965  gcry_mpi_powm (tmp2, w, challenge, elgamal_p);
1966  gcry_mpi_mulm (tmp2, tmp2, commit2, elgamal_p);
1967 
1968 
1969  if (0 != gcry_mpi_cmp (tmp1, tmp2))
1970  {
1972  "P%u: Received invalid partial decryption from P%u (eqn 2)\n",
1973  session->share->my_peer,
1974  (unsigned int) (info - session->info));
1975  goto cleanup;
1976  }
1977 
1978 
1979  GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption,
1981 cleanup:
1982  gcry_mpi_release (tmp1);
1983  gcry_mpi_release (tmp2);
1984  gcry_mpi_release (sigma);
1985  gcry_mpi_release (commit1);
1986  gcry_mpi_release (commit2);
1987  gcry_mpi_release (r);
1988  gcry_mpi_release (w);
1989  gcry_mpi_release (challenge);
1990  gcry_mpi_release (c1);
1991 }
1992 
1993 
1994 static void
1996 {
1998  struct GNUNET_SET_Element element;
1999  /* our share */
2000  gcry_mpi_t s;
2001  /* partial decryption with our share */
2002  gcry_mpi_t w;
2003  /* first component of the elgamal ciphertext */
2004  gcry_mpi_t c1;
2005  /* nonce for dlog zkp */
2006  gcry_mpi_t beta;
2007  gcry_mpi_t tmp;
2008  gcry_mpi_t challenge;
2009  gcry_mpi_t sigma;
2010  struct GNUNET_HashCode challenge_hash;
2011 
2012  /* make vagrind happy until we implement the real deal ... */
2013  memset (&d, 0, sizeof d);
2014 
2015  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n",
2016  ds->share->my_peer);
2017 
2018  GNUNET_assert (ds->share->my_peer < ds->share->num_peers);
2019 
2026 
2027  GNUNET_assert (NULL != (w = gcry_mpi_new (0)));
2028  GNUNET_assert (NULL != (beta = gcry_mpi_new (0)));
2029  GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
2030 
2031  // FIXME: unnecessary, remove once crypto works
2032  gcry_mpi_powm (tmp, elgamal_g, s, elgamal_p);
2033  if (0 != gcry_mpi_cmp (tmp, sigma))
2034  {
2035  char *sigma_str = mpi_to_str (sigma);
2036  char *tmp_str = mpi_to_str (tmp);
2037  char *s_str = mpi_to_str (s);
2038  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Share of P%u is invalid, ref sigma %s, "
2039  "computed sigma %s, s %s\n",
2040  ds->share->my_peer,
2041  sigma_str, tmp_str, s_str);
2042  GNUNET_free (sigma_str);
2043  GNUNET_free (tmp_str);
2044  GNUNET_free (s_str);
2045  }
2046 
2047  gcry_mpi_powm (w, c1, s, elgamal_p);
2048 
2049  element.data = (void *) &d;
2050  element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
2051  element.element_type = 0;
2052 
2053  d.ciphertext = ds->ciphertext;
2054  d.peer = my_peer;
2056 
2057  // create the zero knowledge proof
2058  // randomly choose beta such that 0 < beta < q
2059  do
2060  {
2061  gcry_mpi_randomize (beta, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
2062  } while ((gcry_mpi_cmp_ui (beta, 0) == 0) || (gcry_mpi_cmp (beta, elgamal_q) >= 0));
2063  // tmp = g^beta
2064  gcry_mpi_powm (tmp, elgamal_g, beta, elgamal_p);
2066  // tmp = (c_1)^beta
2067  gcry_mpi_powm (tmp, c1, beta, elgamal_p);
2069 
2070  // the challenge is the hash of everything up to the response
2071  GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) &d,
2072  offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) -
2073  offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext),
2074  &challenge_hash);
2075 
2076  GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
2077  sizeof (struct GNUNET_HashCode));
2078 
2079  // compute the response in tmp,
2080  // tmp = (c * s + beta) mod q
2081  gcry_mpi_mulm (tmp, challenge, s, elgamal_q);
2082  gcry_mpi_addm (tmp, tmp, beta, elgamal_q);
2083 
2085 
2086  d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose));
2087  d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
2088 
2090  GNUNET_CRYPTO_eddsa_sign (my_peer_private_key,
2091  &d.purpose,
2092  &d.signature));
2093 
2094  GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
2096  "P%u: Inserting decrypt element done!\n",
2097  ds->share->my_peer);
2098 
2099  gcry_mpi_release (s);
2100  gcry_mpi_release (w);
2101  gcry_mpi_release (c1);
2102  gcry_mpi_release (beta);
2103  gcry_mpi_release (tmp);
2104  gcry_mpi_release (challenge);
2105  gcry_mpi_release (sigma);
2106 }
2107 
2108 
2116 static int
2119 {
2120  /* we check later, it's complicated */
2121  return GNUNET_OK;
2122 }
2123 
2124 
2132 static void
2135 {
2136  struct ClientState *cs = cls;
2137  struct DecryptSession *ds;
2138  struct GNUNET_HashCode session_id;
2139 
2140  if (NULL != cs->decrypt_session)
2141  {
2142  GNUNET_break (0);
2144  return;
2145  }
2146  ds = GNUNET_new (struct DecryptSession);
2147  cs->decrypt_session = ds;
2148  ds->cs = cs;
2149  ds->start = GNUNET_TIME_absolute_ntoh (msg->start);
2151  ds->ciphertext = msg->ciphertext;
2152 
2153  ds->share = GNUNET_SECRETSHARING_share_read (&msg[1],
2154  ntohs (msg->header.size) - sizeof (*msg),
2155  NULL);
2156  if (NULL == ds->share)
2157  {
2158  GNUNET_break (0);
2160  return;
2161  }
2162 
2163  /* FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ... */
2165  sizeof (struct GNUNET_SECRETSHARING_Ciphertext),
2166  &session_id);
2168  ds->share->num_peers,
2169  ds->share->peers,
2170  &session_id,
2171  ds->start,
2172  ds->deadline,
2174  ds);
2175 
2176 
2177  ds->info = GNUNET_new_array (ds->share->num_peers,
2178  struct DecryptPeerInfo);
2179  for (unsigned int i = 0; i < ds->share->num_peers; i++)
2180  {
2181  ds->info[i].peer = ds->share->peers[i];
2182  ds->info[i].original_index = ds->share->original_indices[i];
2183  }
2187  ds);
2190  "decrypting with %u peers\n",
2191  ds->share->num_peers);
2192 }
2193 
2194 
2195 static void
2197 {
2198  GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
2200  GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
2202  GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
2204 }
2205 
2206 
2214 static void
2215 run (void *cls,
2216  const struct GNUNET_CONFIGURATION_Handle *c,
2218 {
2219  cfg = c;
2220  my_peer_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
2221  if (NULL == my_peer_private_key)
2222  {
2224  "could not access host private key\n");
2225  GNUNET_break (0);
2227  return;
2228  }
2230  if (GNUNET_OK !=
2232  &my_peer))
2233  {
2235  "could not retrieve host identity\n");
2236  GNUNET_break (0);
2238  return;
2239  }
2241  NULL);
2242 }
2243 
2244 
2253 static void *
2255  struct GNUNET_SERVICE_Client *c,
2256  struct GNUNET_MQ_Handle *mq)
2257 {
2258  struct ClientState *cs = GNUNET_new (struct ClientState);;
2259 
2260  cs->client = c;
2261  cs->mq = mq;
2262  return cs;
2263 }
2264 
2265 
2273 static void
2275  struct GNUNET_SERVICE_Client *c,
2276  void *internal_cls)
2277 {
2278  struct ClientState *cs = internal_cls;
2279 
2280  if (NULL != cs->keygen_session)
2282 
2283  if (NULL != cs->decrypt_session)
2285  GNUNET_free (cs);
2286 }
2287 
2288 
2293 ("secretsharing",
2295  &run,
2298  NULL,
2299  GNUNET_MQ_hd_var_size (client_keygen,
2302  NULL),
2303  GNUNET_MQ_hd_var_size (client_decrypt,
2306  NULL),
static char * mpi_to_str(gcry_mpi_t mpi)
Get a string representation of an MPI.
static int peer_id_cmp(const void *p1, const void *p2)
Compare two peer identities.
static unsigned int threshold
What should the threshold for then key be?
static void insert_round1_element(struct KeygenSession *ks)
Insert the ephemeral key and the presecret commitment of this peer in the consensus of the given sess...
struct GNUNET_CRYPTO_EddsaSignature signature
Signature over the rest of the message.
static int peer_find(const struct GNUNET_PeerIdentity *haystack, unsigned int n, const struct GNUNET_PeerIdentity *needle)
Get the index of a peer in an array of peers.
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1
Signature for the first round of distributed key generation.
static void keygen_round1_conclude(void *cls)
Called when the first consensus round has concluded.
Information about a peer in a decrypt session.
static gcry_mpi_t keygen_reveal_get_exp_preshare(struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
struct GNUNET_PeerIdentity peer
Peer that inserts this element.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration of this service.
void GNUNET_CONSENSUS_destroy(struct GNUNET_CONSENSUS_Handle *consensus)
Destroy a consensus handle (free all state associated with it, no longer call any of the callbacks)...
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void insert_round2_element(struct KeygenSession *ks)
Insert round 2 element in the consensus, consisting of (1) The exponentiated pre-share polynomial coe...
struct GNUNET_SECRETSHARING_Share * GNUNET_SECRETSHARING_share_read(const void *data, size_t len, size_t *readlen)
Read a share from its binary representation.
State we keep per client.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:670
gcry_mpi_t preshare_commitment
Commitment to the preshare that is intended for our peer.
static unsigned int element_size
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
struct GNUNET_SECRETSHARING_FieldElement my_share
Share of &#39;my_peer&#39;.
p2p message definitions for secretsharing
#define GNUNET_SECRETSHARING_ELGAMAL_G_HEX
The g-parameter for ElGamal encryption, a generator of the unique size q subgroup of Z_p^*...
int round1_valid
Did we successfully receive the round1 element of the peer?
struct GNUNET_PeerIdentity peer
Peer that inserts this element.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Handle to a service.
Definition: service.c:116
struct GNUNET_SECRETSHARING_FieldElement plaintext
Decrypted plaintext.
struct GNUNET_MQ_Handle * mq
MQ to talk to client.
void GNUNET_SECRETSHARING_share_destroy(struct GNUNET_SECRETSHARING_Share *share)
struct GNUNET_SECRETSHARING_Share * share
Share of the local peer.
static void decrypt_conclude(void *cls)
Called when the partial decryption consensus concludes.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
Element stored in a set.
struct GNUNET_PeerIdentity * peers
Peer identities (includes &#39;my_peer&#39;)
static void keygen_round2_conclude(void *cls)
static struct DecryptPeerInfo * get_decrypt_peer_info(const struct DecryptSession *ds, const struct GNUNET_PeerIdentity *peer)
Get the peer info belonging to a peer identity in a decrypt session.
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static void generate_presecret_polynomial(struct KeygenSession *ks)
Generate the random coefficients of our pre-secret polynomial.
char h[GNUNET_SECRETSHARING_ELGAMAL_BITS/8]
h = g^x, where x is the fairly encrypte secret.
static struct KeygenPeerInfo * get_keygen_peer_info(const struct KeygenSession *ks, const struct GNUNET_PeerIdentity *peer)
Get the peer info belonging to a peer identity in a keygen session.
static void keygen_info_destroy(struct KeygenPeerInfo *info)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_CRYPTO_EddsaSignature signature
Signature over rest of the message.
messages used for the secretsharing api
static gcry_mpi_t keygen_reveal_get_exp_coeff(struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
int GNUNET_CRYPTO_eddsa_sign(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:989
#define GNUNET_SECRETSHARING_ELGAMAL_Q_HEX
The q-parameter for ElGamal encryption, a 1023-bit Sophie Germain prime, q = (p-1)/2.
void GNUNET_CRYPTO_mpi_print_unsigned(void *buf, size_t size, gcry_mpi_t val)
Output the given MPI value to the given buffer in network byte order.
Definition: crypto_mpi.c:75
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT
Request the decryption of a ciphertext.
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
static struct Experiment * e
struct GNUNET_CRYPTO_PaillierPublicKey pubkey
Ephemeral paillier public key used by &#39;peer&#39; for this session.
A share, with all values in in host byte order.
struct GNUNET_PeerIdentity peer
Identity of the peer.
gcry_mpi_t my_share
Share of our peer.
static struct GNUNET_HashCode session_id
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static void decrypt_new_element(void *cls, const struct GNUNET_SET_Element *element)
Called when a new partial decryption arrives.
struct GNUNET_TIME_Absolute start_time
When does the DKG start? Necessary to compute fractions of the operation&#39;s desired time interval...
char t1[GNUNET_SECRETSHARING_ELGAMAL_BITS/8]
Data of then element put in consensus for decrypting a value.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
unsigned int threshold
Minimum number of shares required to restore the secret.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_REQUEST.
void GNUNET_CONSENSUS_insert(struct GNUNET_CONSENSUS_Handle *consensus, const struct GNUNET_SET_Element *element, GNUNET_CONSENSUS_InsertDoneCallback idc, void *idc_cls)
Insert an element in the set being reconsiled.
static struct GNUNET_SCHEDULER_Task * t
Main task.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static void init_crypto_constants(void)
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
struct GNUNET_SECRETSHARING_FieldElement nizk_commit1
Commitment for the non-interactive zero knowledge proof.
uint64_t abs_value_us
The actual value.
gcry_mpi_t partial_decryption
Set to the partial decryption of this peer, or NULL if we did not receive a partial decryption from t...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
const void * data
Actual data of the element.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
void GNUNET_CRYPTO_paillier_create(struct GNUNET_CRYPTO_PaillierPublicKey *public_key, struct GNUNET_CRYPTO_PaillierPrivateKey *private_key)
Create a freshly generated paillier public key.
unsigned int local_peer
Index of the local peer.
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.
Handle to a client that is connected to a service.
Definition: service.c:249
int round2_valid
Did we successfully receive the round2 element of the peer?
static void get_fair_encryption_challenge(const struct GNUNET_SECRETSHARING_FairEncryption *fe, gcry_mpi_t *e)
#define GNUNET_SECRETSHARING_ELGAMAL_P_HEX
The q-parameter for ElGamal encryption, a 1024-bit safe prime.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
static void insert_decrypt_element(struct DecryptSession *ds)
static struct LoggingHandle * l
unsigned char bits[2048 *2/8]
The bits of the ciphertext.
gcry_mpi_t public_key
Public key, will be updated when a round2 element arrives.
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE
The service succeeded in decrypting a ciphertext.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
struct GNUNET_CONSENSUS_Handle * consensus
Current consensus, used for both DKG rounds.
#define GNUNET_memcpy(dst, src, n)
int GNUNET_CRYPTO_eddsa_verify(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:1116
struct GNUNET_TIME_AbsoluteNBO deadline
Deadline for the establishment of the crypto system.
Definition: secretsharing.h:67
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
static void decrypt_session_destroy(struct DecryptSession *ds)
Destroy a decrypt session, removing it from the linked list of decrypt sessions.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
struct DecryptSession * decrypt_session
Decrypt session of the client, if any.
static struct GNUNET_PeerIdentity my_peer
Peer that runs this service.
static void compute_lagrange_coefficient(gcry_mpi_t coeff, unsigned int j, unsigned int *indices, unsigned int num)
Get a the j-th lagrange coefficient for a set of indices.
static gcry_mpi_t elgamal_g
Generator for prime field of order &#39;elgamal_q&#39;.
static int verify_fair(const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, const struct GNUNET_SECRETSHARING_FairEncryption *fe)
Session to establish a threshold-shared secret.
static char buf[2048]
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
struct GNUNET_HashCode session_id
Identifier for this session.
gcry_mpi_t presecret_commitment
The peer&#39;s commitment to its presecret.
static struct GNUNET_PeerIdentity * normalize_peers(struct GNUNET_PeerIdentity *listed, unsigned int num_listed, unsigned int *num_normalized, unsigned int *my_peer_idx)
Normalize the given list of peers, by including the local peer (if it is missing) and sorting the pee...
static int result
Global testing status.
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE.
Definition: secretsharing.h:52
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_peer_private_key
Peer that runs this service.
static void handle_client_keygen(void *cls, const struct GNUNET_SECRETSHARING_CreateMessage *msg)
Functions with this signature are called whenever a message is received.
void GNUNET_CRYPTO_paillier_decrypt(const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key, const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext, gcry_mpi_t m)
Decrypt a paillier ciphertext with a private key.
int GNUNET_SECRETSHARING_share_write(const struct GNUNET_SECRETSHARING_Share *share, void *buf, size_t buflen, size_t *writelen)
Convert a share to its binary representation.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
static struct GNUNET_SECRETSHARING_Ciphertext ciphertext
static gcry_mpi_t elgamal_p
Modulus of the prime field used for ElGamal.
unsigned int local_peer_idx
Index of the local peer in the ordered list of peers in the session.
struct GNUNET_HashCode commitment
Commitment of &#39;peer&#39; to its presecret.
A 512-bit hashcode.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2618
struct GNUNET_TIME_AbsoluteNBO deadline
Until when should the decryption be finished?
char t2[GNUNET_CRYPTO_PAILLIER_BITS *2/8]
uint16_t threshold
Mininum number of cooperating peers to decrypt a value.
Definition: secretsharing.h:73
static int res
uint32_t c1_bits[1024/8/sizeof(uint32_t)]
struct GNUNET_CRYPTO_PaillierPublicKey paillier_public_key
The peer&#39;s paillier public key.
static void restore_fair(const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, const struct GNUNET_SECRETSHARING_FairEncryption *fe, gcry_mpi_t x, gcry_mpi_t xres)
void GNUNET_CRYPTO_mpi_scan_unsigned(gcry_mpi_t *result, const void *data, size_t size)
Convert data buffer into MPI value.
Definition: crypto_mpi.c:128
static struct GNUNET_TIME_Absolute start_time
Start time of the current round; used to determine how long one iteration takes (which influences how...
static void keygen_session_destroy(struct KeygenSession *ks)
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Signature purpose for signing the keygen commit data.
unsigned int num_peers
Total number of peers.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
struct KeygenSession * keygen_session
Keygen session of the client, if any.
static void keygen_round2_new_element(void *cls, const struct GNUNET_SET_Element *element)
struct GNUNET_CRYPTO_PaillierPrivateKey paillier_private_key
Paillier private key of our peer.
struct DecryptPeerInfo * info
State information about other peers.
struct ClientState * cs
Which client is this for?
struct GNUNET_SECRETSHARING_FieldElement nizk_response
Reponse to the challenge computed from the protocol transcript.
struct GNUNET_TIME_AbsoluteNBO start
Until when should the decryption start?
struct GNUNET_CONSENSUS_Handle * consensus
Handle to the consensus over partial decryptions.
static struct GNUNET_SECRETSHARING_FairEncryption * keygen_reveal_get_enc_preshare(struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
static void encrypt_fair(gcry_mpi_t v, const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, struct GNUNET_SECRETSHARING_FairEncryption *fe)
Create a fair Paillier encryption of then given ciphertext.
static unsigned int num_peers
struct KeygenPeerInfo * info
Information about all participating peers.
static int check_client_decrypt(void *cls, const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg)
Check that msg is well-formed.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
Info about a peer in a key generation session.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initialize secretsharing service.
static struct GNUNET_TIME_Absolute time_between(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end, int num, int denum)
Interpolate between two points in time.
char z[GNUNET_SECRETSHARING_ELGAMAL_BITS/8]
struct GNUNET_TIME_Absolute deadline
When would we like the key to be established?
Handle to a message queue.
Definition: mq.c:85
unsigned int original_index
Original index in the key generation round.
Private ECC key encoded for transmission.
struct GNUNET_TIME_Absolute deadline
When would we like the ciphertext to be decrypted?
static void handle_client_decrypt(void *cls, const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg)
Functions with this signature are called whenever a message is received.
The identity of the host (wraps the signing key of the peer).
static void keygen_round1_new_element(void *cls, const struct GNUNET_SET_Element *element)
Consensus element handler for round one.
uint32_t success
Zero if decryption failed, non-zero if decryption succeeded.
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.
configuration data
Definition: configuration.c:85
struct GNUNET_PeerIdentity peer
Peer that inserts this element.
struct GNUNET_SERVICE_Client * client
Client this is about.
gcry_mpi_t * presecret_polynomial
Randomly generated coefficients of the polynomial for sharing our pre-secret, where &#39;preshares[0]&#39; is...
struct GNUNET_SECRETSHARING_FieldElement * sigmas
uint16_t my_peer
Index of our peer in the list.
uint16_t size
Number of bytes in the buffer pointed to by data.
struct GNUNET_PeerIdentity * peers
List of all peers involved in the secret sharing session.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
void GNUNET_CONSENSUS_conclude(struct GNUNET_CONSENSUS_Handle *consensus, GNUNET_CONSENSUS_ConcludeCallback conclude, void *conclude_cls)
We are done with inserting new elements into the consensus; try to conclude the consensus within a gi...
struct GNUNET_PeerIdentity peer
Peer identity of the peer.
int GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host&#39;s peer.
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION
Signature for cooperatice decryption.
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer&#39;s key from the file specified in the configuration...
uint16_t num_peers
Number of peers at the end of this message.
Definition: secretsharing.h:78
Handle for the service.
Definition: consensus_api.c:40
static struct GNUNET_TIME_Absolute deadline
Deadline for all consensuses.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY
The cryptosystem has been established.
#define GNUNET_YES
Definition: gnunet_common.h:80
static struct GNUNET_FS_DirScanner * ds
Handle to the directory scanner (for recursive insertions).
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
struct GNUNET_CONSENSUS_Handle * GNUNET_CONSENSUS_create(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, const struct GNUNET_PeerIdentity *peers, const struct GNUNET_HashCode *session_id, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, GNUNET_CONSENSUS_ElementCallback new_element_cb, void *new_element_cls)
Create a consensus session.
gcry_mpi_t sigma
Sigma (exponentiated share) for this peer.
char w[GNUNET_CRYPTO_PAILLIER_BITS/8]
static float beta
Percentage of total peer number in the view to send random PULLs to.
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE
Establish a new session.
struct GNUNET_TIME_Absolute start
When should we start communicating for decryption?
uint16_t num_peers
Peers that have the share.
static gcry_mpi_t elgamal_q
The ElGamal prime field order as libgcrypt mpi.
struct GNUNET_SECRETSHARING_PublicKey public_key
Public key.
#define GNUNET_CRYPTO_PAILLIER_BITS
Size of paillier plain texts and public keys.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
uint32_t c2_bits[1024/8/sizeof(uint32_t)]
static void cleanup_task(void *cls)
Task run during shutdown.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
GNUNET_SERVICE_MAIN("secretsharing", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(client_keygen, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, struct GNUNET_SECRETSHARING_CreateMessage, NULL), GNUNET_MQ_hd_var_size(client_decrypt, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, struct GNUNET_SECRETSHARING_DecryptRequestMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2
Signature for the second round of distributed key generation.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2533
struct ClientState * cs
Which client is this for?
struct GNUNET_SECRETSHARING_FieldElement partial_decryption
Partial decryption, computed as c_1^{s_i}.
static void horner_eval(gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
Evaluate the polynomial with coefficients coeff at x.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_malloc(size)
Wrapper around malloc.
Notify the client that then threshold secret has been established.
struct GNUNET_SECRETSHARING_FieldElement nizk_commit2
Commitment for the non-interactive zero knowledge proof.
Session to cooperatively decrypt a value.
#define GNUNET_free(ptr)
Wrapper around free.
static int check_client_keygen(void *cls, const struct GNUNET_SECRETSHARING_CreateMessage *msg)
Check that msg is well-formed.
Consensus element data used in the first round of key generation.
uint16_t element_type
Application-specific element type.
struct GNUNET_CRYPTO_PaillierCiphertext c
struct GNUNET_CRYPTO_EddsaPublicKey public_key
#define GNUNET_SECRETSHARING_ELGAMAL_BITS
Number of bits for secretsharing elements.