GNUnet 0.21.1
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"
32#include "gnunet_applications.h"
33#include "gnunet_protocols.h"
35#include "gnunet_seti_service.h"
36#include "scalarproduct.h"
38#include "gnunet_constants.h"
39
40#define LOG(kind, ...) \
41 GNUNET_log_from (kind, "scalarproduct-alice", __VA_ARGS__)
42
46struct MpiElement
47{
53 const struct GNUNET_HashCode *key;
54
58 gcry_mpi_t value;
59};
60
61
67{
72
77
82
87
92
98
104
110
115
120
125
130
135
140
145
149 gcry_mpi_t product;
150
155 uint32_t total;
156
162 uint32_t used_element_count;
163
169
175
183
188 int in_destroy;
189};
190
191
195static const struct GNUNET_CONFIGURATION_Handle *cfg;
196
201
206
210static gcry_mpi_t my_offset;
211
216
217
226static int
227free_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
228{
230
231 GNUNET_free (e);
232 return GNUNET_OK;
233}
234
235
241static void
243{
244 if (GNUNET_YES == s->in_destroy)
245 return;
247 if (NULL != s->client)
248 {
249 struct GNUNET_SERVICE_Client *c = s->client;
250
251 s->client = NULL;
253 }
254 if (NULL != s->channel)
255 {
257 s->channel = NULL;
258 }
259 if (NULL != s->intersected_elements)
260 {
263 s);
265 s->intersected_elements = NULL;
266 }
267 if (NULL != s->intersection_listen)
268 {
270 s->intersection_listen = NULL;
271 }
272 if (NULL != s->intersection_op)
273 {
275 s->intersection_op = NULL;
276 }
277 if (NULL != s->intersection_set)
278 {
280 s->intersection_set = NULL;
281 }
282 if (NULL != s->sorted_elements)
283 {
284 for (unsigned int i = 0; i < s->used_element_count; i++)
285 gcry_mpi_release (s->sorted_elements[i].value);
287 s->sorted_elements = NULL;
288 }
289 if (NULL != s->r)
290 {
291 GNUNET_free (s->r);
292 s->r = NULL;
293 }
294 if (NULL != s->r_prime)
295 {
296 GNUNET_free (s->r_prime);
297 s->r_prime = NULL;
298 }
299 if (NULL != s->product)
300 {
301 gcry_mpi_release (s->product);
302 s->product = NULL;
303 }
304 GNUNET_free (s);
305}
306
307
314static void
316{
318 struct GNUNET_MQ_Envelope *e;
319
320 if (NULL == session->client_mq)
321 return; /* no client left to be notified */
322 GNUNET_log (
324 "Sending session-end notification with status %d to client for session %s\n",
325 session->status,
326 GNUNET_h2s (&session->session_id));
328 msg->product_length = htonl (0);
329 msg->status = htonl (session->status);
330 GNUNET_MQ_send (session->client_mq, e);
331}
332
333
340static void
342{
344 struct GNUNET_MQ_Envelope *e;
345 unsigned char *product_exported = NULL;
346 size_t product_length = 0;
347 int32_t range;
348 gcry_error_t rc;
349 int sign;
350 gcry_mpi_t value;
351
352 if (NULL == s->product)
353 {
354 GNUNET_break (0);
356 return;
357 }
358 value = gcry_mpi_new (0);
359 sign = gcry_mpi_cmp_ui (s->product, 0);
360 if (0 > sign)
361 {
362 range = -1;
363 gcry_mpi_sub (value, value, s->product);
364 }
365 else if (0 < sign)
366 {
367 range = 1;
368 gcry_mpi_add (value, value, s->product);
369 }
370 else
371 {
372 /* result is exactly zero */
373 range = 0;
374 }
375 gcry_mpi_release (s->product);
376 s->product = NULL;
377
378 if ((0 != range) && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
379 &product_exported,
380 &product_length,
381 value))))
382 {
383 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
385 return;
386 }
387 gcry_mpi_release (value);
389 product_length,
392 msg->range = htonl (range);
393 msg->product_length = htonl (product_length);
394 if (NULL != product_exported)
395 {
396 GNUNET_memcpy (&msg[1], product_exported, product_length);
397 GNUNET_free (product_exported);
398 }
401 "Sent result to client, session %s has ended!\n",
402 GNUNET_h2s (&s->session_id));
403}
404
405
415static void
416cb_channel_destruction (void *cls, const struct GNUNET_CADET_Channel *channel)
417{
418 struct AliceServiceSession *s = cls;
419
421 "Peer disconnected, terminating session %s with peer %s\n",
422 GNUNET_h2s (&s->session_id),
423 GNUNET_i2s (&s->peer));
425 {
426 /* We didn't get an answer yet, fail with error */
429 }
430 s->channel = NULL;
431}
432
433
441static gcry_mpi_t
443 uint32_t length)
444{
445 gcry_mpi_t elem;
446 gcry_mpi_t sum;
447 uint32_t i;
448
449 GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
450 GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
451 for (i = 0; i < length; i++)
452 {
453 gcry_mpi_mul (elem, vector[i].value, vector[i].value);
454 gcry_mpi_add (sum, sum, elem);
455 }
456 gcry_mpi_release (elem);
457 return sum;
458}
459
460
468static gcry_mpi_t
469compute_square_sum (const gcry_mpi_t *vector, uint32_t length)
470{
471 gcry_mpi_t elem;
472 gcry_mpi_t sum;
473 uint32_t i;
474
475 GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
476 GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
477 for (i = 0; i < length; i++)
478 {
479 gcry_mpi_mul (elem, vector[i], vector[i]);
480 gcry_mpi_add (sum, sum, elem);
481 }
482 gcry_mpi_release (elem);
483 return sum;
484}
485
486
493static gcry_mpi_t
495{
496 uint32_t count;
497 gcry_mpi_t t;
498 gcry_mpi_t u;
499 gcry_mpi_t u_prime;
500 gcry_mpi_t p;
501 gcry_mpi_t p_prime;
502 gcry_mpi_t tmp;
503 gcry_mpi_t r[session->used_element_count];
504 gcry_mpi_t r_prime[session->used_element_count];
505 gcry_mpi_t s;
506 gcry_mpi_t s_prime;
507 unsigned int i;
508
509 count = session->used_element_count;
510 // due to the introduced static offset S, we now also have to remove this
511 // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
512 // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
513 for (i = 0; i < count; i++)
514 {
515 r[i] = gcry_mpi_new (0);
517 &my_pubkey,
518 &session->r[i],
519 r[i]);
520 gcry_mpi_sub (r[i], r[i], my_offset);
521 gcry_mpi_sub (r[i], r[i], my_offset);
522 r_prime[i] = gcry_mpi_new (0);
524 &my_pubkey,
525 &session->r_prime[i],
526 r_prime[i]);
527 gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
528 gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
529 }
530
531 // calculate t = sum(ai)
533 // calculate U
534 u = gcry_mpi_new (0);
535 tmp = compute_square_sum (r, count);
536 gcry_mpi_sub (u, u, tmp);
537 gcry_mpi_release (tmp);
538
539 // calculate U'
540 u_prime = gcry_mpi_new (0);
541 tmp = compute_square_sum (r_prime, count);
542 gcry_mpi_sub (u_prime, u_prime, tmp);
543
544 GNUNET_assert (p = gcry_mpi_new (0));
545 GNUNET_assert (p_prime = gcry_mpi_new (0));
546 GNUNET_assert (s = gcry_mpi_new (0));
547 GNUNET_assert (s_prime = gcry_mpi_new (0));
548
549 // compute P
552 &my_pubkey,
553 &session->s_prime,
554 s_prime);
555
556 // compute P
557 gcry_mpi_add (p, s, t);
558 gcry_mpi_add (p, p, u);
559
560 // compute P'
561 gcry_mpi_add (p_prime, s_prime, t);
562 gcry_mpi_add (p_prime, p_prime, u_prime);
563
564 gcry_mpi_release (t);
565 gcry_mpi_release (u);
566 gcry_mpi_release (u_prime);
567 gcry_mpi_release (s);
568 gcry_mpi_release (s_prime);
569
570 // compute product
571 gcry_mpi_sub (p, p, p_prime);
572 gcry_mpi_release (p_prime);
573 tmp = gcry_mpi_set_ui (tmp, 2);
574 gcry_mpi_div (p, NULL, p, tmp, 0);
575
576 gcry_mpi_release (tmp);
577 for (i = 0; i < count; i++)
578 {
579 gcry_mpi_release (session->sorted_elements[i].value);
580 gcry_mpi_release (r[i]);
581 gcry_mpi_release (r_prime[i]);
582 }
583 GNUNET_free (session->sorted_elements);
584 session->sorted_elements = NULL;
585 GNUNET_free (session->r);
586 session->r = NULL;
587 GNUNET_free (session->r_prime);
588 session->r_prime = NULL;
589
590 return p;
591}
592
593
603static int
605 void *cls,
607{
608 struct AliceServiceSession *s = cls;
609 uint32_t contained;
610 size_t msg_size;
611 size_t required_size;
612
613 msg_size = ntohs (msg->header.size);
614 contained = ntohl (msg->contained_element_count);
615 required_size =
616 sizeof(struct BobCryptodataMultipartMessage)
617 + 2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
618 if ((required_size != msg_size) ||
620 {
621 GNUNET_break (0);
622 return GNUNET_SYSERR;
623 }
624 return GNUNET_OK;
625}
626
627
635static void
637 void *cls,
639{
640 struct AliceServiceSession *s = cls;
642 size_t i;
643 uint32_t contained;
644
645 contained = ntohl (msg->contained_element_count);
647 "Received %u additional crypto values from Bob\n",
648 (unsigned int) contained);
649
650 payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
651 /* Convert each k[][perm] to its MPI_value */
652 for (i = 0; i < contained; i++)
653 {
655 &payload[2 * i],
656 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
658 &payload[2 * i],
659 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
660 }
661 s->cadet_received_element_count += contained;
664 return; /* more to come */
665
668}
669
670
680static int
682 const struct BobCryptodataMessage *msg)
683{
684 struct AliceServiceSession *s = cls;
685 uint32_t contained;
686 uint16_t msg_size;
687 size_t required_size;
688
689 msg_size = ntohs (msg->header.size);
690 contained = ntohl (msg->contained_element_count);
691 required_size =
692 sizeof(struct BobCryptodataMessage)
693 + 2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)
694 + 2 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
695 if ((msg_size != required_size) || (contained > UINT16_MAX) ||
696 (s->used_element_count < contained))
697 {
698 GNUNET_break_op (0);
699 return GNUNET_SYSERR;
700 }
701 if (NULL == s->sorted_elements)
702 {
703 /* we're not ready yet, how can Bob be? */
704 GNUNET_break_op (0);
705 return GNUNET_SYSERR;
706 }
708 {
709 /* we're not ready yet, how can Bob be? */
710 GNUNET_break_op (0);
711 return GNUNET_SYSERR;
712 }
713 return GNUNET_OK;
714}
715
716
724static void
726 const struct BobCryptodataMessage *msg)
727{
728 struct AliceServiceSession *s = cls;
730 uint32_t i;
731 uint32_t contained;
732
733 contained = ntohl (msg->contained_element_count);
735 "Received %u crypto values from Bob\n",
736 (unsigned int) contained);
737 payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
738 GNUNET_memcpy (&s->s,
739 &payload[0],
740 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
742 &payload[1],
743 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
744 payload = &payload[2];
745
750 for (i = 0; i < contained; i++)
751 {
752 GNUNET_memcpy (&s->r[i],
753 &payload[2 * i],
754 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
755 GNUNET_memcpy (&s->r_prime[i],
756 &payload[2 * i + 1],
757 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
758 }
759 s->cadet_received_element_count = contained;
761
763 {
764 /* More to come */
765 return;
766 }
769}
770
771
780static int
781copy_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
782{
783 struct AliceServiceSession *s = cls;
785 gcry_mpi_t mval;
786 int64_t val;
787
788 mval = gcry_mpi_new (0);
789 val = (int64_t) GNUNET_ntohll (e->value);
790 if (0 > val)
791 gcry_mpi_sub_ui (mval, mval, -val);
792 else
793 gcry_mpi_add_ui (mval, mval, val);
797 return GNUNET_OK;
798}
799
800
808static int
809element_cmp (const void *a, const void *b)
810{
811 const struct MpiElement *ma = a;
812 const struct MpiElement *mb = b;
813
814 return GNUNET_CRYPTO_hash_cmp (ma->key, mb->key);
815}
816
817
822#define ELEMENT_CAPACITY \
823 ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 \
824 - sizeof(struct AliceCryptodataMessage)) \
825 / sizeof(struct GNUNET_CRYPTO_PaillierCiphertext))
826
827
834static void
836{
838 struct GNUNET_MQ_Envelope *e;
840 unsigned int i;
841 uint32_t todo_count;
842 gcry_mpi_t a;
843 uint32_t off;
844
847 * sizeof(struct MpiElement));
848 s->used_element_count = 0;
851 s);
853 "Finished intersection, %d items remain\n",
855 qsort (s->sorted_elements,
857 sizeof(struct MpiElement),
858 &element_cmp);
859 off = 0;
860 while (off < s->used_element_count)
861 {
862 todo_count = s->used_element_count - off;
863 if (todo_count > ELEMENT_CAPACITY)
864 todo_count = ELEMENT_CAPACITY;
866 "Sending %u/%u crypto values to Bob\n",
867 (unsigned int) todo_count,
868 (unsigned int) s->used_element_count);
869
870 e =
872 todo_count
873 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext),
875 msg->contained_element_count = htonl (todo_count);
877 a = gcry_mpi_new (0);
878 for (i = off; i < off + todo_count; i++)
879 {
880 gcry_mpi_add (a, s->sorted_elements[i].value, my_offset);
882 3 ==
884 }
885 gcry_mpi_release (a);
886 off += todo_count;
887 GNUNET_MQ_send (s->cadet_mq, e);
888 }
889}
890
891
902static void
904 const struct GNUNET_SETI_Element *element,
905 uint64_t current_size,
907{
908 struct AliceServiceSession *s = cls;
910
911 switch (status)
912 {
914 /* this element has been removed from the set */
916 element->data);
917 GNUNET_assert (NULL != se);
919 "Intersection removed element with key %s and value %lld\n",
920 GNUNET_h2s (&se->key),
921 (long long) GNUNET_ntohll (se->value));
923 GNUNET_YES ==
925 element->data,
926 se));
927 GNUNET_free (se);
928 return;
929
931 s->intersection_op = NULL;
932 if (NULL != s->intersection_set)
933 {
935 s->intersection_set = NULL;
936 }
938 return;
940 /* unhandled status code */
941 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
942 if (NULL != s->intersection_listen)
943 {
945 s->intersection_listen = NULL;
946 }
947 s->intersection_op = NULL;
948 if (NULL != s->intersection_set)
949 {
951 s->intersection_set = NULL;
952 }
955 return;
956
957 default:
958 GNUNET_break (0);
959 return;
960 }
961}
962
963
979static void
981 const struct GNUNET_PeerIdentity *other_peer,
982 const struct GNUNET_MessageHeader *context_msg,
984{
985 struct AliceServiceSession *s = cls;
986
987 if (0 != GNUNET_memcmp (other_peer, &s->peer))
988 {
989 GNUNET_break_op (0);
990 return;
991 }
992 s->intersection_op = GNUNET_SETI_accept (request,
993 (struct
994 GNUNET_SETI_Option[]){ { 0 } },
996 s);
997 if (NULL == s->intersection_op)
998 {
999 GNUNET_break (0);
1002 return;
1003 }
1004 if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
1005 {
1006 GNUNET_break (0);
1009 return;
1010 }
1011}
1012
1013
1019static void
1021{
1022 struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1023 { GNUNET_MQ_hd_var_size (bobs_cryptodata_message,
1025 struct BobCryptodataMessage,
1026 s),
1028 bobs_cryptodata_multipart,
1031 s),
1033 struct ServiceRequestMessage *msg;
1034 struct GNUNET_MQ_Envelope *e;
1035
1037 "Creating new channel for session with key %s.\n",
1038 GNUNET_h2s (&s->session_id));
1040 s,
1041 &s->peer,
1042 &s->session_id,
1043 NULL,
1045 cadet_handlers);
1046 if (NULL == s->channel)
1047 {
1050 return;
1051 }
1054 &s->session_id,
1056 s);
1057 if (NULL == s->intersection_listen)
1058 {
1061 s->channel = NULL;
1063 return;
1064 }
1065
1066 e = GNUNET_MQ_msg (msg,
1068 msg->session_id = s->session_id;
1069 msg->public_key = my_pubkey;
1070 GNUNET_MQ_send (s->cadet_mq, e);
1071}
1072
1073
1082static int
1084 void *cls,
1086{
1087 struct AliceServiceSession *s = cls;
1088 uint32_t contained_count;
1089 uint16_t msize;
1090
1091 msize = ntohs (msg->header.size);
1092 contained_count = ntohl (msg->element_count_contained);
1093 if ((msize !=
1095 + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))) ||
1096 (0 == contained_count) ||
1097 (s->total == s->client_received_element_count) ||
1098 (s->total < s->client_received_element_count + contained_count))
1099 {
1100 GNUNET_break_op (0);
1101 return GNUNET_SYSERR;
1102 }
1103 return GNUNET_OK;
1104}
1105
1106
1114static void
1116 void *cls,
1118{
1119 struct AliceServiceSession *s = cls;
1120 uint32_t contained_count;
1121 const struct GNUNET_SCALARPRODUCT_Element *elements;
1122 struct GNUNET_SETI_Element set_elem;
1123 struct GNUNET_SCALARPRODUCT_Element *elem;
1124
1125 contained_count = ntohl (msg->element_count_contained);
1126 s->client_received_element_count += contained_count;
1127 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1128 for (uint32_t i = 0; i < contained_count; i++)
1129 {
1131 GNUNET_memcpy (elem,
1132 &elements[i],
1133 sizeof(struct GNUNET_SCALARPRODUCT_Element));
1136 &elem->key,
1137 elem,
1139 {
1140 GNUNET_break (0);
1141 GNUNET_free (elem);
1142 continue;
1143 }
1144 set_elem.data = &elem->key;
1145 set_elem.size = sizeof(elem->key);
1146 set_elem.element_type = 0;
1147 GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
1148 s->used_element_count++;
1149 }
1152 {
1153 /* more to come */
1154 return;
1155 }
1157}
1158
1159
1168static int
1170 const struct AliceComputationMessage *msg)
1171{
1172 struct AliceServiceSession *s = cls;
1173 uint16_t msize;
1174 uint32_t total_count;
1175 uint32_t contained_count;
1176
1177 if (NULL != s->intersected_elements)
1178 {
1179 /* only one concurrent session per client connection allowed,
1180 simplifies logic a lot... */
1181 GNUNET_break (0);
1182 return GNUNET_SYSERR;
1183 }
1184 msize = ntohs (msg->header.size);
1185 total_count = ntohl (msg->element_count_total);
1186 contained_count = ntohl (msg->element_count_contained);
1187 if ((0 == total_count) || (0 == contained_count) ||
1188 (msize !=
1189 (sizeof(struct AliceComputationMessage)
1190 + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))))
1191 {
1192 GNUNET_break_op (0);
1193 return GNUNET_SYSERR;
1194 }
1195 return GNUNET_OK;
1196}
1197
1198
1206static void
1208 const struct AliceComputationMessage *msg)
1209{
1210 struct AliceServiceSession *s = cls;
1211 uint32_t contained_count;
1212 uint32_t total_count;
1213 const struct GNUNET_SCALARPRODUCT_Element *elements;
1214 struct GNUNET_SETI_Element set_elem;
1215 struct GNUNET_SCALARPRODUCT_Element *elem;
1216
1217 total_count = ntohl (msg->element_count_total);
1218 contained_count = ntohl (msg->element_count_contained);
1219 s->peer = msg->peer;
1221 s->total = total_count;
1222 s->client_received_element_count = contained_count;
1223 s->session_id = msg->session_key;
1224 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1228
1229 for (uint32_t i = 0; i < contained_count; i++)
1230 {
1231 if (0 == GNUNET_ntohll (elements[i].value))
1232 continue;
1234 GNUNET_memcpy (elem,
1235 &elements[i],
1236 sizeof(struct GNUNET_SCALARPRODUCT_Element));
1239 &elem->key,
1240 elem,
1242 {
1243 /* element with same key encountered twice! */
1244 GNUNET_break (0);
1245 GNUNET_free (elem);
1246 continue;
1247 }
1248 set_elem.data = &elem->key;
1249 set_elem.size = sizeof(elem->key);
1250 set_elem.element_type = 0;
1252 &set_elem,
1253 NULL,
1254 NULL);
1255 s->used_element_count++;
1256 }
1259 {
1260 /* wait for multipart msg */
1261 return;
1262 }
1264}
1265
1266
1272static void
1273shutdown_task (void *cls)
1274{
1275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down, initiating cleanup.\n");
1276 // FIXME: we have to cut our connections to CADET first!
1277 if (NULL != my_cadet)
1278 {
1280 my_cadet = NULL;
1281 }
1282}
1283
1284
1295static void *
1297 struct GNUNET_SERVICE_Client *client,
1298 struct GNUNET_MQ_Handle *mq)
1299{
1300 struct AliceServiceSession *s;
1301
1302 s = GNUNET_new (struct AliceServiceSession);
1303 s->client = client;
1304 s->client_mq = mq;
1305 return s;
1306}
1307
1308
1319static void
1322 void *app_cls)
1323{
1324 struct AliceServiceSession *s = app_cls;
1325
1327 "Client %p disconnected from us.\n",
1328 client);
1329 s->client = NULL;
1330 s->client_mq = NULL;
1332}
1333
1334
1342static void
1343run (void *cls,
1344 const struct GNUNET_CONFIGURATION_Handle *c,
1346{
1347 cfg = c;
1348 /*
1349 offset has to be sufficiently small to allow computation of:
1350 m1+m2 mod n == (S + a) + (S + b) mod n,
1351 if we have more complex operations, this factor needs to be lowered */
1352 my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1353 gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
1357 if (NULL == my_cadet)
1358 {
1359 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to CADET failed\n"));
1361 return;
1362 }
1363}
1364
1365
1370 "scalarproduct-alice",
1372 &run,
1375 NULL,
1376 GNUNET_MQ_hd_var_size (alice_client_message,
1379 NULL),
1381 alice_client_message_multipart,
1384 NULL),
1386
1387
1388/* 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 mp_limb_t u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
struct GNUNET_HashCode key
The key used in the DHT.
static char * value
Value of the record to add/remove.
static int status
The program status; 0 for success.
Definition: gnunet-nse.c:39
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 void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected.
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.
#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_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:894
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Indicate readiness to receive the next message on a channel.
Definition: cadet_api.c:872
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:830
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected channel.
Definition: cadet_api.c:1066
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:774
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
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
int 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.
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.
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.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ 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:567
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:1340
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2489
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2408
@ 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
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
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
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
void GNUNET_SETI_operation_cancel(struct GNUNET_SETI_OperationHandle *oh)
Cancel the given set operation.
Definition: seti_api.c:335
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...