GNUnet  0.19.5
gnunet-service-scalarproduct_alice.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013, 2014, 2017 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_seti_service.h"
36 #include "scalarproduct.h"
38 
39 #define LOG(kind, ...) \
40  GNUNET_log_from (kind, "scalarproduct-alice", __VA_ARGS__)
41 
45 struct MpiElement
46 {
52  const struct GNUNET_HashCode *key;
53 
57  gcry_mpi_t value;
58 };
59 
60 
66 {
71 
76 
81 
86 
90  struct GNUNET_MQ_Handle *cadet_mq;
91 
97 
103 
109 
114 
119 
123  struct MpiElement *sorted_elements;
124 
129 
134 
139 
144 
148  gcry_mpi_t product;
149 
154  uint32_t total;
155 
161  uint32_t used_element_count;
162 
168 
174 
182 
187  int in_destroy;
188 };
189 
190 
194 static const struct GNUNET_CONFIGURATION_Handle *cfg;
195 
200 
205 
209 static gcry_mpi_t my_offset;
210 
215 
216 
225 static int
226 free_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
227 {
229 
230  GNUNET_free (e);
231  return GNUNET_OK;
232 }
233 
234 
240 static void
242 {
243  if (GNUNET_YES == s->in_destroy)
244  return;
245  s->in_destroy = GNUNET_YES;
246  if (NULL != s->client)
247  {
248  struct GNUNET_SERVICE_Client *c = s->client;
249 
250  s->client = NULL;
252  }
253  if (NULL != s->channel)
254  {
256  s->channel = NULL;
257  }
258  if (NULL != s->intersected_elements)
259  {
262  s);
264  s->intersected_elements = NULL;
265  }
266  if (NULL != s->intersection_listen)
267  {
269  s->intersection_listen = NULL;
270  }
271  if (NULL != s->intersection_op)
272  {
274  s->intersection_op = NULL;
275  }
276  if (NULL != s->intersection_set)
277  {
279  s->intersection_set = NULL;
280  }
281  if (NULL != s->sorted_elements)
282  {
283  for (unsigned int i = 0; i < s->used_element_count; i++)
284  gcry_mpi_release (s->sorted_elements[i].value);
286  s->sorted_elements = NULL;
287  }
288  if (NULL != s->r)
289  {
290  GNUNET_free (s->r);
291  s->r = NULL;
292  }
293  if (NULL != s->r_prime)
294  {
295  GNUNET_free (s->r_prime);
296  s->r_prime = NULL;
297  }
298  if (NULL != s->product)
299  {
300  gcry_mpi_release (s->product);
301  s->product = NULL;
302  }
303  GNUNET_free (s);
304 }
305 
306 
313 static void
315 {
316  struct ClientResponseMessage *msg;
317  struct GNUNET_MQ_Envelope *e;
318 
319  if (NULL == session->client_mq)
320  return; /* no client left to be notified */
321  GNUNET_log (
323  "Sending session-end notification with status %d to client for session %s\n",
324  session->status,
325  GNUNET_h2s (&session->session_id));
327  msg->product_length = htonl (0);
328  msg->status = htonl (session->status);
329  GNUNET_MQ_send (session->client_mq, e);
330 }
331 
332 
339 static void
341 {
342  struct ClientResponseMessage *msg;
343  struct GNUNET_MQ_Envelope *e;
344  unsigned char *product_exported = NULL;
345  size_t product_length = 0;
346  int32_t range;
347  gcry_error_t rc;
348  int sign;
349  gcry_mpi_t value;
350 
351  if (NULL == s->product)
352  {
353  GNUNET_break (0);
355  return;
356  }
357  value = gcry_mpi_new (0);
358  sign = gcry_mpi_cmp_ui (s->product, 0);
359  if (0 > sign)
360  {
361  range = -1;
362  gcry_mpi_sub (value, value, s->product);
363  }
364  else if (0 < sign)
365  {
366  range = 1;
367  gcry_mpi_add (value, value, s->product);
368  }
369  else
370  {
371  /* result is exactly zero */
372  range = 0;
373  }
374  gcry_mpi_release (s->product);
375  s->product = NULL;
376 
377  if ((0 != range) && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
378  &product_exported,
379  &product_length,
380  value))))
381  {
382  LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
384  return;
385  }
386  gcry_mpi_release (value);
388  product_length,
390  msg->status = htonl (GNUNET_SCALARPRODUCT_STATUS_SUCCESS);
391  msg->range = htonl (range);
392  msg->product_length = htonl (product_length);
393  if (NULL != product_exported)
394  {
395  GNUNET_memcpy (&msg[1], product_exported, product_length);
396  GNUNET_free (product_exported);
397  }
398  GNUNET_MQ_send (s->client_mq, e);
400  "Sent result to client, session %s has ended!\n",
401  GNUNET_h2s (&s->session_id));
402 }
403 
404 
414 static void
415 cb_channel_destruction (void *cls, const struct GNUNET_CADET_Channel *channel)
416 {
417  struct AliceServiceSession *s = cls;
418 
420  "Peer disconnected, terminating session %s with peer %s\n",
421  GNUNET_h2s (&s->session_id),
422  GNUNET_i2s (&s->peer));
423  if (GNUNET_SCALARPRODUCT_STATUS_ACTIVE == s->status)
424  {
425  /* We didn't get an answer yet, fail with error */
428  }
429  s->channel = NULL;
430 }
431 
432 
440 static gcry_mpi_t
442  uint32_t length)
443 {
444  gcry_mpi_t elem;
445  gcry_mpi_t sum;
446  uint32_t i;
447 
448  GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
449  GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
450  for (i = 0; i < length; i++)
451  {
452  gcry_mpi_mul (elem, vector[i].value, vector[i].value);
453  gcry_mpi_add (sum, sum, elem);
454  }
455  gcry_mpi_release (elem);
456  return sum;
457 }
458 
459 
467 static gcry_mpi_t
468 compute_square_sum (const gcry_mpi_t *vector, uint32_t length)
469 {
470  gcry_mpi_t elem;
471  gcry_mpi_t sum;
472  uint32_t i;
473 
474  GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
475  GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
476  for (i = 0; i < length; i++)
477  {
478  gcry_mpi_mul (elem, vector[i], vector[i]);
479  gcry_mpi_add (sum, sum, elem);
480  }
481  gcry_mpi_release (elem);
482  return sum;
483 }
484 
485 
492 static gcry_mpi_t
494 {
495  uint32_t count;
496  gcry_mpi_t t;
497  gcry_mpi_t u;
498  gcry_mpi_t u_prime;
499  gcry_mpi_t p;
500  gcry_mpi_t p_prime;
501  gcry_mpi_t tmp;
502  gcry_mpi_t r[session->used_element_count];
503  gcry_mpi_t r_prime[session->used_element_count];
504  gcry_mpi_t s;
505  gcry_mpi_t s_prime;
506  unsigned int i;
507 
508  count = session->used_element_count;
509  // due to the introduced static offset S, we now also have to remove this
510  // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
511  // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
512  for (i = 0; i < count; i++)
513  {
514  r[i] = gcry_mpi_new (0);
516  &my_pubkey,
517  &session->r[i],
518  r[i]);
519  gcry_mpi_sub (r[i], r[i], my_offset);
520  gcry_mpi_sub (r[i], r[i], my_offset);
521  r_prime[i] = gcry_mpi_new (0);
523  &my_pubkey,
524  &session->r_prime[i],
525  r_prime[i]);
526  gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
527  gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
528  }
529 
530  // calculate t = sum(ai)
532  // calculate U
533  u = gcry_mpi_new (0);
534  tmp = compute_square_sum (r, count);
535  gcry_mpi_sub (u, u, tmp);
536  gcry_mpi_release (tmp);
537 
538  // calculate U'
539  u_prime = gcry_mpi_new (0);
540  tmp = compute_square_sum (r_prime, count);
541  gcry_mpi_sub (u_prime, u_prime, tmp);
542 
543  GNUNET_assert (p = gcry_mpi_new (0));
544  GNUNET_assert (p_prime = gcry_mpi_new (0));
545  GNUNET_assert (s = gcry_mpi_new (0));
546  GNUNET_assert (s_prime = gcry_mpi_new (0));
547 
548  // compute P
551  &my_pubkey,
552  &session->s_prime,
553  s_prime);
554 
555  // compute P
556  gcry_mpi_add (p, s, t);
557  gcry_mpi_add (p, p, u);
558 
559  // compute P'
560  gcry_mpi_add (p_prime, s_prime, t);
561  gcry_mpi_add (p_prime, p_prime, u_prime);
562 
563  gcry_mpi_release (t);
564  gcry_mpi_release (u);
565  gcry_mpi_release (u_prime);
566  gcry_mpi_release (s);
567  gcry_mpi_release (s_prime);
568 
569  // compute product
570  gcry_mpi_sub (p, p, p_prime);
571  gcry_mpi_release (p_prime);
572  tmp = gcry_mpi_set_ui (tmp, 2);
573  gcry_mpi_div (p, NULL, p, tmp, 0);
574 
575  gcry_mpi_release (tmp);
576  for (i = 0; i < count; i++)
577  {
578  gcry_mpi_release (session->sorted_elements[i].value);
579  gcry_mpi_release (r[i]);
580  gcry_mpi_release (r_prime[i]);
581  }
582  GNUNET_free (session->sorted_elements);
583  session->sorted_elements = NULL;
584  GNUNET_free (session->r);
585  session->r = NULL;
586  GNUNET_free (session->r_prime);
587  session->r_prime = NULL;
588 
589  return p;
590 }
591 
592 
602 static int
604  void *cls,
605  const struct BobCryptodataMultipartMessage *msg)
606 {
607  struct AliceServiceSession *s = cls;
608  uint32_t contained;
609  size_t msg_size;
610  size_t required_size;
611 
612  msg_size = ntohs (msg->header.size);
613  contained = ntohl (msg->contained_element_count);
614  required_size =
615  sizeof(struct BobCryptodataMultipartMessage)
616  + 2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
617  if ((required_size != msg_size) ||
618  (s->cadet_received_element_count + contained > s->used_element_count))
619  {
620  GNUNET_break (0);
621  return GNUNET_SYSERR;
622  }
623  return GNUNET_OK;
624 }
625 
626 
634 static void
636  void *cls,
637  const struct BobCryptodataMultipartMessage *msg)
638 {
639  struct AliceServiceSession *s = cls;
641  size_t i;
642  uint32_t contained;
643 
644  contained = ntohl (msg->contained_element_count);
646  "Received %u additional crypto values from Bob\n",
647  (unsigned int) contained);
648 
649  payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
650  /* Convert each k[][perm] to its MPI_value */
651  for (i = 0; i < contained; i++)
652  {
654  &payload[2 * i],
655  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
657  &payload[2 * i],
658  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
659  }
660  s->cadet_received_element_count += contained;
663  return; /* more to come */
664 
667 }
668 
669 
679 static int
681  const struct BobCryptodataMessage *msg)
682 {
683  struct AliceServiceSession *s = cls;
684  uint32_t contained;
685  uint16_t msg_size;
686  size_t required_size;
687 
688  msg_size = ntohs (msg->header.size);
689  contained = ntohl (msg->contained_element_count);
690  required_size =
691  sizeof(struct BobCryptodataMessage)
692  + 2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)
693  + 2 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
694  if ((msg_size != required_size) || (contained > UINT16_MAX) ||
695  (s->used_element_count < contained))
696  {
697  GNUNET_break_op (0);
698  return GNUNET_SYSERR;
699  }
700  if (NULL == s->sorted_elements)
701  {
702  /* we're not ready yet, how can Bob be? */
703  GNUNET_break_op (0);
704  return GNUNET_SYSERR;
705  }
707  {
708  /* we're not ready yet, how can Bob be? */
709  GNUNET_break_op (0);
710  return GNUNET_SYSERR;
711  }
712  return GNUNET_OK;
713 }
714 
715 
723 static void
725  const struct BobCryptodataMessage *msg)
726 {
727  struct AliceServiceSession *s = cls;
729  uint32_t i;
730  uint32_t contained;
731 
732  contained = ntohl (msg->contained_element_count);
734  "Received %u crypto values from Bob\n",
735  (unsigned int) contained);
736  payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
737  GNUNET_memcpy (&s->s,
738  &payload[0],
739  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
740  GNUNET_memcpy (&s->s_prime,
741  &payload[1],
742  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
743  payload = &payload[2];
744 
749  for (i = 0; i < contained; i++)
750  {
751  GNUNET_memcpy (&s->r[i],
752  &payload[2 * i],
753  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
754  GNUNET_memcpy (&s->r_prime[i],
755  &payload[2 * i + 1],
756  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
757  }
758  s->cadet_received_element_count = contained;
760 
762  {
763  /* More to come */
764  return;
765  }
768 }
769 
770 
779 static int
780 copy_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
781 {
782  struct AliceServiceSession *s = cls;
784  gcry_mpi_t mval;
785  int64_t val;
786 
787  mval = gcry_mpi_new (0);
788  val = (int64_t) GNUNET_ntohll (e->value);
789  if (0 > val)
790  gcry_mpi_sub_ui (mval, mval, -val);
791  else
792  gcry_mpi_add_ui (mval, mval, val);
794  s->sorted_elements[s->used_element_count].key = &e->key;
795  s->used_element_count++;
796  return GNUNET_OK;
797 }
798 
799 
807 static int
808 element_cmp (const void *a, const void *b)
809 {
810  const struct MpiElement *ma = a;
811  const struct MpiElement *mb = b;
812 
813  return GNUNET_CRYPTO_hash_cmp (ma->key, mb->key);
814 }
815 
816 
821 #define ELEMENT_CAPACITY \
822  ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 \
823  - sizeof(struct AliceCryptodataMessage)) \
824  / sizeof(struct GNUNET_CRYPTO_PaillierCiphertext))
825 
826 
833 static void
835 {
836  struct AliceCryptodataMessage *msg;
837  struct GNUNET_MQ_Envelope *e;
839  unsigned int i;
840  uint32_t todo_count;
841  gcry_mpi_t a;
842  uint32_t off;
843 
846  * sizeof(struct MpiElement));
847  s->used_element_count = 0;
850  s);
852  "Finished intersection, %d items remain\n",
853  s->used_element_count);
854  qsort (s->sorted_elements,
856  sizeof(struct MpiElement),
857  &element_cmp);
858  off = 0;
859  while (off < s->used_element_count)
860  {
861  todo_count = s->used_element_count - off;
862  if (todo_count > ELEMENT_CAPACITY)
863  todo_count = ELEMENT_CAPACITY;
865  "Sending %u/%u crypto values to Bob\n",
866  (unsigned int) todo_count,
867  (unsigned int) s->used_element_count);
868 
869  e =
871  todo_count
872  * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext),
874  msg->contained_element_count = htonl (todo_count);
876  a = gcry_mpi_new (0);
877  for (i = off; i < off + todo_count; i++)
878  {
879  gcry_mpi_add (a, s->sorted_elements[i].value, my_offset);
880  GNUNET_assert (
881  3 ==
882  GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i - off]));
883  }
884  gcry_mpi_release (a);
885  off += todo_count;
886  GNUNET_MQ_send (s->cadet_mq, e);
887  }
888 }
889 
890 
901 static void
903  const struct GNUNET_SETI_Element *element,
904  uint64_t current_size,
906 {
907  struct AliceServiceSession *s = cls;
908  struct GNUNET_SCALARPRODUCT_Element *se;
909 
910  switch (status)
911  {
913  /* this element has been removed from the set */
915  element->data);
916  GNUNET_assert (NULL != se);
918  "Intersection removed element with key %s and value %lld\n",
919  GNUNET_h2s (&se->key),
920  (long long) GNUNET_ntohll (se->value));
921  GNUNET_assert (
922  GNUNET_YES ==
924  element->data,
925  se));
926  GNUNET_free (se);
927  return;
928 
930  s->intersection_op = NULL;
931  if (NULL != s->intersection_set)
932  {
934  s->intersection_set = NULL;
935  }
937  return;
939  /* unhandled status code */
940  LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
941  if (NULL != s->intersection_listen)
942  {
944  s->intersection_listen = NULL;
945  }
946  s->intersection_op = NULL;
947  if (NULL != s->intersection_set)
948  {
950  s->intersection_set = NULL;
951  }
954  return;
955 
956  default:
957  GNUNET_break (0);
958  return;
959  }
960 }
961 
962 
978 static void
980  const struct GNUNET_PeerIdentity *other_peer,
981  const struct GNUNET_MessageHeader *context_msg,
983 {
984  struct AliceServiceSession *s = cls;
985 
986  if (0 != GNUNET_memcmp (other_peer, &s->peer))
987  {
988  GNUNET_break_op (0);
989  return;
990  }
991  s->intersection_op = GNUNET_SETI_accept (request,
992  (struct
993  GNUNET_SETI_Option[]){ { 0 } },
995  s);
996  if (NULL == s->intersection_op)
997  {
998  GNUNET_break (0);
1001  return;
1002  }
1003  if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
1004  {
1005  GNUNET_break (0);
1008  return;
1009  }
1010 }
1011 
1012 
1018 static void
1020 {
1021  struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1022  { GNUNET_MQ_hd_var_size (bobs_cryptodata_message,
1024  struct BobCryptodataMessage,
1025  s),
1027  bobs_cryptodata_multipart,
1030  s),
1031  GNUNET_MQ_handler_end () };
1032  struct ServiceRequestMessage *msg;
1033  struct GNUNET_MQ_Envelope *e;
1034 
1036  "Creating new channel for session with key %s.\n",
1037  GNUNET_h2s (&s->session_id));
1039  s,
1040  &s->peer,
1041  &s->session_id,
1042  NULL,
1044  cadet_handlers);
1045  if (NULL == s->channel)
1046  {
1049  return;
1050  }
1053  &s->session_id,
1055  s);
1056  if (NULL == s->intersection_listen)
1057  {
1060  s->channel = NULL;
1062  return;
1063  }
1064 
1065  e = GNUNET_MQ_msg (msg,
1067  msg->session_id = s->session_id;
1068  msg->public_key = my_pubkey;
1069  GNUNET_MQ_send (s->cadet_mq, e);
1070 }
1071 
1072 
1081 static int
1083  void *cls,
1085 {
1086  struct AliceServiceSession *s = cls;
1087  uint32_t contained_count;
1088  uint16_t msize;
1089 
1090  msize = ntohs (msg->header.size);
1091  contained_count = ntohl (msg->element_count_contained);
1092  if ((msize !=
1094  + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))) ||
1095  (0 == contained_count) ||
1096  (s->total == s->client_received_element_count) ||
1097  (s->total < s->client_received_element_count + contained_count))
1098  {
1099  GNUNET_break_op (0);
1100  return GNUNET_SYSERR;
1101  }
1102  return GNUNET_OK;
1103 }
1104 
1105 
1113 static void
1115  void *cls,
1117 {
1118  struct AliceServiceSession *s = cls;
1119  uint32_t contained_count;
1120  const struct GNUNET_SCALARPRODUCT_Element *elements;
1121  struct GNUNET_SETI_Element set_elem;
1122  struct GNUNET_SCALARPRODUCT_Element *elem;
1123 
1124  contained_count = ntohl (msg->element_count_contained);
1125  s->client_received_element_count += contained_count;
1126  elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1127  for (uint32_t i = 0; i < contained_count; i++)
1128  {
1129  elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1130  GNUNET_memcpy (elem,
1131  &elements[i],
1132  sizeof(struct GNUNET_SCALARPRODUCT_Element));
1135  &elem->key,
1136  elem,
1138  {
1139  GNUNET_break (0);
1140  GNUNET_free (elem);
1141  continue;
1142  }
1143  set_elem.data = &elem->key;
1144  set_elem.size = sizeof(elem->key);
1145  set_elem.element_type = 0;
1146  GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
1147  s->used_element_count++;
1148  }
1150  if (s->total != s->client_received_element_count)
1151  {
1152  /* more to come */
1153  return;
1154  }
1156 }
1157 
1158 
1167 static int
1169  const struct AliceComputationMessage *msg)
1170 {
1171  struct AliceServiceSession *s = cls;
1172  uint16_t msize;
1173  uint32_t total_count;
1174  uint32_t contained_count;
1175 
1176  if (NULL != s->intersected_elements)
1177  {
1178  /* only one concurrent session per client connection allowed,
1179  simplifies logic a lot... */
1180  GNUNET_break (0);
1181  return GNUNET_SYSERR;
1182  }
1183  msize = ntohs (msg->header.size);
1184  total_count = ntohl (msg->element_count_total);
1185  contained_count = ntohl (msg->element_count_contained);
1186  if ((0 == total_count) || (0 == contained_count) ||
1187  (msize !=
1188  (sizeof(struct AliceComputationMessage)
1189  + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))))
1190  {
1191  GNUNET_break_op (0);
1192  return GNUNET_SYSERR;
1193  }
1194  return GNUNET_OK;
1195 }
1196 
1197 
1205 static void
1207  const struct AliceComputationMessage *msg)
1208 {
1209  struct AliceServiceSession *s = cls;
1210  uint32_t contained_count;
1211  uint32_t total_count;
1212  const struct GNUNET_SCALARPRODUCT_Element *elements;
1213  struct GNUNET_SETI_Element set_elem;
1214  struct GNUNET_SCALARPRODUCT_Element *elem;
1215 
1216  total_count = ntohl (msg->element_count_total);
1217  contained_count = ntohl (msg->element_count_contained);
1218  s->peer = msg->peer;
1220  s->total = total_count;
1221  s->client_received_element_count = contained_count;
1222  s->session_id = msg->session_key;
1223  elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1227 
1228  for (uint32_t i = 0; i < contained_count; i++)
1229  {
1230  if (0 == GNUNET_ntohll (elements[i].value))
1231  continue;
1232  elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1233  GNUNET_memcpy (elem,
1234  &elements[i],
1235  sizeof(struct GNUNET_SCALARPRODUCT_Element));
1238  &elem->key,
1239  elem,
1241  {
1242  /* element with same key encountered twice! */
1243  GNUNET_break (0);
1244  GNUNET_free (elem);
1245  continue;
1246  }
1247  set_elem.data = &elem->key;
1248  set_elem.size = sizeof(elem->key);
1249  set_elem.element_type = 0;
1251  &set_elem,
1252  NULL,
1253  NULL);
1254  s->used_element_count++;
1255  }
1257  if (s->total != s->client_received_element_count)
1258  {
1259  /* wait for multipart msg */
1260  return;
1261  }
1263 }
1264 
1265 
1271 static void
1272 shutdown_task (void *cls)
1273 {
1274  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down, initiating cleanup.\n");
1275  // FIXME: we have to cut our connections to CADET first!
1276  if (NULL != my_cadet)
1277  {
1279  my_cadet = NULL;
1280  }
1281 }
1282 
1283 
1294 static void *
1296  struct GNUNET_SERVICE_Client *client,
1297  struct GNUNET_MQ_Handle *mq)
1298 {
1299  struct AliceServiceSession *s;
1300 
1301  s = GNUNET_new (struct AliceServiceSession);
1302  s->client = client;
1303  s->client_mq = mq;
1304  return s;
1305 }
1306 
1307 
1318 static void
1320  struct GNUNET_SERVICE_Client *client,
1321  void *app_cls)
1322 {
1323  struct AliceServiceSession *s = app_cls;
1324 
1326  "Client %p disconnected from us.\n",
1327  client);
1328  s->client = NULL;
1329  s->client_mq = NULL;
1331 }
1332 
1333 
1341 static void
1342 run (void *cls,
1343  const struct GNUNET_CONFIGURATION_Handle *c,
1345 {
1346  cfg = c;
1347  /*
1348  offset has to be sufficiently small to allow computation of:
1349  m1+m2 mod n == (S + a) + (S + b) mod n,
1350  if we have more complex operations, this factor needs to be lowered */
1351  my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1352  gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
1356  if (NULL == my_cadet)
1357  {
1358  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to CADET failed\n"));
1360  return;
1361  }
1362 }
1363 
1364 
1369  "scalarproduct-alice",
1371  &run,
1374  NULL,
1375  GNUNET_MQ_hd_var_size (alice_client_message,
1377  struct AliceComputationMessage,
1378  NULL),
1380  alice_client_message_multipart,
1383  NULL),
1385 
1386 
1387 /* end of gnunet-service-scalarproduct_alice.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static struct Experiment * e
struct GNUNET_HashCode key
The key used in the DHT.
uint16_t status
See PRISM_STATUS_*-constants.
static char * value
Value of the record to add/remove.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static unsigned long long payload
How much data are we currently storing in the database?
scalarproduct service P2P messages
static void cb_intersection_request_alice(void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SETI_Request *request)
Called when another peer wants to do a set operation with the local peer.
static void client_request_complete_alice(struct AliceServiceSession *s)
Our client has finished sending us its multipart message.
static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey
Service's own private key.
static int check_alice_client_message(void *cls, const struct AliceComputationMessage *msg)
Handler for Alice's client request message.
static struct GNUNET_CADET_Handle * my_cadet
Handle to the CADET service.
static const struct GNUNET_CONFIGURATION_Handle * cfg
GNUnet configuration handle.
static int check_bobs_cryptodata_multipart(void *cls, const struct BobCryptodataMultipartMessage *msg)
Check a multipart chunk of a response we got from another service we wanted to calculate a scalarprod...
static void handle_alice_client_message_multipart(void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
We're receiving additional set data.
static void prepare_client_end_notification(struct AliceServiceSession *session)
Notify the client that the session has failed.
static void destroy_service_session(struct AliceServiceSession *s)
Destroy session state, we are done with it.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_cls)
A client disconnected.
#define ELEMENT_CAPACITY
Maximum number of elements we can put into a single cryptodata message.
static void shutdown_task(void *cls)
Task run during shutdown.
static void handle_bobs_cryptodata_message(void *cls, const struct BobCryptodataMessage *msg)
Handle a response we got from another service we wanted to calculate a scalarproduct with.
static gcry_mpi_t compute_square_sum_mpi_elements(const struct MpiElement *vector, uint32_t length)
Computes the square sum over a vector of a given length.
static void handle_bobs_cryptodata_multipart(void *cls, const struct BobCryptodataMultipartMessage *msg)
Handle a multipart chunk of a response we got from another service we wanted to calculate a scalarpro...
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initialization of the program and message handlers.
static void send_alices_cryptodata_message(struct AliceServiceSession *s)
Send the cryptographic data from Alice to Bob.
static int check_bobs_cryptodata_message(void *cls, const struct BobCryptodataMessage *msg)
Check a response we got from another service we wanted to calculate a scalarproduct with.
static void cb_channel_destruction(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called whenever a channel is destroyed.
static void handle_alice_client_message(void *cls, const struct AliceComputationMessage *msg)
Handler for Alice's client request message.
static int element_cmp(const void *a, const void *b)
Compare two struct MpiValues by key for sorting.
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.
static gcry_mpi_t compute_scalar_product(struct AliceServiceSession *session)
Compute our scalar product, done by Alice.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected.
#define LOG(kind,...)
static void transmit_client_response(struct AliceServiceSession *s)
Prepare the final (positive) response we will send to Alice's client.
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 void cb_intersection_element_removed(void *cls, const struct GNUNET_SETI_Element *element, uint64_t current_size, enum GNUNET_SETI_Status status)
Callback for set operation results.
static int check_alice_client_message_multipart(void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
We're receiving additional set data.
static int free_element_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator called to free elements.
static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey
Service's own public key.
GNUNET_SERVICE_MAIN("scalarproduct-alice", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(alice_client_message, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE, struct AliceComputationMessage, NULL), GNUNET_MQ_hd_var_size(alice_client_message_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_ALICE, struct ComputationBobCryptodataMultipartMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static gcry_mpi_t my_offset
Service's offset for values that could possibly be negative but are plaintext for encryption.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
static struct GNUNET_SCHEDULER_Task * t
Main task.
Constants for network applications operating on top of the CADET service.
CADET service; establish channels to distant peers.
Core service; the main API for encrypted P2P communications.
Constants for network protocols.
Two-peer set intersection operations.
struct GNUNET_CADET_Channel * GNUNET_CADET_channel_create(struct GNUNET_CADET_Handle *h, void *channel_cls, const struct GNUNET_PeerIdentity *destination, const struct GNUNET_HashCode *port, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Create a new channel towards a remote peer.
Definition: cadet_api.c:1015
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:872
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:830
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:774
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:1066
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:894
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:221
enum GNUNET_GenericReturnValue 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.
enum GNUNET_GenericReturnValue 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.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_log(kind,...)
#define GNUNET_CRYPTO_PAILLIER_BITS
Size of paillier plain texts and public keys.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
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.
void GNUNET_CRYPTO_paillier_create(struct GNUNET_CRYPTO_PaillierPublicKey *public_key, struct GNUNET_CRYPTO_PaillierPrivateKey *private_key)
Create a freshly generated paillier public key.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
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:304
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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:63
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT
Alice/Bob -> Client Result.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA
Alice -> Bob SP crypto-data (after intersection)
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA
Bob -> Alice SP crypto-data.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_ALICE
Client -> Alice multipart.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION
Alice -> Bob session initialization.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE
Client -> Alice.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART
Bob -> Alice SP crypto-data multipart.
GNUNET_SCALARPRODUCT_ResponseStatus
Result status values for the computation.
@ GNUNET_SCALARPRODUCT_STATUS_SUCCESS
The computation was successful.
@ GNUNET_SCALARPRODUCT_STATUS_ACTIVE
Operation is still active (never returned, used internally).
@ GNUNET_SCALARPRODUCT_STATUS_FAILURE
We encountered some error.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
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,...
Definition: scheduler.c:1334
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2330
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2249
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
GNUNET_SETI_Status
Status for the result callback.
struct GNUNET_SETI_OperationHandle * GNUNET_SETI_accept(struct GNUNET_SETI_Request *request, const struct GNUNET_SETI_Option options[], GNUNET_SETI_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SETI_listen().
Definition: seti_api.c:754
void GNUNET_SETI_destroy(struct GNUNET_SETI_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: seti_api.c:488
struct GNUNET_SETI_Handle * GNUNET_SETI_create(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create an empty set, supporting the specified operation.
Definition: seti_api.c:399
int GNUNET_SETI_add_element(struct GNUNET_SETI_Handle *set, const struct GNUNET_SETI_Element *element, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Add an element to the given set.
Definition: seti_api.c:447
int GNUNET_SETI_commit(struct GNUNET_SETI_OperationHandle *oh, struct GNUNET_SETI_Handle *set)
Commit a set to be used with a set operation.
Definition: seti_api.c:810
void GNUNET_SETI_operation_cancel(struct GNUNET_SETI_OperationHandle *oh)
Cancel the given set operation.
Definition: seti_api.c:335
struct GNUNET_SETI_ListenHandle * GNUNET_SETI_listen(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode *app_id, GNUNET_SETI_ListenCallback listen_cb, void *listen_cls)
Wait for set operation requests for the given application ID.
Definition: seti_api.c:702
void GNUNET_SETI_listen_cancel(struct GNUNET_SETI_ListenHandle *lh)
Cancel the given listen operation.
Definition: seti_api.c:734
@ GNUNET_SETI_STATUS_DONE
Success, all elements have been sent (and received).
@ GNUNET_SETI_STATUS_FAILURE
The other peer refused to do the operation with us, or something went wrong.
@ GNUNET_SETI_STATUS_DEL_LOCAL
Element should be delete from the result set of the local peer, i.e.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Scalar Product API Message Types.
#define LOG_GCRY(level, cmd, rc)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
Definition: scalarproduct.h:35
Message type passed from client to service to initiate a request or responder role.
Definition: scalarproduct.h:46
Vector of Pallier-encrypted values sent by Alice to Bob (after set intersection).
A scalarproduct session which tracks a request form the client to our final response.
struct GNUNET_CRYPTO_PaillierCiphertext s
Bob's "s".
struct MpiElement * sorted_elements
a(Alice), sorted array by key of length used_element_count.
struct GNUNET_HashCode session_id
(hopefully) unique transaction ID
struct GNUNET_CONTAINER_MultiHashMap * intersected_elements
all non-0-value'd elements transmitted to us.
uint32_t total
How many elements we were supplied with from the client (total count before intersection).
struct GNUNET_MQ_Handle * client_mq
The message queue for the client.
int product
The computed scalar product.
gcry_mpi_t product
The computed scalar.
struct GNUNET_SETI_Handle * intersection_set
Set of elements for which will conduction an intersection.
struct GNUNET_CRYPTO_PaillierCiphertext * r
Bob's permutation p of R.
int in_destroy
Flag to prevent recursive calls to destroy_service_session() from doing harm.
uint32_t cadet_received_element_count
Already transferred elements from Bob to us.
struct GNUNET_SETI_OperationHandle * intersection_op
Set of elements for which will conduction an intersection.
struct GNUNET_CRYPTO_PaillierCiphertext * r_prime
Bob's permutation q of R.
uint32_t client_received_element_count
Already transferred elements from client to us.
struct GNUNET_SERVICE_Client * client
The client this request is related to.
struct GNUNET_CADET_Channel * channel
channel-handle associated with our cadet handle
struct GNUNET_PeerIdentity peer
Alice or Bob's peerID.
struct GNUNET_MQ_Handle * cadet_mq
The message queue for CADET.
struct GNUNET_SETI_ListenHandle * intersection_listen
Handle to Alice's Intersection operation listening for Bob.
uint32_t used_element_count
How many elements actually are used for the scalar product.
struct GNUNET_CRYPTO_PaillierCiphertext s_prime
Bob's "s'".
enum GNUNET_SCALARPRODUCT_ResponseStatus status
State of this session.
Message type passed from responding service Bob to responding service Alice to complete a request and...
Multipart Message type passed between to supply additional elements for the peer.
Message type passed from service client to finalize a session as requester or responder.
multipart messages following struct ComputationMessage
Opaque handle to a channel.
Definition: cadet.h:116
Opaque handle to the service.
Definition: cadet_api.c:39
Internal representation of the hash map.
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
The identity of the host (wraps the signing key of the peer).
An element key-value pair for scalarproduct.
struct GNUNET_HashCode key
Key used to identify matching pairs of values to multiply.
int64_t value
Value to multiply in scalar product, in NBO.
Handle to a client that is connected to a service.
Definition: service.c:252
Handle to a service.
Definition: service.c:118
Element stored in a set.
const void * data
Actual data of the element.
uint16_t element_type
Application-specific element type.
uint16_t size
Number of bytes in the buffer pointed to by data.
Opaque handle to a set.
Definition: seti_api.c:40
Opaque handle to a listen operation.
Definition: seti_api.c:163
Handle to an operation.
Definition: seti_api.c:106
Option for set operations.
Handle for a set operation request from another peer.
Definition: seti_api.c:86
An encrypted element key-value pair.
const struct GNUNET_HashCode * key
Key used to identify matching pairs of values to multiply.
gcry_mpi_t value
Value represented (a).
Message type passed from requesting service Alice to responding service Bob to initiate a request and...