GNUnet  0.10.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 {
67 
71  struct GNUNET_HashCode session_id;
72 
76  struct GNUNET_SERVICE_Client *client;
77 
81  struct GNUNET_MQ_Handle *client_mq;
82 
86  struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
87 
92  struct GNUNET_SET_Handle *intersection_set;
93 
98  struct GNUNET_SET_OperationHandle *intersection_op;
99 
103  struct GNUNET_CADET_Port *port;
104 
108  struct MpiElement *sorted_elements;
109 
114 
119 
124 
129 
134 
139  struct CadetIncomingSession *cadet;
140 
144  uint32_t total;
145 
150  uint32_t client_received_element_count;
151 
157  uint32_t used_element_count;
158 
163  uint32_t cadet_received_element_count;
164 
170 
178 
182  int in_destroy;
183 
187  struct GNUNET_CADET_Channel *channel;
188 
192  struct GNUNET_PeerIdentity peer;
193 
197  struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey;
198 
202  struct GNUNET_MQ_Handle *cadet_mq;
203 
204 };
205 
206 
207 
211 static const struct GNUNET_CONFIGURATION_Handle *cfg;
212 
217 
222 
226 static gcry_mpi_t my_offset;
227 
232 
233 
241 static int
242 free_element_cb (void *cls,
243  const struct GNUNET_HashCode *key,
244  void *value)
245 {
246  struct GNUNET_SCALARPRODUCT_Element *element = value;
247 
248  GNUNET_free (element);
249  return GNUNET_OK;
250 }
251 
252 
258 static void
260 {
261  unsigned int i;
262 
263  if (GNUNET_YES == s->in_destroy)
264  return;
265  s->in_destroy = GNUNET_YES;
266  if (NULL != s->client)
267  {
268  struct GNUNET_SERVICE_Client *c = s->client;
269 
270  s->client = NULL;
272  }
273  if (NULL != s->intersected_elements)
274  {
277  NULL);
279  s->intersected_elements = NULL;
280  }
281  if (NULL != s->intersection_op)
282  {
284  s->intersection_op = NULL;
285  }
286  if (NULL != s->intersection_set)
287  {
289  s->intersection_set = NULL;
290  }
291  if (NULL != s->e_a)
292  {
293  GNUNET_free (s->e_a);
294  s->e_a = NULL;
295  }
296  if (NULL != s->sorted_elements)
297  {
298  for (i=0;i<s->used_element_count;i++)
299  gcry_mpi_release (s->sorted_elements[i].value);
301  s->sorted_elements = NULL;
302  }
303  if (NULL != s->r)
304  {
305  GNUNET_free (s->r);
306  s->r = NULL;
307  }
308  if (NULL != s->r_prime)
309  {
310  GNUNET_free (s->r_prime);
311  s->r_prime = NULL;
312  }
313  if (NULL != s->port)
314  {
316  s->port = NULL;
317  }
318  if (NULL != s->channel)
319  {
321  s->channel = NULL;
322  }
323  GNUNET_free (s);
324 }
325 
326 
334 static void
336 {
337  struct ClientResponseMessage *msg;
338  struct GNUNET_MQ_Envelope *e;
339 
340  if (NULL == session->client_mq)
341  return; /* no client left to be notified */
343  "Sending session-end notification with status %d to client for session %s\n",
344  session->status,
345  GNUNET_h2s (&session->session_id));
346  e = GNUNET_MQ_msg (msg,
348  msg->range = 0;
349  msg->product_length = htonl (0);
350  msg->status = htonl (session->status);
351  GNUNET_MQ_send (session->client_mq,
352  e);
353 }
354 
355 
365 static void
367  const struct GNUNET_CADET_Channel *channel)
368 {
369  struct BobServiceSession *s = cls;
370 
372  "Peer disconnected, terminating session %s with peer %s\n",
373  GNUNET_h2s (&s->session_id),
374  GNUNET_i2s (&s->peer));
376  {
379  }
380  s->channel = NULL;
382 }
383 
384 
389 static void
390 bob_cadet_done_cb (void *cls)
391 {
392  struct BobServiceSession *session = cls;
393 
396 }
397 
398 
402 #define ELEMENT_CAPACITY ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 - sizeof (struct BobCryptodataMultipartMessage)) / sizeof (struct 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 GNUNET_CRYPTO_PaillierCiphertext) * 2,
433  msg->contained_element_count = htonl (todo_count);
434  payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
435  for (i = s->cadet_transmitted_element_count, j = 0; i < s->cadet_transmitted_element_count + todo_count; i++)
436  {
437  //r[i][p] and r[i][q]
438  GNUNET_memcpy (&payload[j++],
439  &s->r[i],
440  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
441  GNUNET_memcpy (&payload[j++],
442  &s->r_prime[i],
443  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
444  }
445  s->cadet_transmitted_element_count += todo_count;
449  s);
451  e);
452  }
454  "All values queued for Alice, Bob is done\n");
455 }
456 
457 
469 static void
471 {
472  struct BobCryptodataMessage *msg;
473  struct GNUNET_MQ_Envelope *e;
475  unsigned int i;
476 
479  / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) / 2) - 1;
482 
483  e = GNUNET_MQ_msg_extra (msg,
485  * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext),
488 
490  "Sending %u/%u crypto values to Alice\n",
491  (unsigned int) s->cadet_transmitted_element_count,
492  (unsigned int) s->used_element_count);
493 
494  payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
495  GNUNET_memcpy (&payload[0],
496  &s->s,
497  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
498  GNUNET_memcpy (&payload[1],
499  &s->s_prime,
500  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
501 
502  payload = &payload[2];
503  // convert k[][]
504  for (i = 0; i < s->cadet_transmitted_element_count; i++)
505  {
506  //k[i][p] and k[i][q]
507  GNUNET_memcpy (&payload[i * 2],
508  &s->r[i],
509  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
510  GNUNET_memcpy (&payload[i * 2 + 1],
511  &s->r_prime[i],
512  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
513  }
517  s);
519  e);
521 }
522 #undef ELEMENT_CAPACITY
523 
524 
533 static gcry_mpi_t
534 compute_square_sum (const gcry_mpi_t *vector,
535  uint32_t length)
536 {
537  gcry_mpi_t elem;
538  gcry_mpi_t sum;
539  uint32_t i;
540 
541  GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
542  GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
543  for (i = 0; i < length; i++)
544  {
545  gcry_mpi_mul (elem, vector[i], vector[i]);
546  gcry_mpi_add (sum, sum, elem);
547  }
548  gcry_mpi_release (elem);
549  return sum;
550 }
551 
552 
563 static int
565 {
566  uint32_t i;
567  unsigned int *p;
568  unsigned int *q;
569  uint32_t count;
570  gcry_mpi_t *rand;
571  gcry_mpi_t tmp;
572  const struct MpiElement *b;
575  struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
576 
577  count = session->used_element_count;
578  a = session->e_a;
579  b = session->sorted_elements;
581  count);
583  count);
584  rand = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
585  for (i = 0; i < count; i++)
586  GNUNET_assert (NULL != (rand[i] = gcry_mpi_new (0)));
587  r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
588  r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
589 
590  for (i = 0; i < count; i++)
591  {
592  int32_t svalue;
593 
595  UINT32_MAX);
596  // long to gcry_mpi_t
597  if (svalue < 0)
598  gcry_mpi_sub_ui (rand[i],
599  rand[i],
600  - svalue);
601  else
602  rand[i] = gcry_mpi_set_ui (rand[i], svalue);
603  }
604 
605  tmp = gcry_mpi_new (0);
606  // encrypt the element
607  // for the sake of readability I decided to have dedicated permutation
608  // vectors, which get rid of all the lookups in p/q.
609  // however, ap/aq are not absolutely necessary but are just abstraction
610  // Calculate Kp = E(S + a_pi) (+) E(S - r_pi - b_pi)
611  for (i = 0; i < count; i++)
612  {
613  // E(S - r_pi - b_pi)
614  gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
615  gcry_mpi_sub (tmp, tmp, b[p[i]].value);
616  GNUNET_assert (2 ==
618  tmp,
619  2,
620  &r[i]));
621 
622  // E(S - r_pi - b_pi) * E(S + a_pi) == E(2*S + a - r - b)
623  if (GNUNET_OK !=
625  &r[i],
626  &a[p[i]],
627  &r[i]))
628  {
629  GNUNET_break_op (0);
630  goto error_cleanup;
631  }
632  }
633 
634  // Calculate Kq = E(S + a_qi) (+) E(S - r_qi)
635  for (i = 0; i < count; i++)
636  {
637  // E(S - r_qi)
638  gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
639  GNUNET_assert (2 ==
641  tmp,
642  2,
643  &r_prime[i]));
644 
645  // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
646  if (GNUNET_OK !=
648  &r_prime[i],
649  &a[q[i]],
650  &r_prime[i]))
651  {
652  GNUNET_break_op (0);
653  goto error_cleanup;
654  }
655  }
656  gcry_mpi_release (tmp);
657 
658  // Calculate S' = E(SUM( r_i^2 ))
659  tmp = compute_square_sum (rand, count);
660  GNUNET_assert (1 ==
662  tmp,
663  1,
664  &session->s_prime));
665  gcry_mpi_release (tmp);
666 
667  // Calculate S = E(SUM( (r_i + b_i)^2 ))
668  for (i = 0; i < count; i++)
669  gcry_mpi_add (rand[i], rand[i], b[i].value);
670  tmp = compute_square_sum (rand, count);
671  GNUNET_assert (1 ==
673  tmp,
674  1,
675  &session->s));
676  gcry_mpi_release (tmp);
677 
678  session->r = r;
679  session->r_prime = r_prime;
680 
681  for (i = 0; i < count; i++)
682  gcry_mpi_release (rand[i]);
683  GNUNET_free (session->e_a);
684  session->e_a = NULL;
685  GNUNET_free (p);
686  GNUNET_free (q);
687  GNUNET_free (rand);
688  return GNUNET_OK;
689 
690  error_cleanup:
691  GNUNET_free (r);
692  GNUNET_free (r_prime);
693  gcry_mpi_release (tmp);
694  GNUNET_free (p);
695  GNUNET_free (q);
696  for (i = 0; i < count; i++)
697  gcry_mpi_release (rand[i]);
698  GNUNET_free (rand);
699  return GNUNET_SYSERR;
700 }
701 
702 
712 static int
713 copy_element_cb (void *cls,
714  const struct GNUNET_HashCode *key,
715  void *value)
716 {
717  struct BobServiceSession *s = cls;
719  gcry_mpi_t mval;
720  int64_t val;
721 
722  mval = gcry_mpi_new (0);
723  val = (int64_t) GNUNET_ntohll (e->value);
724  if (0 > val)
725  gcry_mpi_sub_ui (mval, mval, -val);
726  else
727  gcry_mpi_add_ui (mval, mval, val);
730  s->used_element_count++;
731  return GNUNET_OK;
732 }
733 
734 
743 static int
744 element_cmp (const void *a,
745  const void *b)
746 {
747  const struct MpiElement *ma = a;
748  const struct MpiElement *mb = b;
749 
750  return GNUNET_CRYPTO_hash_cmp (ma->key,
751  mb->key);
752 }
753 
754 
762 static void
764 {
765  struct GNUNET_CADET_Channel *channel;
766 
767  /* TODO: code duplication with Alice! */
769  "Received everything, building reply for Alice\n");
770  s->sorted_elements
772  sizeof (struct MpiElement));
773  s->used_element_count = 0;
776  s);
777  qsort (s->sorted_elements,
779  sizeof (struct MpiElement),
780  &element_cmp);
781  if (GNUNET_OK !=
783  {
784  channel = s->channel;
785  s->channel = NULL;
787  return;
788  }
790 }
791 
792 
802 static int
804  const struct AliceCryptodataMessage *msg)
805 {
806  struct BobServiceSession *s = cls;
807  uint32_t contained_elements;
808  size_t msg_length;
809  uint16_t msize;
810  unsigned int max;
811 
812  msize = ntohs (msg->header.size);
813  contained_elements = ntohl (msg->contained_element_count);
814  /* Our intersection may still be ongoing, but this is nevertheless
815  an upper bound on the required array size */
817  msg_length = sizeof (struct AliceCryptodataMessage)
818  + contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
819  if ( (msize != msg_length) ||
820  (0 == contained_elements) ||
821  (contained_elements > UINT16_MAX) ||
822  (max < contained_elements + s->cadet_received_element_count) )
823  {
824  GNUNET_break_op (0);
825  return GNUNET_SYSERR;
826  }
827  return GNUNET_OK;
828 }
829 
830 
838 static void
840  const struct AliceCryptodataMessage *msg)
841 {
842  struct BobServiceSession *s = cls;
844  uint32_t contained_elements;
845  unsigned int max;
846 
847  contained_elements = ntohl (msg->contained_element_count);
848  /* Our intersection may still be ongoing, but this is nevertheless
849  an upper bound on the required array size */
852  "Received %u crypto values from Alice\n",
853  (unsigned int) contained_elements);
854 
855  payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
856  if (NULL == s->e_a)
857  s->e_a = GNUNET_new_array (max,
860  payload,
861  sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements);
862  s->cadet_received_element_count += contained_elements;
863 
864  if ( (s->cadet_received_element_count == max) &&
865  (NULL == s->intersection_op) )
866  {
867  /* intersection has finished also on our side, and
868  we got the full set, so we can proceed with the
869  CADET response(s) */
871  }
873 }
874 
875 
885 static void
887  const struct GNUNET_SET_Element *element,
888  uint64_t current_size,
890 {
891  struct BobServiceSession *s = cls;
892  struct GNUNET_SCALARPRODUCT_Element *se;
893 
894  switch (status)
895  {
897  /* this element has been removed from the set */
899  element->data);
900  GNUNET_assert (NULL != se);
902  "Removed element with key %s and value %lld\n",
903  GNUNET_h2s (&se->key),
904  (long long) GNUNET_ntohll (se->value));
907  element->data,
908  se));
909  GNUNET_free (se);
910  return;
912  s->intersection_op = NULL;
913  GNUNET_break (NULL == s->intersection_set);
916  "Finished intersection, %d items remain\n",
920  {
921  /* CADET transmission from Alice is also already done,
922  start with our own reply */
924  }
925  return;
927  /* unexpected for intersection */
928  GNUNET_break (0);
929  return;
931  /* unhandled status code */
933  "Set intersection failed!\n");
934  s->intersection_op = NULL;
935  if (NULL != s->intersection_set)
936  {
938  s->intersection_set = NULL;
939  }
942  return;
943  default:
944  GNUNET_break (0);
945  return;
946  }
947 }
948 
949 
956 static void
958 {
960  "Got session with key %s and %u elements, starting intersection.\n",
961  GNUNET_h2s (&s->session_id),
962  (unsigned int) s->total);
963 
964  s->intersection_op
965  = GNUNET_SET_prepare (&s->peer,
966  &s->session_id,
967  NULL,
969  (struct GNUNET_SET_Option[]) {{ 0 }},
971  s);
972  if (GNUNET_OK !=
973  GNUNET_SET_commit (s->intersection_op,
974  s->intersection_set))
975  {
976  GNUNET_break (0);
979  return;
980  }
981  GNUNET_SET_destroy (s->intersection_set);
982  s->intersection_set = NULL;
983 }
984 
985 
992 static void
994  const struct ServiceRequestMessage *msg)
995 {
996  struct BobServiceSession *s = cls;
997 
998  s->session_id = msg->session_id; // ??
999  s->remote_pubkey = msg->public_key;
1000  if (s->client_received_element_count == s->total)
1001  start_intersection (s);
1002 }
1003 
1004 
1015 static void *
1017  struct GNUNET_CADET_Channel *channel,
1018  const struct GNUNET_PeerIdentity *initiator)
1019 {
1020  struct BobServiceSession *s = cls;
1021 
1023  "New incoming channel from peer %s.\n",
1024  GNUNET_i2s (initiator));
1026  s->port = NULL;
1027  s->channel = channel;
1028  s->peer = *initiator;
1030  return s;
1031 }
1032 
1033 
1041 static int
1044 {
1045  struct BobServiceSession *s = cls;
1046  uint32_t contained_count;
1047  uint16_t msize;
1048 
1049  msize = ntohs (msg->header.size);
1050  contained_count = ntohl (msg->element_count_contained);
1051  if ( (msize != (sizeof (struct ComputationBobCryptodataMultipartMessage) +
1052  contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
1053  (0 == contained_count) ||
1054  (UINT16_MAX < contained_count) ||
1055  (s->total == s->client_received_element_count) ||
1056  (s->total < s->client_received_element_count + contained_count) )
1057  {
1058  GNUNET_break (0);
1059  return GNUNET_SYSERR;
1060  }
1061  return GNUNET_OK;
1062 }
1063 
1064 
1072 static void
1075 {
1076  struct BobServiceSession *s = cls;
1077  uint32_t contained_count;
1078  const struct GNUNET_SCALARPRODUCT_Element *elements;
1079  struct GNUNET_SET_Element set_elem;
1080  struct GNUNET_SCALARPRODUCT_Element *elem;
1081 
1082  contained_count = ntohl (msg->element_count_contained);
1083  elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1084  for (uint32_t i = 0; i < contained_count; i++)
1085  {
1086  elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1087  GNUNET_memcpy (elem,
1088  &elements[i],
1089  sizeof (struct GNUNET_SCALARPRODUCT_Element));
1090  if (GNUNET_SYSERR ==
1092  &elem->key,
1093  elem,
1095  {
1096  GNUNET_break (0);
1097  GNUNET_free (elem);
1098  continue;
1099  }
1100  set_elem.data = &elem->key;
1101  set_elem.size = sizeof (elem->key);
1102  set_elem.element_type = 0;
1104  &set_elem,
1105  NULL, NULL);
1106  }
1107  s->client_received_element_count += contained_count;
1109  if (s->total != s->client_received_element_count)
1110  {
1111  /* more to come */
1112  return;
1113  }
1114  if (NULL == s->channel)
1115  {
1116  /* no Alice waiting for this request, wait for Alice */
1117  return;
1118  }
1119  start_intersection (s);
1120 }
1121 
1122 
1131 static int
1133  const struct BobComputationMessage *msg)
1134 {
1135  struct BobServiceSession *s = cls;
1136  uint32_t contained_count;
1137  uint32_t total_count;
1138  uint16_t msize;
1139 
1141  {
1142  GNUNET_break (0);
1143  return GNUNET_SYSERR;
1144  }
1145  msize = ntohs (msg->header.size);
1146  total_count = ntohl (msg->element_count_total);
1147  contained_count = ntohl (msg->element_count_contained);
1148  if ( (0 == total_count) ||
1149  (0 == contained_count) ||
1150  (UINT16_MAX < contained_count) ||
1151  (msize != (sizeof (struct BobComputationMessage) +
1152  contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) )
1153  {
1154  GNUNET_break_op (0);
1155  return GNUNET_SYSERR;
1156  }
1157  return GNUNET_OK;
1158 }
1159 
1160 
1169 static void
1171  const struct BobComputationMessage *msg)
1172 {
1173  struct BobServiceSession *s = cls;
1174  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1175  GNUNET_MQ_hd_fixed_size (alices_computation_request,
1177  struct ServiceRequestMessage,
1178  NULL),
1179  GNUNET_MQ_hd_var_size (alices_cryptodata_message,
1181  struct AliceCryptodataMessage,
1182  NULL),
1184  };
1185  uint32_t contained_count;
1186  uint32_t total_count;
1187  const struct GNUNET_SCALARPRODUCT_Element *elements;
1188  struct GNUNET_SET_Element set_elem;
1189  struct GNUNET_SCALARPRODUCT_Element *elem;
1190 
1191  total_count = ntohl (msg->element_count_total);
1192  contained_count = ntohl (msg->element_count_contained);
1193 
1195  s->total = total_count;
1196  s->client_received_element_count = contained_count;
1197  s->session_id = msg->session_key;
1198  elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1201  GNUNET_YES);
1202  s->intersection_set
1203  = GNUNET_SET_create (cfg,
1205  for (uint32_t i = 0; i < contained_count; i++)
1206  {
1207  if (0 == GNUNET_ntohll (elements[i].value))
1208  continue;
1209  elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1210  GNUNET_memcpy (elem,
1211  &elements[i],
1212  sizeof (struct GNUNET_SCALARPRODUCT_Element));
1213  if (GNUNET_SYSERR ==
1215  &elem->key,
1216  elem,
1218  {
1219  GNUNET_break (0);
1220  GNUNET_free (elem);
1221  continue;
1222  }
1223  set_elem.data = &elem->key;
1224  set_elem.size = sizeof (elem->key);
1225  set_elem.element_type = 0;
1227  &set_elem,
1228  NULL, NULL);
1229  s->used_element_count++;
1230  }
1232  /* We're ready, open the port */
1233  s->port = GNUNET_CADET_open_port (my_cadet,
1234  &msg->session_key,
1236  s,
1237  NULL,
1239  cadet_handlers);
1240  if (NULL == s->port)
1241  {
1242  GNUNET_break (0);
1244  return;
1245  }
1246 }
1247 
1248 
1254 static void
1255 shutdown_task (void *cls)
1256 {
1258  "Shutting down, initiating cleanup.\n");
1259  // FIXME: we have to cut our connections to CADET first!
1260  if (NULL != my_cadet)
1261  {
1262  GNUNET_CADET_disconnect (my_cadet);
1263  my_cadet = NULL;
1264  }
1265 }
1266 
1267 
1278 static void *
1280  struct GNUNET_SERVICE_Client *client,
1281  struct GNUNET_MQ_Handle *mq)
1282 {
1283  struct BobServiceSession *s;
1284 
1285  s = GNUNET_new (struct BobServiceSession);
1286  s->client = client;
1287  s->client_mq = mq;
1288  return s;
1289 }
1290 
1291 
1302 static void
1304  struct GNUNET_SERVICE_Client *client,
1305  void *app_cls)
1306 {
1307  struct BobServiceSession *s = app_cls;
1308 
1310  "Client disconnected from us.\n");
1311  s->client = NULL;
1313 }
1314 
1315 
1323 static void
1324 run (void *cls,
1325  const struct GNUNET_CONFIGURATION_Handle *c,
1327 {
1328  cfg = c;
1329  /*
1330  offset has to be sufficiently small to allow computation of:
1331  m1+m2 mod n == (S + a) + (S + b) mod n,
1332  if we have more complex operations, this factor needs to be lowered */
1333  my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1334  gcry_mpi_set_bit (my_offset,
1336 
1338  &my_privkey);
1339  my_cadet = GNUNET_CADET_connect (cfg);
1341  NULL);
1342  if (NULL == my_cadet)
1343  {
1345  _("Connect to CADET failed\n"));
1347  return;
1348  }
1349 }
1350 
1351 
1356 ("scalarproduct-bob",
1358  &run,
1361  NULL,
1362  GNUNET_MQ_hd_var_size (bob_client_message,
1364  struct BobComputationMessage,
1365  NULL),
1366 GNUNET_MQ_hd_var_size (bob_client_message_multipart,
1369  NULL),
1371 
1372 
1373 /* 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:849
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:686
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:96
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:91
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:1293
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:656
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_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
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_HashMapIterator it, void *it_cls)
Iterate over all entries in the map.
#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:78
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:812
#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:524
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:995
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:208
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:249
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:771
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:1029
#define GNUNET_memcpy(dst, src, n)
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:2618
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:79
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:1124
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:973
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:79
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:278
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:151
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:515
multipart messages following struct ComputationMessage
Message type passed from client to service to initiate a request or responder role.
Definition: scalarproduct.h:85
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port().
Definition: cadet_api.c:882
#define GNUNET_YES
Definition: gnunet_common.h:80
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.
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:911
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:2533
#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:1142
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...