GNUnet  0.11.x
gnunet-service-scalarproduct_bob.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013, 2014, 2016 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  */
26 #include "platform.h"
27 #include <limits.h>
28 #include <gcrypt.h>
29 #include "gnunet_util_lib.h"
30 #include "gnunet_core_service.h"
31 #include "gnunet_cadet_service.h"
32 #include "gnunet_applications.h"
33 #include "gnunet_protocols.h"
35 #include "gnunet_set_service.h"
36 #include "scalarproduct.h"
38 
39 #define LOG(kind, ...) GNUNET_log_from (kind, "scalarproduct-bob", __VA_ARGS__)
40 
41 
45 struct MpiElement
46 {
52  const struct GNUNET_HashCode *key;
53 
57  gcry_mpi_t value;
58 };
59 
60 
65 struct BobServiceSession
66 {
70  struct GNUNET_HashCode session_id;
71 
75  struct GNUNET_SERVICE_Client *client;
76 
80  struct GNUNET_MQ_Handle *client_mq;
81 
85  struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
86 
91  struct GNUNET_SET_Handle *intersection_set;
92 
97  struct GNUNET_SET_OperationHandle *intersection_op;
98 
102  struct GNUNET_CADET_Port *port;
103 
107  struct MpiElement *sorted_elements;
108 
113 
118 
123 
128 
133 
138  struct CadetIncomingSession *cadet;
139 
143  uint32_t total;
144 
149  uint32_t client_received_element_count;
150 
156  uint32_t used_element_count;
157 
162  uint32_t cadet_received_element_count;
163 
169 
177 
181  int in_destroy;
182 
186  struct GNUNET_CADET_Channel *channel;
187 
191  struct GNUNET_PeerIdentity peer;
192 
196  struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey;
197 
201  struct GNUNET_MQ_Handle *cadet_mq;
202 };
203 
204 
208 static const struct GNUNET_CONFIGURATION_Handle *cfg;
209 
214 
219 
223 static gcry_mpi_t my_offset;
224 
229 
230 
238 static int
239 free_element_cb (void *cls,
240  const struct GNUNET_HashCode *key,
241  void *value)
242 {
243  struct GNUNET_SCALARPRODUCT_Element *element = value;
244 
245  GNUNET_free (element);
246  return GNUNET_OK;
247 }
248 
249 
255 static void
257 {
258  unsigned int i;
259 
260  if (GNUNET_YES == s->in_destroy)
261  return;
262  s->in_destroy = GNUNET_YES;
263  if (NULL != s->client)
264  {
265  struct GNUNET_SERVICE_Client *c = s->client;
266 
267  s->client = NULL;
269  }
270  if (NULL != s->intersected_elements)
271  {
274  NULL);
276  s->intersected_elements = NULL;
277  }
278  if (NULL != s->intersection_op)
279  {
281  s->intersection_op = NULL;
282  }
283  if (NULL != s->intersection_set)
284  {
286  s->intersection_set = NULL;
287  }
288  if (NULL != s->e_a)
289  {
290  GNUNET_free (s->e_a);
291  s->e_a = NULL;
292  }
293  if (NULL != s->sorted_elements)
294  {
295  for (i = 0; i < s->used_element_count; i++)
296  gcry_mpi_release (s->sorted_elements[i].value);
298  s->sorted_elements = NULL;
299  }
300  if (NULL != s->r)
301  {
302  GNUNET_free (s->r);
303  s->r = NULL;
304  }
305  if (NULL != s->r_prime)
306  {
307  GNUNET_free (s->r_prime);
308  s->r_prime = NULL;
309  }
310  if (NULL != s->port)
311  {
313  s->port = NULL;
314  }
315  if (NULL != s->channel)
316  {
318  s->channel = NULL;
319  }
320  GNUNET_free (s);
321 }
322 
323 
331 static void
333 {
334  struct ClientResponseMessage *msg;
335  struct GNUNET_MQ_Envelope *e;
336 
337  if (NULL == session->client_mq)
338  return; /* no client left to be notified */
340  "Sending session-end notification with status %d to client for session %s\n",
341  session->status,
342  GNUNET_h2s (&session->session_id));
343  e = GNUNET_MQ_msg (msg,
345  msg->range = 0;
346  msg->product_length = htonl (0);
347  msg->status = htonl (session->status);
348  GNUNET_MQ_send (session->client_mq,
349  e);
350 }
351 
352 
362 static void
364  const struct GNUNET_CADET_Channel *channel)
365 {
366  struct BobServiceSession *s = cls;
367 
369  "Peer disconnected, terminating session %s with peer %s\n",
370  GNUNET_h2s (&s->session_id),
371  GNUNET_i2s (&s->peer));
373  {
376  }
377  s->channel = NULL;
379 }
380 
381 
386 static void
387 bob_cadet_done_cb (void *cls)
388 {
389  struct BobServiceSession *session = cls;
390 
393 }
394 
395 
399 #define ELEMENT_CAPACITY ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 \
400  - sizeof(struct BobCryptodataMultipartMessage)) \
401  / sizeof(struct \
402  GNUNET_CRYPTO_PaillierCiphertext))
403 
404 
411 static void
413 {
416  struct GNUNET_MQ_Envelope *e;
417  unsigned int i;
418  unsigned int j;
419  uint32_t todo_count;
420 
422  {
424  if (todo_count > ELEMENT_CAPACITY / 2)
425  todo_count = ELEMENT_CAPACITY / 2;
426 
428  "Sending %u additional crypto values to Alice\n",
429  (unsigned int) todo_count);
430  e = GNUNET_MQ_msg_extra (msg,
431  todo_count * sizeof(struct
433  * 2,
435  msg->contained_element_count = htonl (todo_count);
436  payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
437  for (i = s->cadet_transmitted_element_count, j = 0; i <
438  s->cadet_transmitted_element_count + todo_count; i++)
439  {
440  // r[i][p] and r[i][q]
441  GNUNET_memcpy (&payload[j++],
442  &s->r[i],
443  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
444  GNUNET_memcpy (&payload[j++],
445  &s->r_prime[i],
446  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
447  }
448  s->cadet_transmitted_element_count += todo_count;
452  s);
454  e);
455  }
457  "All values queued for Alice, Bob is done\n");
458 }
459 
460 
472 static void
474 {
475  struct BobCryptodataMessage *msg;
476  struct GNUNET_MQ_Envelope *e;
478  unsigned int i;
479 
481  = ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 - sizeof(struct
483  / sizeof(struct GNUNET_CRYPTO_PaillierCiphertext) / 2) - 1;
486 
487  e = GNUNET_MQ_msg_extra (msg,
489  * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext),
492 
494  "Sending %u/%u crypto values to Alice\n",
495  (unsigned int) s->cadet_transmitted_element_count,
496  (unsigned int) s->used_element_count);
497 
498  payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
499  GNUNET_memcpy (&payload[0],
500  &s->s,
501  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
502  GNUNET_memcpy (&payload[1],
503  &s->s_prime,
504  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
505 
506  payload = &payload[2];
507  // convert k[][]
508  for (i = 0; i < s->cadet_transmitted_element_count; i++)
509  {
510  // k[i][p] and k[i][q]
511  GNUNET_memcpy (&payload[i * 2],
512  &s->r[i],
513  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
514  GNUNET_memcpy (&payload[i * 2 + 1],
515  &s->r_prime[i],
516  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
517  }
521  s);
523  e);
525 }
526 
527 
528 #undef ELEMENT_CAPACITY
529 
530 
539 static gcry_mpi_t
540 compute_square_sum (const gcry_mpi_t *vector,
541  uint32_t length)
542 {
543  gcry_mpi_t elem;
544  gcry_mpi_t sum;
545  uint32_t i;
546 
547  GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
548  GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
549  for (i = 0; i < length; i++)
550  {
551  gcry_mpi_mul (elem, vector[i], vector[i]);
552  gcry_mpi_add (sum, sum, elem);
553  }
554  gcry_mpi_release (elem);
555  return sum;
556 }
557 
558 
569 static int
571 {
572  uint32_t i;
573  unsigned int *p;
574  unsigned int *q;
575  uint32_t count;
576  gcry_mpi_t *rand;
577  gcry_mpi_t tmp;
578  const struct MpiElement *b;
581  struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
582 
583  count = session->used_element_count;
584  a = session->e_a;
585  b = session->sorted_elements;
587  count);
589  count);
590  rand = GNUNET_malloc (sizeof(gcry_mpi_t) * count);
591  for (i = 0; i < count; i++)
592  GNUNET_assert (NULL != (rand[i] = gcry_mpi_new (0)));
593  r = GNUNET_malloc (sizeof(struct GNUNET_CRYPTO_PaillierCiphertext) * count);
594  r_prime = GNUNET_malloc (sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)
595  * count);
596 
597  for (i = 0; i < count; i++)
598  {
599  int32_t svalue;
600 
602  UINT32_MAX);
603  // long to gcry_mpi_t
604  if (svalue < 0)
605  gcry_mpi_sub_ui (rand[i],
606  rand[i],
607  -svalue);
608  else
609  rand[i] = gcry_mpi_set_ui (rand[i], svalue);
610  }
611 
612  tmp = gcry_mpi_new (0);
613  // encrypt the element
614  // for the sake of readability I decided to have dedicated permutation
615  // vectors, which get rid of all the lookups in p/q.
616  // however, ap/aq are not absolutely necessary but are just abstraction
617  // Calculate Kp = E(S + a_pi) (+) E(S - r_pi - b_pi)
618  for (i = 0; i < count; i++)
619  {
620  // E(S - r_pi - b_pi)
621  gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
622  gcry_mpi_sub (tmp, tmp, b[p[i]].value);
623  GNUNET_assert (2 ==
625  tmp,
626  2,
627  &r[i]));
628 
629  // E(S - r_pi - b_pi) * E(S + a_pi) == E(2*S + a - r - b)
630  if (GNUNET_OK !=
632  &r[i],
633  &a[p[i]],
634  &r[i]))
635  {
636  GNUNET_break_op (0);
637  goto error_cleanup;
638  }
639  }
640 
641  // Calculate Kq = E(S + a_qi) (+) E(S - r_qi)
642  for (i = 0; i < count; i++)
643  {
644  // E(S - r_qi)
645  gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
646  GNUNET_assert (2 ==
648  tmp,
649  2,
650  &r_prime[i]));
651 
652  // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
653  if (GNUNET_OK !=
655  &r_prime[i],
656  &a[q[i]],
657  &r_prime[i]))
658  {
659  GNUNET_break_op (0);
660  goto error_cleanup;
661  }
662  }
663  gcry_mpi_release (tmp);
664 
665  // Calculate S' = E(SUM( r_i^2 ))
666  tmp = compute_square_sum (rand, count);
667  GNUNET_assert (1 ==
669  tmp,
670  1,
671  &session->s_prime));
672  gcry_mpi_release (tmp);
673 
674  // Calculate S = E(SUM( (r_i + b_i)^2 ))
675  for (i = 0; i < count; i++)
676  gcry_mpi_add (rand[i], rand[i], b[i].value);
677  tmp = compute_square_sum (rand, count);
678  GNUNET_assert (1 ==
680  tmp,
681  1,
682  &session->s));
683  gcry_mpi_release (tmp);
684 
685  session->r = r;
686  session->r_prime = r_prime;
687 
688  for (i = 0; i < count; i++)
689  gcry_mpi_release (rand[i]);
690  GNUNET_free (session->e_a);
691  session->e_a = NULL;
692  GNUNET_free (p);
693  GNUNET_free (q);
694  GNUNET_free (rand);
695  return GNUNET_OK;
696 
697 error_cleanup:
698  GNUNET_free (r);
699  GNUNET_free (r_prime);
700  gcry_mpi_release (tmp);
701  GNUNET_free (p);
702  GNUNET_free (q);
703  for (i = 0; i < count; i++)
704  gcry_mpi_release (rand[i]);
705  GNUNET_free (rand);
706  return GNUNET_SYSERR;
707 }
708 
709 
719 static int
720 copy_element_cb (void *cls,
721  const struct GNUNET_HashCode *key,
722  void *value)
723 {
724  struct BobServiceSession *s = cls;
726  gcry_mpi_t mval;
727  int64_t val;
728 
729  mval = gcry_mpi_new (0);
730  val = (int64_t) GNUNET_ntohll (e->value);
731  if (0 > val)
732  gcry_mpi_sub_ui (mval, mval, -val);
733  else
734  gcry_mpi_add_ui (mval, mval, val);
737  s->used_element_count++;
738  return GNUNET_OK;
739 }
740 
741 
750 static int
751 element_cmp (const void *a,
752  const void *b)
753 {
754  const struct MpiElement *ma = a;
755  const struct MpiElement *mb = b;
756 
757  return GNUNET_CRYPTO_hash_cmp (ma->key,
758  mb->key);
759 }
760 
761 
769 static void
771 {
772  struct GNUNET_CADET_Channel *channel;
773 
774  /* TODO: code duplication with Alice! */
776  "Received everything, building reply for Alice\n");
777  s->sorted_elements
780  * sizeof(struct MpiElement));
781  s->used_element_count = 0;
784  s);
785  qsort (s->sorted_elements,
787  sizeof(struct MpiElement),
788  &element_cmp);
789  if (GNUNET_OK !=
791  {
792  channel = s->channel;
793  s->channel = NULL;
795  return;
796  }
798 }
799 
800 
810 static int
812  const struct AliceCryptodataMessage *msg)
813 {
814  struct BobServiceSession *s = cls;
815  uint32_t contained_elements;
816  size_t msg_length;
817  uint16_t msize;
818  unsigned int max;
819 
820  msize = ntohs (msg->header.size);
821  contained_elements = ntohl (msg->contained_element_count);
822  /* Our intersection may still be ongoing, but this is nevertheless
823  an upper bound on the required array size */
825  msg_length = sizeof(struct AliceCryptodataMessage)
826  + contained_elements * sizeof(struct
828  if ((msize != msg_length) ||
829  (0 == contained_elements) ||
830  (contained_elements > UINT16_MAX) ||
831  (max < contained_elements + s->cadet_received_element_count))
832  {
833  GNUNET_break_op (0);
834  return GNUNET_SYSERR;
835  }
836  return GNUNET_OK;
837 }
838 
839 
847 static void
849  const struct AliceCryptodataMessage *msg)
850 {
851  struct BobServiceSession *s = cls;
853  uint32_t contained_elements;
854  unsigned int max;
855 
856  contained_elements = ntohl (msg->contained_element_count);
857  /* Our intersection may still be ongoing, but this is nevertheless
858  an upper bound on the required array size */
861  "Received %u crypto values from Alice\n",
862  (unsigned int) contained_elements);
863 
864  payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
865  if (NULL == s->e_a)
866  s->e_a = GNUNET_new_array (max,
869  payload,
870  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)
871  * contained_elements);
872  s->cadet_received_element_count += contained_elements;
873 
874  if ((s->cadet_received_element_count == max) &&
875  (NULL == s->intersection_op))
876  {
877  /* intersection has finished also on our side, and
878  we got the full set, so we can proceed with the
879  CADET response(s) */
881  }
883 }
884 
885 
895 static void
897  const struct GNUNET_SET_Element *element,
898  uint64_t current_size,
900 {
901  struct BobServiceSession *s = cls;
902  struct GNUNET_SCALARPRODUCT_Element *se;
903 
904  switch (status)
905  {
907  /* this element has been removed from the set */
909  element->data);
910  GNUNET_assert (NULL != se);
912  "Removed element with key %s and value %lld\n",
913  GNUNET_h2s (&se->key),
914  (long long) GNUNET_ntohll (se->value));
918  element->data,
919  se));
920  GNUNET_free (se);
921  return;
922 
924  s->intersection_op = NULL;
925  GNUNET_break (NULL == s->intersection_set);
928  "Finished intersection, %d items remain\n",
932  {
933  /* CADET transmission from Alice is also already done,
934  start with our own reply */
936  }
937  return;
938 
940  /* unexpected for intersection */
941  GNUNET_break (0);
942  return;
943 
945  /* unhandled status code */
947  "Set intersection failed!\n");
948  s->intersection_op = NULL;
949  if (NULL != s->intersection_set)
950  {
952  s->intersection_set = NULL;
953  }
956  return;
957 
958  default:
959  GNUNET_break (0);
960  return;
961  }
962 }
963 
964 
971 static void
973 {
975  "Got session with key %s and %u elements, starting intersection.\n",
976  GNUNET_h2s (&s->session_id),
977  (unsigned int) s->total);
978 
979  s->intersection_op
980  = GNUNET_SET_prepare (&s->peer,
981  &s->session_id,
982  NULL,
984  (struct GNUNET_SET_Option[]) { { 0 } },
986  s);
987  if (GNUNET_OK !=
988  GNUNET_SET_commit (s->intersection_op,
989  s->intersection_set))
990  {
991  GNUNET_break (0);
994  return;
995  }
996  GNUNET_SET_destroy (s->intersection_set);
997  s->intersection_set = NULL;
998 }
999 
1000 
1007 static void
1009  const struct ServiceRequestMessage *msg)
1010 {
1011  struct BobServiceSession *s = cls;
1012 
1013  s->session_id = msg->session_id; // ??
1014  s->remote_pubkey = msg->public_key;
1015  if (s->client_received_element_count == s->total)
1016  start_intersection (s);
1017 }
1018 
1019 
1030 static void *
1032  struct GNUNET_CADET_Channel *channel,
1033  const struct GNUNET_PeerIdentity *initiator)
1034 {
1035  struct BobServiceSession *s = cls;
1036 
1038  "New incoming channel from peer %s.\n",
1039  GNUNET_i2s (initiator));
1041  s->port = NULL;
1042  s->channel = channel;
1043  s->peer = *initiator;
1045  return s;
1046 }
1047 
1048 
1056 static int
1058  const struct
1060  msg)
1061 {
1062  struct BobServiceSession *s = cls;
1063  uint32_t contained_count;
1064  uint16_t msize;
1065 
1066  msize = ntohs (msg->header.size);
1067  contained_count = ntohl (msg->element_count_contained);
1068  if ((msize != (sizeof(struct ComputationBobCryptodataMultipartMessage)
1069  + contained_count * sizeof(struct
1071  (0 == contained_count) ||
1072  (UINT16_MAX < contained_count) ||
1073  (s->total == s->client_received_element_count) ||
1074  (s->total < s->client_received_element_count + contained_count))
1075  {
1076  GNUNET_break (0);
1077  return GNUNET_SYSERR;
1078  }
1079  return GNUNET_OK;
1080 }
1081 
1082 
1090 static void
1092  const struct
1094  msg)
1095 {
1096  struct BobServiceSession *s = cls;
1097  uint32_t contained_count;
1098  const struct GNUNET_SCALARPRODUCT_Element *elements;
1099  struct GNUNET_SET_Element set_elem;
1100  struct GNUNET_SCALARPRODUCT_Element *elem;
1101 
1102  contained_count = ntohl (msg->element_count_contained);
1103  elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1104  for (uint32_t i = 0; i < contained_count; i++)
1105  {
1106  elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1107  GNUNET_memcpy (elem,
1108  &elements[i],
1109  sizeof(struct GNUNET_SCALARPRODUCT_Element));
1110  if (GNUNET_SYSERR ==
1112  &elem->key,
1113  elem,
1115  {
1116  GNUNET_break (0);
1117  GNUNET_free (elem);
1118  continue;
1119  }
1120  set_elem.data = &elem->key;
1121  set_elem.size = sizeof(elem->key);
1122  set_elem.element_type = 0;
1124  &set_elem,
1125  NULL, NULL);
1126  }
1127  s->client_received_element_count += contained_count;
1129  if (s->total != s->client_received_element_count)
1130  {
1131  /* more to come */
1132  return;
1133  }
1134  if (NULL == s->channel)
1135  {
1136  /* no Alice waiting for this request, wait for Alice */
1137  return;
1138  }
1139  start_intersection (s);
1140 }
1141 
1142 
1151 static int
1153  const struct BobComputationMessage *msg)
1154 {
1155  struct BobServiceSession *s = cls;
1156  uint32_t contained_count;
1157  uint32_t total_count;
1158  uint16_t msize;
1159 
1161  {
1162  GNUNET_break (0);
1163  return GNUNET_SYSERR;
1164  }
1165  msize = ntohs (msg->header.size);
1166  total_count = ntohl (msg->element_count_total);
1167  contained_count = ntohl (msg->element_count_contained);
1168  if ((0 == total_count) ||
1169  (0 == contained_count) ||
1170  (UINT16_MAX < contained_count) ||
1171  (msize != (sizeof(struct BobComputationMessage)
1172  + contained_count * sizeof(struct
1174  {
1175  GNUNET_break_op (0);
1176  return GNUNET_SYSERR;
1177  }
1178  return GNUNET_OK;
1179 }
1180 
1181 
1190 static void
1192  const struct BobComputationMessage *msg)
1193 {
1194  struct BobServiceSession *s = cls;
1195  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1196  GNUNET_MQ_hd_fixed_size (alices_computation_request,
1198  struct ServiceRequestMessage,
1199  NULL),
1200  GNUNET_MQ_hd_var_size (alices_cryptodata_message,
1202  struct AliceCryptodataMessage,
1203  NULL),
1205  };
1206  uint32_t contained_count;
1207  uint32_t total_count;
1208  const struct GNUNET_SCALARPRODUCT_Element *elements;
1209  struct GNUNET_SET_Element set_elem;
1210  struct GNUNET_SCALARPRODUCT_Element *elem;
1211 
1212  total_count = ntohl (msg->element_count_total);
1213  contained_count = ntohl (msg->element_count_contained);
1214 
1216  s->total = total_count;
1217  s->client_received_element_count = contained_count;
1218  s->session_id = msg->session_key;
1219  elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1222  GNUNET_YES);
1223  s->intersection_set
1224  = GNUNET_SET_create (cfg,
1226  for (uint32_t i = 0; i < contained_count; i++)
1227  {
1228  if (0 == GNUNET_ntohll (elements[i].value))
1229  continue;
1230  elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1231  GNUNET_memcpy (elem,
1232  &elements[i],
1233  sizeof(struct GNUNET_SCALARPRODUCT_Element));
1234  if (GNUNET_SYSERR ==
1236  &elem->key,
1237  elem,
1239  {
1240  GNUNET_break (0);
1241  GNUNET_free (elem);
1242  continue;
1243  }
1244  set_elem.data = &elem->key;
1245  set_elem.size = sizeof(elem->key);
1246  set_elem.element_type = 0;
1248  &set_elem,
1249  NULL, NULL);
1250  s->used_element_count++;
1251  }
1253  /* We're ready, open the port */
1254  s->port = GNUNET_CADET_open_port (my_cadet,
1255  &msg->session_key,
1257  s,
1258  NULL,
1260  cadet_handlers);
1261  if (NULL == s->port)
1262  {
1263  GNUNET_break (0);
1265  return;
1266  }
1267 }
1268 
1269 
1275 static void
1276 shutdown_task (void *cls)
1277 {
1279  "Shutting down, initiating cleanup.\n");
1280  // FIXME: we have to cut our connections to CADET first!
1281  if (NULL != my_cadet)
1282  {
1283  GNUNET_CADET_disconnect (my_cadet);
1284  my_cadet = NULL;
1285  }
1286 }
1287 
1288 
1299 static void *
1301  struct GNUNET_SERVICE_Client *client,
1302  struct GNUNET_MQ_Handle *mq)
1303 {
1304  struct BobServiceSession *s;
1305 
1306  s = GNUNET_new (struct BobServiceSession);
1307  s->client = client;
1308  s->client_mq = mq;
1309  return s;
1310 }
1311 
1312 
1323 static void
1325  struct GNUNET_SERVICE_Client *client,
1326  void *app_cls)
1327 {
1328  struct BobServiceSession *s = app_cls;
1329 
1331  "Client disconnected from us.\n");
1332  s->client = NULL;
1334 }
1335 
1336 
1344 static void
1345 run (void *cls,
1346  const struct GNUNET_CONFIGURATION_Handle *c,
1348 {
1349  cfg = c;
1350  /*
1351  offset has to be sufficiently small to allow computation of:
1352  m1+m2 mod n == (S + a) + (S + b) mod n,
1353  if we have more complex operations, this factor needs to be lowered */
1354  my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1355  gcry_mpi_set_bit (my_offset,
1357 
1359  &my_privkey);
1360  my_cadet = GNUNET_CADET_connect (cfg);
1362  NULL);
1363  if (NULL == my_cadet)
1364  {
1366  _ ("Connect to CADET failed\n"));
1368  return;
1369  }
1370 }
1371 
1372 
1377  ("scalarproduct-bob",
1379  &run,
1382  NULL,
1383  GNUNET_MQ_hd_var_size (bob_client_message,
1385  struct BobComputationMessage,
1386  NULL),
1387  GNUNET_MQ_hd_var_size (bob_client_message_multipart,
1390  NULL),
1392 
1393 
1394 /* end of gnunet-service-scalarproduct_bob.c */
Message type passed from service client to finalize a session as requester or responder.
GNUNET_SERVICE_MAIN("scalarproduct-bob", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(bob_client_message, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB, struct BobComputationMessage, NULL), GNUNET_MQ_hd_var_size(bob_client_message_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB, struct ComputationBobCryptodataMultipartMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
int in_destroy
Are we already in destroy_service_session()?
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:841
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
uint32_t client_received_element_count
Already transferred elements (received) for multipart messages from client.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_CRYPTO_PaillierPublicKey public_key
Alice&#39;s public key.
struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey
Public key of the remote service.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
unsigned int * GNUNET_CRYPTO_random_permute(enum GNUNET_CRYPTO_Quality mode, unsigned int n)
Get an array with a random permutation of the numbers 0...n-1.
int GNUNET_SET_add_element(struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls)
Add an element to the given set.
Definition: set_api.c:687
static int check_bob_client_message_multipart(void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
We&#39;re receiving additional set data.
Opaque handle to the service.
Definition: cadet_api.c:38
struct GNUNET_CRYPTO_PaillierCiphertext * e_a
E(ai)(Bob) after applying the mask.
uint32_t used_element_count
How many elements actually are used for the scalar product.
Handle to a service.
Definition: service.c:116
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION
Alice -> Bob session initialization.
uint32_t element_count_total
how many elements the vector in payload contains
Definition: scalarproduct.h:99
static gcry_mpi_t compute_square_sum(const gcry_mpi_t *vector, uint32_t length)
Computes the square sum over a vector of a given length.
struct GNUNET_MessageHeader header
GNUNET message header with type GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB.
Definition: scalarproduct.h:94
const struct GNUNET_HashCode * key
Key used to identify matching pairs of values to multiply.
Operation is still active (never returned, used internally).
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:1300
struct GNUNET_HashCode key
Key used to identify matching pairs of values to multiply.
static void prepare_client_end_notification(struct BobServiceSession *session)
Notify the client that the session has succeeded or failed.
enum GNUNET_SCALARPRODUCT_ResponseStatus status
State of this session.
Element stored in a set.
struct GNUNET_SET_Handle * GNUNET_SET_create(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op)
Create an empty set, supporting the specified operation.
Definition: set_api.c:657
struct GNUNET_CADET_Port * port
Our open port.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_MQ_Handle * client_mq
Client message queue.
int32_t range
Workaround for libgcrypt: -1 if negative, 0 if zero, else 1.
static void destroy_service_session(struct BobServiceSession *s)
Destroy session state, we are done with it.
static void cb_channel_destruction(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called whenever a channel is destroyed.
Message type passed from responding service Bob to responding service Alice to complete a request and...
static int copy_element_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator to copy over messages from the hash map into an array for sorting.
static const struct GNUNET_CONFIGURATION_Handle * cfg
GNUnet configuration handle.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initialization of the program and message handlers.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
struct GNUNET_SET_OperationHandle * intersection_op
Set of elements for which will conduction an intersection.
static struct Experiment * e
#define LOG(kind,...)
Opaque handle to a channel.
Definition: cadet_api.c:80
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static void transmit_bobs_cryptodata_message_multipart(struct BobServiceSession *s)
Send a multipart chunk of a service response from Bob to Alice.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_SET_OperationHandle * GNUNET_SET_prepare(const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Prepare a set operation to be evaluated with another peer.
Definition: set_api.c:813
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB
Client -> Bob.
struct MpiElement * sorted_elements
b(Bob)
static void transmit_bobs_cryptodata_message(struct BobServiceSession *s)
Bob generates the response message to be sent to Alice after computing the values (1)...
static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey
Service&#39;s own private key.
gcry_mpi_t value
a_i value, not disclosed to Bob.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
A scalarproduct session which tracks an offer for a multiplication service by a local client...
static void handle_alices_cryptodata_message(void *cls, const struct AliceCryptodataMessage *msg)
Handle a multipart-chunk of a request from another service to calculate a scalarproduct with us...
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:526
Success, all elements have been sent (and received).
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
const void * data
Actual data of the element.
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:976
void GNUNET_CRYPTO_paillier_create(struct GNUNET_CRYPTO_PaillierPublicKey *public_key, struct GNUNET_CRYPTO_PaillierPrivateKey *private_key)
Create a freshly generated paillier public key.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static void bob_cadet_done_cb(void *cls)
MQ finished giving our last message to CADET, now notify the client that we are finished.
Handle to a client that is connected to a service.
Definition: service.c:250
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:772
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected.
static int free_element_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
Callback used to free the elements in the map.
uint32_t status
Status information about the outcome of this session, An enum GNUNET_SCALARPRODUCT_ResponseStatus (in...
struct GNUNET_HashCode session_id
(hopefully) unique transaction ID
#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
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_cls)
A client disconnected.
uint32_t cadet_transmitted_element_count
Counts the number of values transmitted from us to Alice.
struct GNUNET_CADET_Port * GNUNET_CADET_open_port(struct GNUNET_CADET_Handle *h, const struct GNUNET_HashCode *port, GNUNET_CADET_ConnectEventHandler connects, void *connects_cls, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Open a port to receive incomming MQ-based channels.
Definition: cadet_api.c:1010
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_CRYPTO_PaillierCiphertext s_prime
Bob&#39;s "s&#39;".
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore...
Definition: mq.c:774
The other peer refused to to the operation with us, or something went wrong.
Success, all elements have been returned (but the other peer might still be receiving some from us...
Scalar Product API Message Types.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
Everything went ok, we are transmitting an element of the result (in set, or to be removed from set...
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
Operation is still active (never returned, used internally).
GNUNET_SET_Status
Status for the result callback.
static gcry_mpi_t my_offset
Service&#39;s offset for values that could possibly be negative but are plaintext for encryption...
Message type passed from requesting service Alice to responding service Bob to initiate a request and...
static int compute_service_response(struct BobServiceSession *session)
Compute the values (1)[]: $E_A(a_{pi(i)}) otimes E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)...
struct GNUNET_CADET_Channel * channel
The CADET channel.
uint16_t status
See PRISM_STATUS_*-constants.
static void * cb_channel_incoming(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
Function called for inbound channels on Bob&#39;s end.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
static struct GNUNET_CADET_Handle * my_cadet
Handle to the CADET service.
static void cb_intersection_element_removed(void *cls, const struct GNUNET_SET_Element *element, uint64_t current_size, enum GNUNET_SET_Status status)
Callback for set operation results.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA
Bob -> Alice SP crypto-data.
struct GNUNET_HashCode session_id
The transaction/session key used to identify a session.
struct GNUNET_SERVICE_Client * client
The client this request is related to.
struct GNUNET_CRYPTO_PaillierCiphertext s
Bob&#39;s "s".
int GNUNET_CRYPTO_paillier_hom_add(const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const struct GNUNET_CRYPTO_PaillierCiphertext *c1, const struct GNUNET_CRYPTO_PaillierCiphertext *c2, struct GNUNET_CRYPTO_PaillierCiphertext *result)
Compute a ciphertext that represents the sum of the plaintext in x1 and x2.
A 512-bit hashcode.
uint32_t total
How many elements will be supplied in total from the client.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2324
Message handler for a specific message type.
#define GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE
Maximum message size that can be sent on CADET.
Opaque handle to a set.
Definition: set_api.c:49
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
static void handle_bob_client_message(void *cls, const struct BobComputationMessage *msg)
Handler for Bob&#39;s a client request message.
static void start_intersection(struct BobServiceSession *s)
We&#39;ve paired up a client session with an incoming CADET request.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
Vector of Pallier-encrypted values sent by Alice to Bob (after set intersection). ...
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct CadetIncomingSession * cadet
Handle for our associated incoming CADET session, or NULL if we have not gotten one yet...
An encrypted element key-value pair.
scalarproduct service P2P messages
Multipart Message type passed between to supply additional elements for the peer. ...
static void transmit_cryptographic_reply(struct BobServiceSession *s)
Intersection operation and receiving data via CADET from Alice are both done, compute and transmit ou...
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA.
#define ELEMENT_CAPACITY
Maximum count of elements we can put into a multipart message.
uint32_t product_length
0 if no product attached
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART
Bob -> Alice SP crypto-data multipart.
static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey
Service&#39;s own public key.
Option for set operations.
int64_t value
Value to multiply in scalar product, in NBO.
struct GNUNET_SET_Handle * intersection_set
Set of elements for which we will be conducting an intersection.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static unsigned long long payload
How much data are we currently storing in the database?
uint32_t cadet_received_element_count
Counts the number of values received from Alice by us.
uint32_t element_count_contained
contained elements the vector in payload contains
Handle to an operation.
Definition: set_api.c:135
Handle to a message queue.
Definition: mq.c:85
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA
Alice -> Bob SP crypto-data (after intersection)
struct GNUNET_CONTAINER_MultiHashMap * intersected_elements
All non-0-value&#39;d elements transmitted to us.
The identity of the host (wraps the signing key of the peer).
int GNUNET_SET_commit(struct GNUNET_SET_OperationHandle *oh, struct GNUNET_SET_Handle *set)
Commit a set to be used with a set operation.
Definition: set_api.c:1128
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Send an ack on the channel to confirm the processing of a message.
Definition: cadet_api.c:954
static void handle_bob_client_message_multipart(void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
We&#39;re receiving additional set data.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
struct GNUNET_MessageHeader header
GNUNET message header.
configuration data
Definition: configuration.c:85
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
Definition: crypto_hash.c:294
static void handle_alices_computation_request(void *cls, const struct ServiceRequestMessage *msg)
Handle a request from Alice to calculate a scalarproduct with us (Bob).
static int element_cmp(const void *a, const void *b)
Compare two struct MpiValues by key for sorting.
static void shutdown_task(void *cls)
Task run during shutdown.
uint32_t contained_element_count
How many elements we supply within this message? In NBO.
uint16_t size
Number of bytes in the buffer pointed to by data.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB
Client -> Bob multipart.
Opaque handle to a port.
Definition: cadet_api.c:145
uint32_t contained_element_count
How many elements we appended to this message? In NBO.
Client gets only elements that have been removed from the set.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
uint32_t element_count_contained
contained elements the vector in payload contains
struct GNUNET_CRYPTO_PaillierCiphertext * r
Bob&#39;s permutation p of R.
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:516
multipart messages following struct ComputationMessage
Message type passed from client to service to initiate a request or responder role.
Definition: scalarproduct.h:88
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port().
Definition: cadet_api.c:874
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_HashCode session_key
the transaction/session key used to identify a session
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
Set intersection, only return elements that are in both sets.
struct GNUNET_PeerIdentity peer
Originator&#39;s peer identity.
uint32_t contained_element_count
How many elements this individual message delivers (in NBO).
GNUNET_SCALARPRODUCT_ResponseStatus
Result status values for the computation.
#define GNUNET_CRYPTO_PAILLIER_BITS
Size of paillier plain texts and public keys.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
static int check_bob_client_message(void *cls, const struct BobComputationMessage *msg)
Handler for Bob&#39;s a client request message.
struct GNUNET_MQ_Handle * cadet_mq
The message queue for this channel.
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:903
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
An element key-value pair for scalarproduct.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT
Alice/Bob -> Client Result.
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t element_type
Application-specific element type.
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected peer.
Definition: cadet_api.c:1119
int GNUNET_CRYPTO_paillier_encrypt(const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const gcry_mpi_t m, int desired_ops, struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext)
Encrypt a plaintext with a paillier public key.
struct GNUNET_CRYPTO_PaillierCiphertext * r_prime
Bob&#39;s permutation q of R.
static int check_alices_cryptodata_message(void *cls, const struct AliceCryptodataMessage *msg)
Check a multipart-chunk of a request from another service to calculate a scalarproduct with us...