GNUnet  0.10.x
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_set_service.h"
36 #include "scalarproduct.h"
38 
39 #define LOG(kind, ...) \
40  GNUNET_log_from(kind, "scalarproduct-alice", __VA_ARGS__)
41 
45 struct MpiElement {
51  const struct GNUNET_HashCode *key;
52 
56  gcry_mpi_t value;
57 };
58 
59 
64 struct AliceServiceSession {
68  struct GNUNET_HashCode session_id;
69 
73  struct GNUNET_PeerIdentity peer;
74 
78  struct GNUNET_SERVICE_Client *client;
79 
83  struct GNUNET_MQ_Handle *client_mq;
84 
88  struct GNUNET_MQ_Handle *cadet_mq;
89 
94  struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
95 
100  struct GNUNET_SET_Handle *intersection_set;
101 
106  struct GNUNET_SET_OperationHandle *intersection_op;
107 
111  struct GNUNET_SET_ListenHandle *intersection_listen;
112 
116  struct GNUNET_CADET_Channel *channel;
117 
121  struct MpiElement *sorted_elements;
122 
127 
132 
137 
142 
146  gcry_mpi_t product;
147 
152  uint32_t total;
153 
159  uint32_t used_element_count;
160 
165  uint32_t client_received_element_count;
166 
172 
180 
185  int in_destroy;
186 };
187 
188 
192 static const struct GNUNET_CONFIGURATION_Handle *cfg;
193 
198 
203 
207 static gcry_mpi_t my_offset;
208 
213 
214 
223 static int
224 free_element_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
225 {
227 
228  GNUNET_free(e);
229  return GNUNET_OK;
230 }
231 
232 
238 static void
240 {
241  if (GNUNET_YES == s->in_destroy)
242  return;
243  s->in_destroy = GNUNET_YES;
244  if (NULL != s->client)
245  {
246  struct GNUNET_SERVICE_Client *c = s->client;
247 
248  s->client = NULL;
250  }
251  if (NULL != s->channel)
252  {
254  s->channel = NULL;
255  }
256  if (NULL != s->intersected_elements)
257  {
260  s);
262  s->intersected_elements = NULL;
263  }
264  if (NULL != s->intersection_listen)
265  {
267  s->intersection_listen = NULL;
268  }
269  if (NULL != s->intersection_op)
270  {
272  s->intersection_op = NULL;
273  }
274  if (NULL != s->intersection_set)
275  {
277  s->intersection_set = NULL;
278  }
279  if (NULL != s->sorted_elements)
280  {
281  for (unsigned int i = 0; i < s->used_element_count; i++)
282  gcry_mpi_release(s->sorted_elements[i].value);
284  s->sorted_elements = NULL;
285  }
286  if (NULL != s->r)
287  {
288  GNUNET_free(s->r);
289  s->r = NULL;
290  }
291  if (NULL != s->r_prime)
292  {
293  GNUNET_free(s->r_prime);
294  s->r_prime = NULL;
295  }
296  if (NULL != s->product)
297  {
298  gcry_mpi_release(s->product);
299  s->product = NULL;
300  }
301  GNUNET_free(s);
302 }
303 
304 
311 static void
313 {
314  struct ClientResponseMessage *msg;
315  struct GNUNET_MQ_Envelope *e;
316 
317  if (NULL == session->client_mq)
318  return; /* no client left to be notified */
319  GNUNET_log(
321  "Sending session-end notification with status %d to client for session %s\n",
322  session->status,
323  GNUNET_h2s(&session->session_id));
325  msg->product_length = htonl(0);
326  msg->status = htonl(session->status);
327  GNUNET_MQ_send(session->client_mq, e);
328 }
329 
330 
337 static void
339 {
340  struct ClientResponseMessage *msg;
341  struct GNUNET_MQ_Envelope *e;
342  unsigned char *product_exported = NULL;
343  size_t product_length = 0;
344  int32_t range;
345  gcry_error_t rc;
346  int sign;
347  gcry_mpi_t value;
348 
349  if (NULL == s->product)
350  {
351  GNUNET_break(0);
353  return;
354  }
355  value = gcry_mpi_new(0);
356  sign = gcry_mpi_cmp_ui(s->product, 0);
357  if (0 > sign)
358  {
359  range = -1;
360  gcry_mpi_sub(value, value, s->product);
361  }
362  else if (0 < sign)
363  {
364  range = 1;
365  gcry_mpi_add(value, value, s->product);
366  }
367  else
368  {
369  /* result is exactly zero */
370  range = 0;
371  }
372  gcry_mpi_release(s->product);
373  s->product = NULL;
374 
375  if ((0 != range) && (0 != (rc = gcry_mpi_aprint(GCRYMPI_FMT_STD,
376  &product_exported,
377  &product_length,
378  value))))
379  {
380  LOG_GCRY(GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
382  return;
383  }
384  gcry_mpi_release(value);
385  e = GNUNET_MQ_msg_extra(msg,
386  product_length,
389  msg->range = htonl(range);
390  msg->product_length = htonl(product_length);
391  if (NULL != product_exported)
392  {
393  GNUNET_memcpy(&msg[1], product_exported, product_length);
394  GNUNET_free(product_exported);
395  }
396  GNUNET_MQ_send(s->client_mq, e);
398  "Sent result to client, session %s has ended!\n",
399  GNUNET_h2s(&s->session_id));
400 }
401 
402 
412 static void
413 cb_channel_destruction(void *cls, const struct GNUNET_CADET_Channel *channel)
414 {
415  struct AliceServiceSession *s = cls;
416 
418  "Peer disconnected, terminating session %s with peer %s\n",
419  GNUNET_h2s(&s->session_id),
420  GNUNET_i2s(&s->peer));
422  {
423  /* We didn't get an answer yet, fail with error */
426  }
427  s->channel = NULL;
428 }
429 
430 
438 static gcry_mpi_t
440  uint32_t length)
441 {
442  gcry_mpi_t elem;
443  gcry_mpi_t sum;
444  uint32_t i;
445 
446  GNUNET_assert(NULL != (sum = gcry_mpi_new(0)));
447  GNUNET_assert(NULL != (elem = gcry_mpi_new(0)));
448  for (i = 0; i < length; i++)
449  {
450  gcry_mpi_mul(elem, vector[i].value, vector[i].value);
451  gcry_mpi_add(sum, sum, elem);
452  }
453  gcry_mpi_release(elem);
454  return sum;
455 }
456 
457 
465 static gcry_mpi_t
466 compute_square_sum(const gcry_mpi_t *vector, uint32_t length)
467 {
468  gcry_mpi_t elem;
469  gcry_mpi_t sum;
470  uint32_t i;
471 
472  GNUNET_assert(NULL != (sum = gcry_mpi_new(0)));
473  GNUNET_assert(NULL != (elem = gcry_mpi_new(0)));
474  for (i = 0; i < length; i++)
475  {
476  gcry_mpi_mul(elem, vector[i], vector[i]);
477  gcry_mpi_add(sum, sum, elem);
478  }
479  gcry_mpi_release(elem);
480  return sum;
481 }
482 
483 
490 static gcry_mpi_t
492 {
493  uint32_t count;
494  gcry_mpi_t t;
495  gcry_mpi_t u;
496  gcry_mpi_t u_prime;
497  gcry_mpi_t p;
498  gcry_mpi_t p_prime;
499  gcry_mpi_t tmp;
500  gcry_mpi_t r[session->used_element_count];
501  gcry_mpi_t r_prime[session->used_element_count];
502  gcry_mpi_t s;
503  gcry_mpi_t s_prime;
504  unsigned int i;
505 
506  count = session->used_element_count;
507  // due to the introduced static offset S, we now also have to remove this
508  // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
509  // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
510  for (i = 0; i < count; i++)
511  {
512  r[i] = gcry_mpi_new(0);
514  &my_pubkey,
515  &session->r[i],
516  r[i]);
517  gcry_mpi_sub(r[i], r[i], my_offset);
518  gcry_mpi_sub(r[i], r[i], my_offset);
519  r_prime[i] = gcry_mpi_new(0);
521  &my_pubkey,
522  &session->r_prime[i],
523  r_prime[i]);
524  gcry_mpi_sub(r_prime[i], r_prime[i], my_offset);
525  gcry_mpi_sub(r_prime[i], r_prime[i], my_offset);
526  }
527 
528  // calculate t = sum(ai)
530  // calculate U
531  u = gcry_mpi_new(0);
532  tmp = compute_square_sum(r, count);
533  gcry_mpi_sub(u, u, tmp);
534  gcry_mpi_release(tmp);
535 
536  //calculate U'
537  u_prime = gcry_mpi_new(0);
538  tmp = compute_square_sum(r_prime, count);
539  gcry_mpi_sub(u_prime, u_prime, tmp);
540 
541  GNUNET_assert(p = gcry_mpi_new(0));
542  GNUNET_assert(p_prime = gcry_mpi_new(0));
543  GNUNET_assert(s = gcry_mpi_new(0));
544  GNUNET_assert(s_prime = gcry_mpi_new(0));
545 
546  // compute P
549  &my_pubkey,
550  &session->s_prime,
551  s_prime);
552 
553  // compute P
554  gcry_mpi_add(p, s, t);
555  gcry_mpi_add(p, p, u);
556 
557  // compute P'
558  gcry_mpi_add(p_prime, s_prime, t);
559  gcry_mpi_add(p_prime, p_prime, u_prime);
560 
561  gcry_mpi_release(t);
562  gcry_mpi_release(u);
563  gcry_mpi_release(u_prime);
564  gcry_mpi_release(s);
565  gcry_mpi_release(s_prime);
566 
567  // compute product
568  gcry_mpi_sub(p, p, p_prime);
569  gcry_mpi_release(p_prime);
570  tmp = gcry_mpi_set_ui(tmp, 2);
571  gcry_mpi_div(p, NULL, p, tmp, 0);
572 
573  gcry_mpi_release(tmp);
574  for (i = 0; i < count; i++)
575  {
576  gcry_mpi_release(session->sorted_elements[i].value);
577  gcry_mpi_release(r[i]);
578  gcry_mpi_release(r_prime[i]);
579  }
580  GNUNET_free(session->sorted_elements);
581  session->sorted_elements = NULL;
582  GNUNET_free(session->r);
583  session->r = NULL;
584  GNUNET_free(session->r_prime);
585  session->r_prime = NULL;
586 
587  return p;
588 }
589 
590 
600 static int
602  void *cls,
603  const struct BobCryptodataMultipartMessage *msg)
604 {
605  struct AliceServiceSession *s = cls;
606  uint32_t contained;
607  size_t msg_size;
608  size_t required_size;
609 
610  msg_size = ntohs(msg->header.size);
611  contained = ntohl(msg->contained_element_count);
612  required_size =
613  sizeof(struct BobCryptodataMultipartMessage) +
614  2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
615  if ((required_size != msg_size) ||
616  (s->cadet_received_element_count + contained > s->used_element_count))
617  {
618  GNUNET_break(0);
619  return GNUNET_SYSERR;
620  }
621  return GNUNET_OK;
622 }
623 
631 static void
633  void *cls,
634  const struct BobCryptodataMultipartMessage *msg)
635 {
636  struct AliceServiceSession *s = cls;
638  size_t i;
639  uint32_t contained;
640 
641  contained = ntohl(msg->contained_element_count);
643  "Received %u additional crypto values from Bob\n",
644  (unsigned int)contained);
645 
646  payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *)&msg[1];
647  /* Convert each k[][perm] to its MPI_value */
648  for (i = 0; i < contained; i++)
649  {
651  &payload[2 * i],
652  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
654  &payload[2 * i],
655  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
656  }
657  s->cadet_received_element_count += contained;
660  return; /* more to come */
661 
664 }
665 
666 
676 static int
678  const struct BobCryptodataMessage *msg)
679 {
680  struct AliceServiceSession *s = cls;
681  uint32_t contained;
682  uint16_t msg_size;
683  size_t required_size;
684 
685  msg_size = ntohs(msg->header.size);
686  contained = ntohl(msg->contained_element_count);
687  required_size =
688  sizeof(struct BobCryptodataMessage) +
689  2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext) +
690  2 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
691  if ((msg_size != required_size) || (contained > UINT16_MAX) ||
692  (s->used_element_count < contained))
693  {
694  GNUNET_break_op(0);
695  return GNUNET_SYSERR;
696  }
697  if (NULL == s->sorted_elements)
698  {
699  /* we're not ready yet, how can Bob be? */
700  GNUNET_break_op(0);
701  return GNUNET_SYSERR;
702  }
704  {
705  /* we're not ready yet, how can Bob be? */
706  GNUNET_break_op(0);
707  return GNUNET_SYSERR;
708  }
709  return GNUNET_OK;
710 }
711 
712 
720 static void
722  const struct BobCryptodataMessage *msg)
723 {
724  struct AliceServiceSession *s = cls;
726  uint32_t i;
727  uint32_t contained;
728 
729  contained = ntohl(msg->contained_element_count);
731  "Received %u crypto values from Bob\n",
732  (unsigned int)contained);
733  payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *)&msg[1];
734  GNUNET_memcpy(&s->s,
735  &payload[0],
736  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
738  &payload[1],
739  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
740  payload = &payload[2];
741 
746  for (i = 0; i < contained; i++)
747  {
748  GNUNET_memcpy(&s->r[i],
749  &payload[2 * i],
750  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
751  GNUNET_memcpy(&s->r_prime[i],
752  &payload[2 * i + 1],
753  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
754  }
755  s->cadet_received_element_count = contained;
757 
759  {
760  /* More to come */
761  return;
762  }
765 }
766 
767 
776 static int
777 copy_element_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
778 {
779  struct AliceServiceSession *s = cls;
781  gcry_mpi_t mval;
782  int64_t val;
783 
784  mval = gcry_mpi_new(0);
785  val = (int64_t)GNUNET_ntohll(e->value);
786  if (0 > val)
787  gcry_mpi_sub_ui(mval, mval, -val);
788  else
789  gcry_mpi_add_ui(mval, mval, val);
792  s->used_element_count++;
793  return GNUNET_OK;
794 }
795 
796 
804 static int
805 element_cmp(const void *a, const void *b)
806 {
807  const struct MpiElement *ma = a;
808  const struct MpiElement *mb = b;
809 
810  return GNUNET_CRYPTO_hash_cmp(ma->key, mb->key);
811 }
812 
813 
818 #define ELEMENT_CAPACITY \
819  ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 - \
820  sizeof(struct AliceCryptodataMessage)) / \
821  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext))
822 
823 
830 static void
832 {
833  struct AliceCryptodataMessage *msg;
834  struct GNUNET_MQ_Envelope *e;
836  unsigned int i;
837  uint32_t todo_count;
838  gcry_mpi_t a;
839  uint32_t off;
840 
843  sizeof(struct MpiElement));
844  s->used_element_count = 0;
847  s);
849  "Finished intersection, %d items remain\n",
850  s->used_element_count);
851  qsort(s->sorted_elements,
853  sizeof(struct MpiElement),
854  &element_cmp);
855  off = 0;
856  while (off < s->used_element_count)
857  {
858  todo_count = s->used_element_count - off;
859  if (todo_count > ELEMENT_CAPACITY)
860  todo_count = ELEMENT_CAPACITY;
862  "Sending %u/%u crypto values to Bob\n",
863  (unsigned int)todo_count,
864  (unsigned int)s->used_element_count);
865 
866  e =
868  todo_count *
869  sizeof(struct GNUNET_CRYPTO_PaillierCiphertext),
871  msg->contained_element_count = htonl(todo_count);
872  payload = (struct GNUNET_CRYPTO_PaillierCiphertext *)&msg[1];
873  a = gcry_mpi_new(0);
874  for (i = off; i < off + todo_count; i++)
875  {
876  gcry_mpi_add(a, s->sorted_elements[i].value, my_offset);
878  3 ==
879  GNUNET_CRYPTO_paillier_encrypt(&my_pubkey, a, 3, &payload[i - off]));
880  }
881  gcry_mpi_release(a);
882  off += todo_count;
883  GNUNET_MQ_send(s->cadet_mq, e);
884  }
885 }
886 
887 
898 static void
900  const struct GNUNET_SET_Element *element,
901  uint64_t current_size,
903 {
904  struct AliceServiceSession *s = cls;
905  struct GNUNET_SCALARPRODUCT_Element *se;
906 
907  switch (status)
908  {
910  /* this element has been removed from the set */
912  element->data);
913  GNUNET_assert(NULL != se);
915  "Intersection removed element with key %s and value %lld\n",
916  GNUNET_h2s(&se->key),
917  (long long)GNUNET_ntohll(se->value));
919  GNUNET_YES ==
921  element->data,
922  se));
923  GNUNET_free(se);
924  return;
925 
927  s->intersection_op = NULL;
928  if (NULL != s->intersection_set)
929  {
931  s->intersection_set = NULL;
932  }
934  return;
935 
937  /* unexpected for intersection */
938  GNUNET_break(0);
939  return;
940 
942  /* unhandled status code */
943  LOG(GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
944  if (NULL != s->intersection_listen)
945  {
947  s->intersection_listen = NULL;
948  }
949  s->intersection_op = NULL;
950  if (NULL != s->intersection_set)
951  {
953  s->intersection_set = NULL;
954  }
957  return;
958 
959  default:
960  GNUNET_break(0);
961  return;
962  }
963 }
964 
965 
981 static void
983  const struct GNUNET_PeerIdentity *other_peer,
984  const struct GNUNET_MessageHeader *context_msg,
985  struct GNUNET_SET_Request *request)
986 {
987  struct AliceServiceSession *s = cls;
988 
989  if (0 != GNUNET_memcmp(other_peer, &s->peer))
990  {
991  GNUNET_break_op(0);
992  return;
993  }
994  s->intersection_op = GNUNET_SET_accept(request,
996  (struct GNUNET_SET_Option[]){ { 0 } },
998  s);
999  if (NULL == s->intersection_op)
1000  {
1001  GNUNET_break(0);
1004  return;
1005  }
1007  {
1008  GNUNET_break(0);
1011  return;
1012  }
1013 }
1014 
1015 
1021 static void
1023 {
1024  struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1025  { GNUNET_MQ_hd_var_size(bobs_cryptodata_message,
1027  struct BobCryptodataMessage,
1028  s),
1030  bobs_cryptodata_multipart,
1033  s),
1035  struct ServiceRequestMessage *msg;
1036  struct GNUNET_MQ_Envelope *e;
1037 
1039  "Creating new channel for session with key %s.\n",
1040  GNUNET_h2s(&s->session_id));
1041  s->channel = GNUNET_CADET_channel_create(my_cadet,
1042  s,
1043  &s->peer,
1044  &s->session_id,
1045  NULL,
1047  cadet_handlers);
1048  if (NULL == s->channel)
1049  {
1052  return;
1053  }
1057  &s->session_id,
1059  s);
1060  if (NULL == s->intersection_listen)
1061  {
1064  s->channel = NULL;
1066  return;
1067  }
1068 
1069  e = GNUNET_MQ_msg(msg,
1071  msg->session_id = s->session_id;
1072  msg->public_key = my_pubkey;
1073  GNUNET_MQ_send(s->cadet_mq, e);
1074 }
1075 
1076 
1085 static int
1087  void *cls,
1089 {
1090  struct AliceServiceSession *s = cls;
1091  uint32_t contained_count;
1092  uint16_t msize;
1093 
1094  msize = ntohs(msg->header.size);
1095  contained_count = ntohl(msg->element_count_contained);
1096  if ((msize !=
1098  contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))) ||
1099  (0 == contained_count) ||
1100  (s->total == s->client_received_element_count) ||
1101  (s->total < s->client_received_element_count + contained_count))
1102  {
1103  GNUNET_break_op(0);
1104  return GNUNET_SYSERR;
1105  }
1106  return GNUNET_OK;
1107 }
1108 
1109 
1117 static void
1119  void *cls,
1121 {
1122  struct AliceServiceSession *s = cls;
1123  uint32_t contained_count;
1124  const struct GNUNET_SCALARPRODUCT_Element *elements;
1125  struct GNUNET_SET_Element set_elem;
1126  struct GNUNET_SCALARPRODUCT_Element *elem;
1127 
1128  contained_count = ntohl(msg->element_count_contained);
1129  s->client_received_element_count += contained_count;
1130  elements = (const struct GNUNET_SCALARPRODUCT_Element *)&msg[1];
1131  for (uint32_t i = 0; i < contained_count; i++)
1132  {
1134  GNUNET_memcpy(elem,
1135  &elements[i],
1136  sizeof(struct GNUNET_SCALARPRODUCT_Element));
1139  &elem->key,
1140  elem,
1142  {
1143  GNUNET_break(0);
1144  GNUNET_free(elem);
1145  continue;
1146  }
1147  set_elem.data = &elem->key;
1148  set_elem.size = sizeof(elem->key);
1149  set_elem.element_type = 0;
1150  GNUNET_SET_add_element(s->intersection_set, &set_elem, NULL, NULL);
1151  s->used_element_count++;
1152  }
1154  if (s->total != s->client_received_element_count)
1155  {
1156  /* more to come */
1157  return;
1158  }
1160 }
1161 
1162 
1171 static int
1173  const struct AliceComputationMessage *msg)
1174 {
1175  struct AliceServiceSession *s = cls;
1176  uint16_t msize;
1177  uint32_t total_count;
1178  uint32_t contained_count;
1179 
1180  if (NULL != s->intersected_elements)
1181  {
1182  /* only one concurrent session per client connection allowed,
1183  simplifies logic a lot... */
1184  GNUNET_break(0);
1185  return GNUNET_SYSERR;
1186  }
1187  msize = ntohs(msg->header.size);
1188  total_count = ntohl(msg->element_count_total);
1189  contained_count = ntohl(msg->element_count_contained);
1190  if ((0 == total_count) || (0 == contained_count) ||
1191  (msize !=
1192  (sizeof(struct AliceComputationMessage) +
1193  contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))))
1194  {
1195  GNUNET_break_op(0);
1196  return GNUNET_SYSERR;
1197  }
1198  return GNUNET_OK;
1199 }
1200 
1201 
1209 static void
1211  const struct AliceComputationMessage *msg)
1212 {
1213  struct AliceServiceSession *s = cls;
1214  uint32_t contained_count;
1215  uint32_t total_count;
1216  const struct GNUNET_SCALARPRODUCT_Element *elements;
1217  struct GNUNET_SET_Element set_elem;
1218  struct GNUNET_SCALARPRODUCT_Element *elem;
1219 
1220  total_count = ntohl(msg->element_count_total);
1221  contained_count = ntohl(msg->element_count_contained);
1222  s->peer = msg->peer;
1224  s->total = total_count;
1225  s->client_received_element_count = contained_count;
1226  s->session_id = msg->session_key;
1227  elements = (const struct GNUNET_SCALARPRODUCT_Element *)&msg[1];
1230  s->intersection_set =
1232 
1233  for (uint32_t i = 0; i < contained_count; i++)
1234  {
1235  if (0 == GNUNET_ntohll(elements[i].value))
1236  continue;
1238  GNUNET_memcpy(elem,
1239  &elements[i],
1240  sizeof(struct GNUNET_SCALARPRODUCT_Element));
1243  &elem->key,
1244  elem,
1246  {
1247  /* element with same key encountered twice! */
1248  GNUNET_break(0);
1249  GNUNET_free(elem);
1250  continue;
1251  }
1252  set_elem.data = &elem->key;
1253  set_elem.size = sizeof(elem->key);
1254  set_elem.element_type = 0;
1255  GNUNET_SET_add_element(s->intersection_set, &set_elem, NULL, NULL);
1256  s->used_element_count++;
1257  }
1259  if (s->total != s->client_received_element_count)
1260  {
1261  /* wait for multipart msg */
1262  return;
1263  }
1265 }
1266 
1267 
1273 static void
1274 shutdown_task(void *cls)
1275 {
1276  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutting down, initiating cleanup.\n");
1277  // FIXME: we have to cut our connections to CADET first!
1278  if (NULL != my_cadet)
1279  {
1280  GNUNET_CADET_disconnect(my_cadet);
1281  my_cadet = NULL;
1282  }
1283 }
1284 
1285 
1296 static void *
1298  struct GNUNET_SERVICE_Client *client,
1299  struct GNUNET_MQ_Handle *mq)
1300 {
1301  struct AliceServiceSession *s;
1302 
1303  s = GNUNET_new(struct AliceServiceSession);
1304  s->client = client;
1305  s->client_mq = mq;
1306  return s;
1307 }
1308 
1309 
1320 static void
1322  struct GNUNET_SERVICE_Client *client,
1323  void *app_cls)
1324 {
1325  struct AliceServiceSession *s = app_cls;
1326 
1328  "Client %p disconnected from us.\n",
1329  client);
1330  s->client = NULL;
1331  s->client_mq = NULL;
1333 }
1334 
1335 
1343 static void
1344 run(void *cls,
1345  const struct GNUNET_CONFIGURATION_Handle *c,
1347 {
1348  cfg = c;
1349  /*
1350  offset has to be sufficiently small to allow computation of:
1351  m1+m2 mod n == (S + a) + (S + b) mod n,
1352  if we have more complex operations, this factor needs to be lowered */
1353  my_offset = gcry_mpi_new(GNUNET_CRYPTO_PAILLIER_BITS / 3);
1354  gcry_mpi_set_bit(my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
1356  my_cadet = GNUNET_CADET_connect(cfg);
1358  if (NULL == my_cadet)
1359  {
1360  GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Connect to CADET failed\n"));
1362  return;
1363  }
1364 }
1365 
1366 
1371  "scalarproduct-alice",
1373  &run,
1376  NULL,
1377  GNUNET_MQ_hd_var_size(alice_client_message,
1379  struct AliceComputationMessage,
1380  NULL),
1382  alice_client_message_multipart,
1385  NULL),
1387 
1388 
1389 /* end of gnunet-service-scalarproduct_alice.c */
A scalarproduct session which tracks a request form the client to our final response.
Message type passed from service client to finalize a session as requester or responder.
int in_destroy
Flag to prevent recursive calls to destroy_service_session() from doing harm.
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:838
static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey
Service&#39;s own private key.
struct GNUNET_SET_ListenHandle * GNUNET_SET_listen(const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op_type, const struct GNUNET_HashCode *app_id, GNUNET_SET_ListenCallback listen_cb, void *listen_cls)
Wait for set operation requests for the given application ID.
Definition: set_api.c:1012
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static gcry_mpi_t my_offset
Service&#39;s offset for values that could possibly be negative but are plaintext for encryption...
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_CRYPTO_PaillierPublicKey public_key
Alice&#39;s public key.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
struct GNUNET_CADET_Channel * channel
channel-handle associated with our cadet handle
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_ALICE
Client -> Alice multipart.
struct GNUNET_MQ_Handle * cadet_mq
The message queue for CADET.
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...
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey
Service&#39;s own public key.
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:682
Handle for a set operation request from another peer.
Definition: set_api.c:113
Opaque handle to the service.
Definition: cadet_api.c:38
Handle to a service.
Definition: service.c:114
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION
Alice -> Bob session initialization.
const struct GNUNET_HashCode * key
Key used to identify matching pairs of values to multiply.
static void prepare_client_end_notification(struct AliceServiceSession *session)
Notify the client that the session has failed.
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:1284
static void shutdown_task(void *cls)
Task run during shutdown.
struct GNUNET_HashCode key
Key used to identify matching pairs of values to multiply.
struct GNUNET_CRYPTO_PaillierCiphertext s_prime
Bob&#39;s "s&#39;".
Element stored in a set.
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...
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:652
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void send_alices_cryptodata_message(struct AliceServiceSession *s)
Send the cryptographic data from Alice to Bob.
int32_t range
Workaround for libgcrypt: -1 if negative, 0 if zero, else 1.
#define LOG_GCRY(level, cmd, rc)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
Definition: scalarproduct.h:35
Message type passed from responding service Bob to responding service Alice to complete a request and...
struct GNUNET_MessageHeader header
GNUNET message header with type GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE.
Definition: scalarproduct.h:47
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static void handle_alice_client_message_multipart(void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
We&#39;re receiving additional set data.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
static struct Experiment * e
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_cls)
A client disconnected.
Opaque handle to a channel.
Definition: cadet_api.c:79
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
#define GNUNET_new(type)
Allocate a struct or union of the given type.
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...
enum GNUNET_SCALARPRODUCT_ResponseStatus status
State of this session.
struct GNUNET_MessageHeader header
GNUNET message header with type GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA. ...
struct GNUNET_MessageHeader header
GNUNET message header.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initialization of the program and message handlers.
gcry_mpi_t value
a_i value, not disclosed to Bob.
static struct GNUNET_SCHEDULER_Task * t
Main task.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
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.
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...
uint32_t total
How many elements we were supplied with from the client (total count before intersection).
Message type passed from client to service to initiate a request or responder role.
Definition: scalarproduct.h:42
struct GNUNET_HashCode session_key
the transaction/session key used to identify a session
Definition: scalarproduct.h:67
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:973
struct GNUNET_CRYPTO_PaillierCiphertext * r_prime
Bob&#39;s permutation q of R.
struct GNUNET_SET_OperationHandle * intersection_op
Set of elements for which will conduction an intersection.
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
Handle to a client that is connected to a service.
Definition: service.c:246
static const struct GNUNET_CONFIGURATION_Handle * cfg
GNUnet configuration handle.
void GNUNET_SET_destroy(struct GNUNET_SET_Handle *set)
Destroy the set handle, and free all associated resources.
Definition: set_api.c:767
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 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.
uint32_t status
Status information about the outcome of this session, An enum GNUNET_SCALARPRODUCT_ResponseStatus (in...
#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 int element_cmp(const void *a, const void *b)
Compare two struct MpiValues by key for sorting.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct MpiElement * sorted_elements
a(Alice), sorted array by key of length used_element_count.
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...
struct GNUNET_PeerIdentity peer
the identity of a remote peer we want to communicate with
Definition: scalarproduct.h:72
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...
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.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
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.
GNUNET_SET_Status
Status for the result callback.
static void destroy_service_session(struct AliceServiceSession *s)
Destroy session state, we are done with it.
uint32_t element_count_total
how many elements the vector in payload contains
Definition: scalarproduct.h:52
Message type passed from requesting service Alice to responding service Bob to initiate a request and...
uint16_t status
See PRISM_STATUS_*-constants.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
uint32_t cadet_received_element_count
Already transferred elements from Bob to us.
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.
#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.
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_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.
A 512-bit hashcode.
static void handle_alice_client_message(void *cls, const struct AliceComputationMessage *msg)
Handler for Alice&#39;s client request message.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2315
Message handler for a specific message type.
static void transmit_client_response(struct AliceServiceSession *s)
Prepare the final (positive) response we will send to Alice&#39;s client.
Opaque handle to a set.
Definition: set_api.c:48
struct GNUNET_PeerIdentity peer
Alice or Bob&#39;s peerID.
static void cb_intersection_request_alice(void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request)
Called when another peer wants to do a set operation with the local peer.
struct GNUNET_HashCode session_id
(hopefully) unique transaction ID
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). ...
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE
Client -> Alice.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
An encrypted element key-value pair.
scalarproduct service P2P messages
Multipart Message type passed between to supply additional elements for the peer. ...
void GNUNET_SET_listen_cancel(struct GNUNET_SET_ListenHandle *lh)
Cancel the given listen operation.
Definition: set_api.c:1046
uint32_t product_length
0 if no product attached
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART
Bob -> Alice SP crypto-data multipart.
Option for set operations.
int64_t value
Value to multiply in scalar product, in NBO.
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 used_element_count
How many elements actually are used for the scalar product.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
struct GNUNET_CONTAINER_MultiHashMap * intersected_elements
all non-0-value&#39;d elements transmitted to us.
#define LOG(kind,...)
gcry_mpi_t product
The computed scalar.
Handle to an operation.
Definition: set_api.c:132
Handle to a message queue.
Definition: mq.c:84
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA
Alice -> Bob SP crypto-data (after intersection)
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:1123
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:951
static int check_alice_client_message_multipart(void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
We&#39;re receiving additional set data.
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:1065
struct GNUNET_MessageHeader header
GNUNET message header.
configuration data
Definition: configuration.c:83
static int free_element_cb(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator called to free elements.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected.
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 int check_alice_client_message(void *cls, const struct AliceComputationMessage *msg)
Handler for Alice&#39;s client request message.
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,...)
uint32_t element_count_contained
contained elements the vector in payload contains
Definition: scalarproduct.h:57
uint32_t contained_element_count
How many elements we appended to this message? In NBO.
Opaque handle to a listen operation.
Definition: set_api.c:182
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
void GNUNET_SET_operation_cancel(struct GNUNET_SET_OperationHandle *oh)
Cancel the given set operation.
Definition: set_api.c:511
multipart messages following struct ComputationMessage
Header for all communications.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_SET_Handle * intersection_set
Set of elements for which will conduction an intersection.
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:351
struct GNUNET_SERVICE_Client * client
The client this request is related to.
static struct GNUNET_CADET_Handle * my_cadet
Handle to the CADET service.
Set intersection, only return elements that are in both sets.
uint32_t contained_element_count
How many elements this individual message delivers (in NBO).
GNUNET_SCALARPRODUCT_ResponseStatus
Result status values for the computation.
struct GNUNET_MQ_Handle * client_mq
The message queue for the client.
struct GNUNET_SET_ListenHandle * intersection_listen
Handle to Alice&#39;s Intersection operation listening for Bob.
#define ELEMENT_CAPACITY
Maximum number of elements we can put into a single cryptodata message.
struct GNUNET_CRYPTO_PaillierCiphertext * r
Bob&#39;s permutation p of R.
#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.
struct GNUNET_CRYPTO_PaillierCiphertext s
Bob&#39;s "s".
uint32_t client_received_element_count
Already transferred elements from client to us.
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:900
static gcry_mpi_t compute_scalar_product(struct AliceServiceSession *session)
Compute our scalar product, done by Alice.
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:2234
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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_SET_OperationHandle * GNUNET_SET_accept(struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, struct GNUNET_SET_Option options[], GNUNET_SET_ResultIterator result_cb, void *result_cls)
Accept a request we got via GNUNET_SET_listen().
Definition: set_api.c:1080
static void client_request_complete_alice(struct AliceServiceSession *s)
Our client has finished sending us its multipart message.
static void cb_channel_destruction(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called whenever a channel is destroyed.
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:1116
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.