GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
gnunet-service-scalarproduct_alice.c File Reference

scalarproduct service implementation More...

#include "platform.h"
#include <limits.h>
#include <gcrypt.h>
#include "gnunet_util_lib.h"
#include "gnunet_cadet_service.h"
#include "gnunet_protocols.h"
#include "gnunet_scalarproduct_service.h"
#include "gnunet_seti_service.h"
#include "scalarproduct.h"
#include "gnunet-service-scalarproduct.h"
#include "gnunet_constants.h"
Include dependency graph for gnunet-service-scalarproduct_alice.c:

Go to the source code of this file.

Data Structures

struct  MpiElement
 An encrypted element key-value pair. More...
 
struct  AliceServiceSession
 A scalarproduct session which tracks a request form the client to our final response. More...
 

Macros

#define LOG(kind, ...)    GNUNET_log_from (kind, "scalarproduct-alice", __VA_ARGS__)
 
#define ELEMENT_CAPACITY
 Maximum number of elements we can put into a single cryptodata message.
 

Functions

static int free_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
 Iterator called to free elements.
 
static void destroy_service_session (struct AliceServiceSession *s)
 Destroy session state, we are done with it.
 
static void prepare_client_end_notification (struct AliceServiceSession *session)
 Notify the client that the session has failed.
 
static void transmit_client_response (struct AliceServiceSession *s)
 Prepare the final (positive) response we will send to Alice's client.
 
static void cb_channel_destruction (void *cls, const struct GNUNET_CADET_Channel *channel)
 Function called whenever a channel is destroyed.
 
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 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 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 scalarproduct with.
 
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 scalarproduct with.
 
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 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 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 int element_cmp (const void *a, const void *b)
 Compare two struct MpiValues by key for sorting.
 
static void send_alices_cryptodata_message (struct AliceServiceSession *s)
 Send the cryptographic data from Alice to Bob.
 
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 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 int check_alice_client_message_multipart (void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
 We're receiving additional set data.
 
static void handle_alice_client_message_multipart (void *cls, const struct ComputationBobCryptodataMultipartMessage *msg)
 We're receiving additional set data.
 
static int check_alice_client_message (void *cls, const struct AliceComputationMessage *msg)
 Handler for Alice's client request message.
 
static void handle_alice_client_message (void *cls, const struct AliceComputationMessage *msg)
 Handler for Alice's client request message.
 
static void shutdown_task (void *cls)
 Task run during shutdown.
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
 A client connected.
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_cls)
 A client disconnected.
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
 Initialization of the program and message handlers.
 
 GNUNET_SERVICE_MAIN (GNUNET_OS_project_data_gnunet(), "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.
 

Variables

static const struct GNUNET_CONFIGURATION_Handlecfg
 GNUnet configuration handle.
 
static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey
 Service's own public key.
 
static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey
 Service's own private key.
 
static gcry_mpi_t my_offset
 Service's offset for values that could possibly be negative but are plaintext for encryption.
 
static struct GNUNET_CADET_Handlemy_cadet
 Handle to the CADET service.
 

Detailed Description

scalarproduct service implementation

Author
Christian M. Fuchs
Christian Grothoff

Definition in file gnunet-service-scalarproduct_alice.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)     GNUNET_log_from (kind, "scalarproduct-alice", __VA_ARGS__)

Definition at line 38 of file gnunet-service-scalarproduct_alice.c.

44{
50 const struct GNUNET_HashCode *key;
51
55 gcry_mpi_t value;
56};
57
58
64{
69
74
79
84
89
95
101
107
112
117
122
127
132
137
142
146 gcry_mpi_t product;
147
152 uint32_t total;
153
159 uint32_t used_element_count;
160
166
172
180
185 int in_destroy;
186};
187
188
192static const struct GNUNET_CONFIGURATION_Handle *cfg;
193
198
203
207static gcry_mpi_t my_offset;
208
212static struct GNUNET_CADET_Handle *my_cadet;
213
214
223static int
224free_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
225{
227
228 GNUNET_free (e);
229 return GNUNET_OK;
230}
231
232
238static void
240{
241 if (GNUNET_YES == s->in_destroy)
242 return;
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
311static void
313{
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
337static void
339{
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);
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 }
398 "Sent result to client, session %s has ended!\n",
399 GNUNET_h2s (&s->session_id));
400}
401
402
412static void
413cb_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
438static gcry_mpi_t
439compute_square_sum_mpi_elements (const struct MpiElement *vector,
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
465static gcry_mpi_t
466compute_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
490static 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
600static int
602 void *cls,
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) ||
617 {
618 GNUNET_break (0);
619 return GNUNET_SYSERR;
620 }
621 return GNUNET_OK;
622}
623
624
632static void
634 void *cls,
636{
637 struct AliceServiceSession *s = cls;
639 size_t i;
640 uint32_t contained;
641
642 contained = ntohl (msg->contained_element_count);
644 "Received %u additional crypto values from Bob\n",
645 (unsigned int) contained);
646
647 payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
648 /* Convert each k[][perm] to its MPI_value */
649 for (i = 0; i < contained; i++)
650 {
652 &payload[2 * i],
653 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
655 &payload[2 * i],
656 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
657 }
658 s->cadet_received_element_count += contained;
661 return; /* more to come */
662
665}
666
667
677static int
679 const struct BobCryptodataMessage *msg)
680{
681 struct AliceServiceSession *s = cls;
682 uint32_t contained;
683 uint16_t msg_size;
684 size_t required_size;
685
686 msg_size = ntohs (msg->header.size);
687 contained = ntohl (msg->contained_element_count);
688 required_size =
689 sizeof(struct BobCryptodataMessage)
690 + 2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)
691 + 2 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
692 if ((msg_size != required_size) || (contained > UINT16_MAX) ||
693 (s->used_element_count < contained))
694 {
695 GNUNET_break_op (0);
696 return GNUNET_SYSERR;
697 }
698 if (NULL == s->sorted_elements)
699 {
700 /* we're not ready yet, how can Bob be? */
701 GNUNET_break_op (0);
702 return GNUNET_SYSERR;
703 }
705 {
706 /* we're not ready yet, how can Bob be? */
707 GNUNET_break_op (0);
708 return GNUNET_SYSERR;
709 }
710 return GNUNET_OK;
711}
712
713
721static void
723 const struct BobCryptodataMessage *msg)
724{
725 struct AliceServiceSession *s = cls;
727 uint32_t i;
728 uint32_t contained;
729
730 contained = ntohl (msg->contained_element_count);
732 "Received %u crypto values from Bob\n",
733 (unsigned int) contained);
734 payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
735 GNUNET_memcpy (&s->s,
736 &payload[0],
737 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
739 &payload[1],
740 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
741 payload = &payload[2];
742
747 for (i = 0; i < contained; i++)
748 {
749 GNUNET_memcpy (&s->r[i],
750 &payload[2 * i],
751 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
752 GNUNET_memcpy (&s->r_prime[i],
753 &payload[2 * i + 1],
754 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
755 }
756 s->cadet_received_element_count = contained;
758
760 {
761 /* More to come */
762 return;
763 }
766}
767
768
777static int
778copy_element_cb (void *cls, const struct GNUNET_HashCode *key, void *value)
779{
780 struct AliceServiceSession *s = cls;
782 gcry_mpi_t mval;
783 int64_t val;
784
785 mval = gcry_mpi_new (0);
786 val = (int64_t) GNUNET_ntohll (e->value);
787 if (0 > val)
788 gcry_mpi_sub_ui (mval, mval, -val);
789 else
790 gcry_mpi_add_ui (mval, mval, val);
794 return GNUNET_OK;
795}
796
797
805static int
806element_cmp (const void *a, const void *b)
807{
808 const struct MpiElement *ma = a;
809 const struct MpiElement *mb = b;
810
811 return GNUNET_CRYPTO_hash_cmp (ma->key, mb->key);
812}
813
814
819#define ELEMENT_CAPACITY \
820 ((GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE - 1 \
821 - sizeof(struct AliceCryptodataMessage)) \
822 / sizeof(struct GNUNET_CRYPTO_PaillierCiphertext))
823
824
831static void
833{
835 struct GNUNET_MQ_Envelope *e;
837 unsigned int i;
838 uint32_t todo_count;
839 gcry_mpi_t a;
840 uint32_t off;
841
844 * sizeof(struct MpiElement));
845 s->used_element_count = 0;
848 s);
850 "Finished intersection, %d items remain\n",
852 qsort (s->sorted_elements,
854 sizeof(struct MpiElement),
855 &element_cmp);
856 off = 0;
857 while (off < s->used_element_count)
858 {
859 todo_count = s->used_element_count - off;
860 if (todo_count > ELEMENT_CAPACITY)
861 todo_count = ELEMENT_CAPACITY;
863 "Sending %u/%u crypto values to Bob\n",
864 (unsigned int) todo_count,
865 (unsigned int) s->used_element_count);
866
867 e =
869 todo_count
870 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext),
872 msg->contained_element_count = htonl (todo_count);
874 a = gcry_mpi_new (0);
875 for (i = off; i < off + todo_count; i++)
876 {
877 gcry_mpi_add (a, s->sorted_elements[i].value, my_offset);
879 3 ==
881 }
882 gcry_mpi_release (a);
883 off += todo_count;
884 GNUNET_MQ_send (s->cadet_mq, e);
885 }
886}
887
888
899static void
901 const struct GNUNET_SETI_Element *element,
902 uint64_t current_size,
904{
905 struct AliceServiceSession *s = cls;
907
908 switch (status)
909 {
911 /* this element has been removed from the set */
913 element->data);
914 GNUNET_assert (NULL != se);
916 "Intersection removed element with key %s and value %lld\n",
917 GNUNET_h2s (&se->key),
918 (long long) GNUNET_ntohll (se->value));
920 GNUNET_YES ==
922 element->data,
923 se));
924 GNUNET_free (se);
925 return;
926
928 s->intersection_op = NULL;
929 if (NULL != s->intersection_set)
930 {
932 s->intersection_set = NULL;
933 }
935 return;
937 /* unhandled status code */
938 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
939 if (NULL != s->intersection_listen)
940 {
942 s->intersection_listen = NULL;
943 }
944 s->intersection_op = NULL;
945 if (NULL != s->intersection_set)
946 {
948 s->intersection_set = NULL;
949 }
952 return;
953
954 default:
955 GNUNET_break (0);
956 return;
957 }
958}
959
960
976static void
978 const struct GNUNET_PeerIdentity *other_peer,
979 const struct GNUNET_MessageHeader *context_msg,
981{
982 struct AliceServiceSession *s = cls;
983
984 if (0 != GNUNET_memcmp (other_peer, &s->peer))
985 {
986 GNUNET_break_op (0);
987 return;
988 }
989 s->intersection_op = GNUNET_SETI_accept (request,
990 (struct
991 GNUNET_SETI_Option[]){ { 0 } },
993 s);
994 if (NULL == s->intersection_op)
995 {
996 GNUNET_break (0);
999 return;
1000 }
1001 if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
1002 {
1003 GNUNET_break (0);
1006 return;
1007 }
1008}
1009
1010
1016static void
1018{
1019 struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1020 { GNUNET_MQ_hd_var_size (bobs_cryptodata_message,
1022 struct BobCryptodataMessage,
1023 s),
1025 bobs_cryptodata_multipart,
1028 s),
1030 struct ServiceRequestMessage *msg;
1031 struct GNUNET_MQ_Envelope *e;
1032
1034 "Creating new channel for session with key %s.\n",
1035 GNUNET_h2s (&s->session_id));
1037 s,
1038 &s->peer,
1039 &s->session_id,
1040 NULL,
1042 cadet_handlers);
1043 if (NULL == s->channel)
1044 {
1047 return;
1048 }
1051 &s->session_id,
1053 s);
1054 if (NULL == s->intersection_listen)
1055 {
1058 s->channel = NULL;
1060 return;
1061 }
1062
1063 e = GNUNET_MQ_msg (msg,
1065 msg->session_id = s->session_id;
1066 msg->public_key = my_pubkey;
1067 GNUNET_MQ_send (s->cadet_mq, e);
1068}
1069
1070
1079static int
1081 void *cls,
1083{
1084 struct AliceServiceSession *s = cls;
1085 uint32_t contained_count;
1086 uint16_t msize;
1087
1088 msize = ntohs (msg->header.size);
1089 contained_count = ntohl (msg->element_count_contained);
1090 if ((msize !=
1092 + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))) ||
1093 (0 == contained_count) ||
1094 (s->total == s->client_received_element_count) ||
1095 (s->total < s->client_received_element_count + contained_count))
1096 {
1097 GNUNET_break_op (0);
1098 return GNUNET_SYSERR;
1099 }
1100 return GNUNET_OK;
1101}
1102
1103
1111static void
1113 void *cls,
1115{
1116 struct AliceServiceSession *s = cls;
1117 uint32_t contained_count;
1118 const struct GNUNET_SCALARPRODUCT_Element *elements;
1119 struct GNUNET_SETI_Element set_elem;
1120 struct GNUNET_SCALARPRODUCT_Element *elem;
1121
1122 contained_count = ntohl (msg->element_count_contained);
1123 s->client_received_element_count += contained_count;
1124 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1125 for (uint32_t i = 0; i < contained_count; i++)
1126 {
1128 GNUNET_memcpy (elem,
1129 &elements[i],
1130 sizeof(struct GNUNET_SCALARPRODUCT_Element));
1133 &elem->key,
1134 elem,
1136 {
1137 GNUNET_break (0);
1138 GNUNET_free (elem);
1139 continue;
1140 }
1141 set_elem.data = &elem->key;
1142 set_elem.size = sizeof(elem->key);
1143 set_elem.element_type = 0;
1144 GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
1145 s->used_element_count++;
1146 }
1149 {
1150 /* more to come */
1151 return;
1152 }
1154}
1155
1156
1165static int
1167 const struct AliceComputationMessage *msg)
1168{
1169 struct AliceServiceSession *s = cls;
1170 uint16_t msize;
1171 uint32_t total_count;
1172 uint32_t contained_count;
1173
1174 if (NULL != s->intersected_elements)
1175 {
1176 /* only one concurrent session per client connection allowed,
1177 simplifies logic a lot... */
1178 GNUNET_break (0);
1179 return GNUNET_SYSERR;
1180 }
1181 msize = ntohs (msg->header.size);
1182 total_count = ntohl (msg->element_count_total);
1183 contained_count = ntohl (msg->element_count_contained);
1184 if ((0 == total_count) || (0 == contained_count) ||
1185 (msize !=
1186 (sizeof(struct AliceComputationMessage)
1187 + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))))
1188 {
1189 GNUNET_break_op (0);
1190 return GNUNET_SYSERR;
1191 }
1192 return GNUNET_OK;
1193}
1194
1195
1203static void
1205 const struct AliceComputationMessage *msg)
1206{
1207 struct AliceServiceSession *s = cls;
1208 uint32_t contained_count;
1209 uint32_t total_count;
1210 const struct GNUNET_SCALARPRODUCT_Element *elements;
1211 struct GNUNET_SETI_Element set_elem;
1212 struct GNUNET_SCALARPRODUCT_Element *elem;
1213
1214 total_count = ntohl (msg->element_count_total);
1215 contained_count = ntohl (msg->element_count_contained);
1216 s->peer = msg->peer;
1218 s->total = total_count;
1219 s->client_received_element_count = contained_count;
1220 s->session_id = msg->session_key;
1221 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1225
1226 for (uint32_t i = 0; i < contained_count; i++)
1227 {
1228 if (0 == GNUNET_ntohll (elements[i].value))
1229 continue;
1231 GNUNET_memcpy (elem,
1232 &elements[i],
1233 sizeof(struct GNUNET_SCALARPRODUCT_Element));
1236 &elem->key,
1237 elem,
1239 {
1240 /* element with same key encountered twice! */
1241 GNUNET_break (0);
1242 GNUNET_free (elem);
1243 continue;
1244 }
1245 set_elem.data = &elem->key;
1246 set_elem.size = sizeof(elem->key);
1247 set_elem.element_type = 0;
1249 &set_elem,
1250 NULL,
1251 NULL);
1252 s->used_element_count++;
1253 }
1256 {
1257 /* wait for multipart msg */
1258 return;
1259 }
1261}
1262
1263
1269static void
1270shutdown_task (void *cls)
1271{
1272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down, initiating cleanup.\n");
1273 // FIXME: we have to cut our connections to CADET first!
1274 if (NULL != my_cadet)
1275 {
1277 my_cadet = NULL;
1278 }
1279}
1280
1281
1292static void *
1293client_connect_cb (void *cls,
1294 struct GNUNET_SERVICE_Client *client,
1295 struct GNUNET_MQ_Handle *mq)
1296{
1297 struct AliceServiceSession *s;
1298
1299 s = GNUNET_new (struct AliceServiceSession);
1300 s->client = client;
1301 s->client_mq = mq;
1302 return s;
1303}
1304
1305
1316static void
1317client_disconnect_cb (void *cls,
1319 void *app_cls)
1320{
1321 struct AliceServiceSession *s = app_cls;
1322
1324 "Client %p disconnected from us.\n",
1325 client);
1326 s->client = NULL;
1327 s->client_mq = NULL;
1329}
1330
1331
1339static void
1340run (void *cls,
1341 const struct GNUNET_CONFIGURATION_Handle *c,
1343{
1344 cfg = c;
1345 /*
1346 offset has to be sufficiently small to allow computation of:
1347 m1+m2 mod n == (S + a) + (S + b) mod n,
1348 if we have more complex operations, this factor needs to be lowered */
1349 my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1350 gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
1354 if (NULL == my_cadet)
1355 {
1356 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to CADET failed\n"));
1358 return;
1359 }
1360}
1361
1362
1368 "scalarproduct-alice",
1370 &run,
1373 NULL,
1374 GNUNET_MQ_hd_var_size (alice_client_message,
1377 NULL),
1379 alice_client_message_multipart,
1382 NULL),
1384
1385
1386/* end of gnunet-service-scalarproduct_alice.c */
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.
struct GNUNET_SCHEDULER_Task * shutdown_task
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?
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 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.
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.
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition cadet_api.c:897
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Indicate readiness to receive the next message on a channel.
Definition cadet_api.c:875
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition cadet_api.c:833
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:1081
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition cadet_api.c:777
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:1030
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.
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.
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.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ 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:305
#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.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
#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:1339
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2462
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2433
@ 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:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
#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...
Message type passed from client to service to initiate a request or responder role.
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.
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.
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:249
Handle to a service.
Definition service.c:116
Element stored in a set.
const void * data
Actual data of the element.
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.
int64_t value
a_i value, not disclosed to Bob.
Message type passed from requesting service Alice to responding service Bob to initiate a request and...

◆ ELEMENT_CAPACITY

#define ELEMENT_CAPACITY
Value:
- sizeof(struct AliceCryptodataMessage)) \
#define GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE
Maximum message size that can be sent on CADET.

Maximum number of elements we can put into a single cryptodata message.

Definition at line 820 of file gnunet-service-scalarproduct_alice.c.

Function Documentation

◆ free_element_cb()

static int free_element_cb ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Iterator called to free elements.

Parameters
clsthe struct AliceServiceSession * (unused)
keythe key (unused)
valuevalue to free
Returns
GNUNET_OK (continue to iterate)

Definition at line 225 of file gnunet-service-scalarproduct_alice.c.

226{
228
229 GNUNET_free (e);
230 return GNUNET_OK;
231}

References GNUNET_free, GNUNET_OK, and value.

Referenced by destroy_service_session().

Here is the caller graph for this function:

◆ destroy_service_session()

static void destroy_service_session ( struct AliceServiceSession s)
static

Destroy session state, we are done with it.

Parameters
sthe session to free elements from

Definition at line 240 of file gnunet-service-scalarproduct_alice.c.

241{
242 if (GNUNET_YES == s->in_destroy)
243 return;
245 if (NULL != s->client)
246 {
247 struct GNUNET_SERVICE_Client *c = s->client;
248
249 s->client = NULL;
251 }
252 if (NULL != s->channel)
253 {
255 s->channel = NULL;
256 }
257 if (NULL != s->intersected_elements)
258 {
261 s);
263 s->intersected_elements = NULL;
264 }
265 if (NULL != s->intersection_listen)
266 {
268 s->intersection_listen = NULL;
269 }
270 if (NULL != s->intersection_op)
271 {
273 s->intersection_op = NULL;
274 }
275 if (NULL != s->intersection_set)
276 {
278 s->intersection_set = NULL;
279 }
280 if (NULL != s->sorted_elements)
281 {
282 for (unsigned int i = 0; i < s->used_element_count; i++)
283 gcry_mpi_release (s->sorted_elements[i].value);
285 s->sorted_elements = NULL;
286 }
287 if (NULL != s->r)
288 {
289 GNUNET_free (s->r);
290 s->r = NULL;
291 }
292 if (NULL != s->r_prime)
293 {
294 GNUNET_free (s->r_prime);
295 s->r_prime = NULL;
296 }
297 if (NULL != s->product)
298 {
299 gcry_mpi_release (s->product);
300 s->product = NULL;
301 }
302 GNUNET_free (s);
303}

References AliceServiceSession::channel, AliceServiceSession::client, free_element_cb(), GNUNET_CADET_channel_destroy(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_free, GNUNET_SERVICE_client_drop(), GNUNET_SETI_destroy(), GNUNET_SETI_listen_cancel(), GNUNET_SETI_operation_cancel(), GNUNET_YES, AliceServiceSession::in_destroy, AliceServiceSession::intersected_elements, AliceServiceSession::intersection_listen, AliceServiceSession::intersection_op, AliceServiceSession::intersection_set, AliceServiceSession::product, AliceServiceSession::r, AliceServiceSession::r_prime, AliceServiceSession::sorted_elements, AliceServiceSession::used_element_count, and MpiElement::value.

Referenced by client_disconnect_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ prepare_client_end_notification()

static void prepare_client_end_notification ( struct AliceServiceSession session)
static

Notify the client that the session has failed.

A message gets sent to Alice's client if we encountered any error.

Parameters
sessionthe associated client session to fail or succeed

Definition at line 313 of file gnunet-service-scalarproduct_alice.c.

314{
316 struct GNUNET_MQ_Envelope *e;
317
318 if (NULL == session->client_mq)
319 return; /* no client left to be notified */
320 GNUNET_log (
322 "Sending session-end notification with status %d to client for session %s\n",
323 session->status,
324 GNUNET_h2s (&session->session_id));
326 msg->product_length = htonl (0);
327 msg->status = htonl (session->status);
328 GNUNET_MQ_send (session->client_mq, e);
329}

References AliceServiceSession::client_mq, GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT, GNUNET_MQ_msg, GNUNET_MQ_send(), msg, AliceServiceSession::session_id, and AliceServiceSession::status.

Referenced by cb_channel_destruction(), cb_intersection_element_removed(), cb_intersection_request_alice(), client_request_complete_alice(), and transmit_client_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_client_response()

static void transmit_client_response ( struct AliceServiceSession s)
static

Prepare the final (positive) response we will send to Alice's client.

Parameters
sthe session associated with our client.

Definition at line 339 of file gnunet-service-scalarproduct_alice.c.

340{
342 struct GNUNET_MQ_Envelope *e;
343 unsigned char *product_exported = NULL;
344 size_t product_length = 0;
345 int32_t range;
346 gcry_error_t rc;
347 int sign;
348 gcry_mpi_t value;
349
350 if (NULL == s->product)
351 {
352 GNUNET_break (0);
354 return;
355 }
356 value = gcry_mpi_new (0);
357 sign = gcry_mpi_cmp_ui (s->product, 0);
358 if (0 > sign)
359 {
360 range = -1;
361 gcry_mpi_sub (value, value, s->product);
362 }
363 else if (0 < sign)
364 {
365 range = 1;
366 gcry_mpi_add (value, value, s->product);
367 }
368 else
369 {
370 /* result is exactly zero */
371 range = 0;
372 }
373 gcry_mpi_release (s->product);
374 s->product = NULL;
375
376 if ((0 != range) && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
377 &product_exported,
378 &product_length,
379 value))))
380 {
381 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
383 return;
384 }
385 gcry_mpi_release (value);
387 product_length,
390 msg->range = htonl (range);
391 msg->product_length = htonl (product_length);
392 if (NULL != product_exported)
393 {
394 GNUNET_memcpy (&msg[1], product_exported, product_length);
395 GNUNET_free (product_exported);
396 }
399 "Sent result to client, session %s has ended!\n",
400 GNUNET_h2s (&s->session_id));
401}

References AliceServiceSession::client_mq, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_h2s(), GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_SCALARPRODUCT_STATUS_SUCCESS, LOG_GCRY, msg, prepare_client_end_notification(), AliceServiceSession::product, AliceServiceSession::session_id, and value.

Referenced by handle_bobs_cryptodata_message(), and handle_bobs_cryptodata_multipart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cb_channel_destruction()

static void cb_channel_destruction ( void *  cls,
const struct GNUNET_CADET_Channel channel 
)
static

Function called whenever a channel is destroyed.

Should clean up any associated state.

It must NOT call GNUNET_CADET_channel_destroy() on the channel.

Parameters
clsour struct AliceServiceSession
channelconnection to the other end (henceforth invalid)

Definition at line 414 of file gnunet-service-scalarproduct_alice.c.

415{
416 struct AliceServiceSession *s = cls;
417
419 "Peer disconnected, terminating session %s with peer %s\n",
420 GNUNET_h2s (&s->session_id),
421 GNUNET_i2s (&s->peer));
423 {
424 /* We didn't get an answer yet, fail with error */
427 }
428 s->channel = NULL;
429}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_SCALARPRODUCT_STATUS_ACTIVE, GNUNET_SCALARPRODUCT_STATUS_FAILURE, prepare_client_end_notification(), and AliceServiceSession::s.

Referenced by client_request_complete_alice().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ compute_square_sum_mpi_elements()

static gcry_mpi_t compute_square_sum_mpi_elements ( const struct MpiElement vector,
uint32_t  length 
)
static

Computes the square sum over a vector of a given length.

Parameters
vectorthe vector to compute over
lengththe length of the vector
Returns
an MPI value containing the calculated sum, never NULL

Definition at line 440 of file gnunet-service-scalarproduct_alice.c.

442{
443 gcry_mpi_t elem;
444 gcry_mpi_t sum;
445 uint32_t i;
446
447 GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
448 GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
449 for (i = 0; i < length; i++)
450 {
451 gcry_mpi_mul (elem, vector[i].value, vector[i].value);
452 gcry_mpi_add (sum, sum, elem);
453 }
454 gcry_mpi_release (elem);
455 return sum;
456}

References GNUNET_assert, and value.

Referenced by compute_scalar_product().

Here is the caller graph for this function:

◆ compute_square_sum()

static gcry_mpi_t compute_square_sum ( const gcry_mpi_t *  vector,
uint32_t  length 
)
static

Computes the square sum over a vector of a given length.

Parameters
vectorthe vector to compute over
lengththe length of the vector
Returns
an MPI value containing the calculated sum, never NULL

Definition at line 467 of file gnunet-service-scalarproduct_alice.c.

468{
469 gcry_mpi_t elem;
470 gcry_mpi_t sum;
471 uint32_t i;
472
473 GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
474 GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
475 for (i = 0; i < length; i++)
476 {
477 gcry_mpi_mul (elem, vector[i], vector[i]);
478 gcry_mpi_add (sum, sum, elem);
479 }
480 gcry_mpi_release (elem);
481 return sum;
482}

References GNUNET_assert.

Referenced by compute_scalar_product().

Here is the caller graph for this function:

◆ compute_scalar_product()

static gcry_mpi_t compute_scalar_product ( struct AliceServiceSession session)
static

Compute our scalar product, done by Alice.

Parameters
sessionthe session associated with this computation
Returns
product as MPI, never NULL

Definition at line 492 of file gnunet-service-scalarproduct_alice.c.

493{
494 uint32_t count;
495 gcry_mpi_t t;
496 gcry_mpi_t u;
497 gcry_mpi_t u_prime;
498 gcry_mpi_t p;
499 gcry_mpi_t p_prime;
500 gcry_mpi_t tmp;
501 gcry_mpi_t r[session->used_element_count];
502 gcry_mpi_t r_prime[session->used_element_count];
503 gcry_mpi_t s;
504 gcry_mpi_t s_prime;
505 unsigned int i;
506
507 count = session->used_element_count;
508 // due to the introduced static offset S, we now also have to remove this
509 // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
510 // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
511 for (i = 0; i < count; i++)
512 {
513 r[i] = gcry_mpi_new (0);
515 &my_pubkey,
516 &session->r[i],
517 r[i]);
518 gcry_mpi_sub (r[i], r[i], my_offset);
519 gcry_mpi_sub (r[i], r[i], my_offset);
520 r_prime[i] = gcry_mpi_new (0);
522 &my_pubkey,
523 &session->r_prime[i],
524 r_prime[i]);
525 gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
526 gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
527 }
528
529 // calculate t = sum(ai)
531 // calculate U
532 u = gcry_mpi_new (0);
533 tmp = compute_square_sum (r, count);
534 gcry_mpi_sub (u, u, tmp);
535 gcry_mpi_release (tmp);
536
537 // calculate U'
538 u_prime = gcry_mpi_new (0);
539 tmp = compute_square_sum (r_prime, count);
540 gcry_mpi_sub (u_prime, u_prime, tmp);
541
542 GNUNET_assert (p = gcry_mpi_new (0));
543 GNUNET_assert (p_prime = gcry_mpi_new (0));
544 GNUNET_assert (s = gcry_mpi_new (0));
545 GNUNET_assert (s_prime = gcry_mpi_new (0));
546
547 // compute P
550 &my_pubkey,
551 &session->s_prime,
552 s_prime);
553
554 // compute P
555 gcry_mpi_add (p, s, t);
556 gcry_mpi_add (p, p, u);
557
558 // compute P'
559 gcry_mpi_add (p_prime, s_prime, t);
560 gcry_mpi_add (p_prime, p_prime, u_prime);
561
562 gcry_mpi_release (t);
563 gcry_mpi_release (u);
564 gcry_mpi_release (u_prime);
565 gcry_mpi_release (s);
566 gcry_mpi_release (s_prime);
567
568 // compute product
569 gcry_mpi_sub (p, p, p_prime);
570 gcry_mpi_release (p_prime);
571 tmp = gcry_mpi_set_ui (tmp, 2);
572 gcry_mpi_div (p, NULL, p, tmp, 0);
573
574 gcry_mpi_release (tmp);
575 for (i = 0; i < count; i++)
576 {
577 gcry_mpi_release (session->sorted_elements[i].value);
578 gcry_mpi_release (r[i]);
579 gcry_mpi_release (r_prime[i]);
580 }
581 GNUNET_free (session->sorted_elements);
582 session->sorted_elements = NULL;
583 GNUNET_free (session->r);
584 session->r = NULL;
585 GNUNET_free (session->r_prime);
586 session->r_prime = NULL;
587
588 return p;
589}

References compute_square_sum(), compute_square_sum_mpi_elements(), GNUNET_assert, GNUNET_CRYPTO_paillier_decrypt(), GNUNET_free, my_offset, my_privkey, my_pubkey, p, AliceServiceSession::r, AliceServiceSession::r_prime, AliceServiceSession::s, AliceServiceSession::s_prime, AliceServiceSession::sorted_elements, t, u, AliceServiceSession::used_element_count, and MpiElement::value.

Referenced by handle_bobs_cryptodata_message(), and handle_bobs_cryptodata_multipart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_bobs_cryptodata_multipart()

static int check_bobs_cryptodata_multipart ( void *  cls,
const struct BobCryptodataMultipartMessage msg 
)
static

Check a multipart chunk of a response we got from another service we wanted to calculate a scalarproduct with.

Parameters
clsthe struct AliceServiceSession
msgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 602 of file gnunet-service-scalarproduct_alice.c.

605{
606 struct AliceServiceSession *s = cls;
607 uint32_t contained;
608 size_t msg_size;
609 size_t required_size;
610
611 msg_size = ntohs (msg->header.size);
612 contained = ntohl (msg->contained_element_count);
613 required_size =
614 sizeof(struct BobCryptodataMultipartMessage)
615 + 2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
616 if ((required_size != msg_size) ||
618 {
619 GNUNET_break (0);
620 return GNUNET_SYSERR;
621 }
622 return GNUNET_OK;
623}

References AliceServiceSession::cadet_received_element_count, GNUNET_break, GNUNET_OK, GNUNET_SYSERR, msg, AliceServiceSession::s, GNUNET_MessageHeader::size, and AliceServiceSession::used_element_count.

◆ handle_bobs_cryptodata_multipart()

static void handle_bobs_cryptodata_multipart ( void *  cls,
const struct BobCryptodataMultipartMessage msg 
)
static

Handle a multipart chunk of a response we got from another service we wanted to calculate a scalarproduct with.

Parameters
clsthe struct AliceServiceSession
msgthe actual message

Definition at line 634 of file gnunet-service-scalarproduct_alice.c.

637{
638 struct AliceServiceSession *s = cls;
640 size_t i;
641 uint32_t contained;
642
643 contained = ntohl (msg->contained_element_count);
645 "Received %u additional crypto values from Bob\n",
646 (unsigned int) contained);
647
648 payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
649 /* Convert each k[][perm] to its MPI_value */
650 for (i = 0; i < contained; i++)
651 {
653 &payload[2 * i],
654 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
656 &payload[2 * i],
657 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
658 }
659 s->cadet_received_element_count += contained;
662 return; /* more to come */
663
666}

References AliceServiceSession::cadet_received_element_count, AliceServiceSession::channel, compute_scalar_product(), GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, msg, payload, AliceServiceSession::product, AliceServiceSession::r, AliceServiceSession::r_prime, AliceServiceSession::s, transmit_client_response(), and AliceServiceSession::used_element_count.

Here is the call graph for this function:

◆ check_bobs_cryptodata_message()

static int check_bobs_cryptodata_message ( void *  cls,
const struct BobCryptodataMessage msg 
)
static

Check a response we got from another service we wanted to calculate a scalarproduct with.

Parameters
clsour struct AliceServiceSession
msgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (we are done)

Definition at line 679 of file gnunet-service-scalarproduct_alice.c.

681{
682 struct AliceServiceSession *s = cls;
683 uint32_t contained;
684 uint16_t msg_size;
685 size_t required_size;
686
687 msg_size = ntohs (msg->header.size);
688 contained = ntohl (msg->contained_element_count);
689 required_size =
690 sizeof(struct BobCryptodataMessage)
691 + 2 * contained * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)
692 + 2 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext);
693 if ((msg_size != required_size) || (contained > UINT16_MAX) ||
694 (s->used_element_count < contained))
695 {
696 GNUNET_break_op (0);
697 return GNUNET_SYSERR;
698 }
699 if (NULL == s->sorted_elements)
700 {
701 /* we're not ready yet, how can Bob be? */
702 GNUNET_break_op (0);
703 return GNUNET_SYSERR;
704 }
706 {
707 /* we're not ready yet, how can Bob be? */
708 GNUNET_break_op (0);
709 return GNUNET_SYSERR;
710 }
711 return GNUNET_OK;
712}

References AliceServiceSession::client_received_element_count, GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, msg, AliceServiceSession::s, GNUNET_MessageHeader::size, AliceServiceSession::sorted_elements, AliceServiceSession::total, and AliceServiceSession::used_element_count.

◆ handle_bobs_cryptodata_message()

static void handle_bobs_cryptodata_message ( void *  cls,
const struct BobCryptodataMessage msg 
)
static

Handle a response we got from another service we wanted to calculate a scalarproduct with.

Parameters
clsour struct AliceServiceSession
msgthe actual message

Definition at line 723 of file gnunet-service-scalarproduct_alice.c.

725{
726 struct AliceServiceSession *s = cls;
728 uint32_t i;
729 uint32_t contained;
730
731 contained = ntohl (msg->contained_element_count);
733 "Received %u crypto values from Bob\n",
734 (unsigned int) contained);
735 payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
736 GNUNET_memcpy (&s->s,
737 &payload[0],
738 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
740 &payload[1],
741 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
742 payload = &payload[2];
743
748 for (i = 0; i < contained; i++)
749 {
750 GNUNET_memcpy (&s->r[i],
751 &payload[2 * i],
752 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
753 GNUNET_memcpy (&s->r_prime[i],
754 &payload[2 * i + 1],
755 sizeof(struct GNUNET_CRYPTO_PaillierCiphertext));
756 }
757 s->cadet_received_element_count = contained;
759
761 {
762 /* More to come */
763 return;
764 }
767}

References AliceServiceSession::cadet_received_element_count, AliceServiceSession::channel, compute_scalar_product(), GNUNET_CADET_receive_done(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_new_array, msg, payload, AliceServiceSession::product, AliceServiceSession::r, AliceServiceSession::r_prime, AliceServiceSession::s, AliceServiceSession::s_prime, transmit_client_response(), and AliceServiceSession::used_element_count.

Here is the call graph for this function:

◆ copy_element_cb()

static int copy_element_cb ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Iterator to copy over messages from the hash map into an array for sorting.

Parameters
clsthe struct AliceServiceSession *
keythe key (unused)
valuethe struct GNUNET_SCALARPRODUCT_Element *

Definition at line 779 of file gnunet-service-scalarproduct_alice.c.

780{
781 struct AliceServiceSession *s = cls;
783 gcry_mpi_t mval;
784 int64_t val;
785
786 mval = gcry_mpi_new (0);
787 val = (int64_t) GNUNET_ntohll (e->value);
788 if (0 > val)
789 gcry_mpi_sub_ui (mval, mval, -val);
790 else
791 gcry_mpi_add_ui (mval, mval, val);
795 return GNUNET_OK;
796}

References GNUNET_ntohll(), GNUNET_OK, MpiElement::key, GNUNET_SCALARPRODUCT_Element::key, AliceServiceSession::s, AliceServiceSession::sorted_elements, AliceServiceSession::used_element_count, value, MpiElement::value, and GNUNET_SCALARPRODUCT_Element::value.

Referenced by send_alices_cryptodata_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ element_cmp()

static int element_cmp ( const void *  a,
const void *  b 
)
static

Compare two struct MpiValues by key for sorting.

Parameters
apointer to first struct MpiValue *
bpointer to first struct MpiValue *
Returns
-1 for a < b, 0 for a=b, 1 for a > b.

Definition at line 807 of file gnunet-service-scalarproduct_alice.c.

808{
809 const struct MpiElement *ma = a;
810 const struct MpiElement *mb = b;
811
812 return GNUNET_CRYPTO_hash_cmp (ma->key, mb->key);
813}

References GNUNET_CRYPTO_hash_cmp(), and MpiElement::key.

Referenced by send_alices_cryptodata_message().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_alices_cryptodata_message()

static void send_alices_cryptodata_message ( struct AliceServiceSession s)
static

Send the cryptographic data from Alice to Bob.

Does nothing if we already transferred all elements.

Parameters
sthe associated service session

Definition at line 833 of file gnunet-service-scalarproduct_alice.c.

834{
836 struct GNUNET_MQ_Envelope *e;
838 unsigned int i;
839 uint32_t todo_count;
840 gcry_mpi_t a;
841 uint32_t off;
842
845 * sizeof(struct MpiElement));
846 s->used_element_count = 0;
849 s);
851 "Finished intersection, %d items remain\n",
853 qsort (s->sorted_elements,
855 sizeof(struct MpiElement),
856 &element_cmp);
857 off = 0;
858 while (off < s->used_element_count)
859 {
860 todo_count = s->used_element_count - off;
861 if (todo_count > ELEMENT_CAPACITY)
862 todo_count = ELEMENT_CAPACITY;
864 "Sending %u/%u crypto values to Bob\n",
865 (unsigned int) todo_count,
866 (unsigned int) s->used_element_count);
867
868 e =
870 todo_count
871 * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext),
873 msg->contained_element_count = htonl (todo_count);
875 a = gcry_mpi_new (0);
876 for (i = off; i < off + todo_count; i++)
877 {
878 gcry_mpi_add (a, s->sorted_elements[i].value, my_offset);
880 3 ==
882 }
883 gcry_mpi_release (a);
884 off += todo_count;
885 GNUNET_MQ_send (s->cadet_mq, e);
886 }
887}

References AliceServiceSession::cadet_mq, copy_element_cb(), ELEMENT_CAPACITY, element_cmp(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CRYPTO_paillier_encrypt(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_malloc, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), AliceServiceSession::intersected_elements, LOG, msg, my_offset, my_pubkey, payload, AliceServiceSession::sorted_elements, AliceServiceSession::used_element_count, and MpiElement::value.

Referenced by cb_intersection_element_removed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cb_intersection_element_removed()

static void cb_intersection_element_removed ( void *  cls,
const struct GNUNET_SETI_Element element,
uint64_t  current_size,
enum GNUNET_SETI_Status  status 
)
static

Callback for set operation results.

Called for each element that should be removed from the result set, and then once to indicate that the set intersection operation is done.

Parameters
clsclosure with the struct AliceServiceSession
elementa result element, only valid if status is #GNUNET_SETI_STATUS_OK
current_sizecurrent set size
statuswhat has happened with the set intersection?

Definition at line 901 of file gnunet-service-scalarproduct_alice.c.

905{
906 struct AliceServiceSession *s = cls;
908
909 switch (status)
910 {
912 /* this element has been removed from the set */
914 element->data);
915 GNUNET_assert (NULL != se);
917 "Intersection removed element with key %s and value %lld\n",
918 GNUNET_h2s (&se->key),
919 (long long) GNUNET_ntohll (se->value));
921 GNUNET_YES ==
923 element->data,
924 se));
925 GNUNET_free (se);
926 return;
927
929 s->intersection_op = NULL;
930 if (NULL != s->intersection_set)
931 {
933 s->intersection_set = NULL;
934 }
936 return;
938 /* unhandled status code */
939 LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n");
940 if (NULL != s->intersection_listen)
941 {
943 s->intersection_listen = NULL;
944 }
945 s->intersection_op = NULL;
946 if (NULL != s->intersection_set)
947 {
949 s->intersection_set = NULL;
950 }
953 return;
954
955 default:
956 GNUNET_break (0);
957 return;
958 }
959}

References GNUNET_SETI_Element::data, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_h2s(), GNUNET_ntohll(), GNUNET_SCALARPRODUCT_STATUS_FAILURE, GNUNET_SETI_destroy(), GNUNET_SETI_listen_cancel(), GNUNET_SETI_STATUS_DEL_LOCAL, GNUNET_SETI_STATUS_DONE, GNUNET_SETI_STATUS_FAILURE, GNUNET_YES, AliceServiceSession::intersected_elements, AliceServiceSession::intersection_listen, AliceServiceSession::intersection_op, AliceServiceSession::intersection_set, GNUNET_SCALARPRODUCT_Element::key, LOG, prepare_client_end_notification(), AliceServiceSession::s, send_alices_cryptodata_message(), status, AliceServiceSession::status, and GNUNET_SCALARPRODUCT_Element::value.

Referenced by cb_intersection_request_alice().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cb_intersection_request_alice()

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 
)
static

Called when another peer wants to do a set operation with the local peer.

If a listen error occurs, the request is NULL.

Parameters
clsclosure with the struct AliceServiceSession *
other_peerthe other peer
context_msgmessage with application specific information from the other peer
requestrequest from the other peer (never NULL), use GNUNET_SETI_accept() to accept it, otherwise the request will be refused Note that we can't just return value from the listen callback, as it is also necessary to specify the set we want to do the operation with, which sometimes can be derived from the context message. It's necessary to specify the timeout.

Definition at line 978 of file gnunet-service-scalarproduct_alice.c.

982{
983 struct AliceServiceSession *s = cls;
984
985 if (0 != GNUNET_memcmp (other_peer, &s->peer))
986 {
987 GNUNET_break_op (0);
988 return;
989 }
990 s->intersection_op = GNUNET_SETI_accept (request,
991 (struct
992 GNUNET_SETI_Option[]){ { 0 } },
994 s);
995 if (NULL == s->intersection_op)
996 {
997 GNUNET_break (0);
1000 return;
1001 }
1002 if (GNUNET_OK != GNUNET_SETI_commit (s->intersection_op, s->intersection_set))
1003 {
1004 GNUNET_break (0);
1007 return;
1008 }
1009}

References cb_intersection_element_removed(), GNUNET_break, GNUNET_break_op, GNUNET_memcmp, GNUNET_OK, GNUNET_SCALARPRODUCT_STATUS_FAILURE, GNUNET_SETI_accept(), GNUNET_SETI_commit(), prepare_client_end_notification(), request, and AliceServiceSession::s.

Referenced by client_request_complete_alice().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_request_complete_alice()

static void client_request_complete_alice ( struct AliceServiceSession s)
static

Our client has finished sending us its multipart message.

Parameters
sessionthe service session context

Definition at line 1018 of file gnunet-service-scalarproduct_alice.c.

1019{
1020 struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1021 { GNUNET_MQ_hd_var_size (bobs_cryptodata_message,
1023 struct BobCryptodataMessage,
1024 s),
1026 bobs_cryptodata_multipart,
1029 s),
1031 struct ServiceRequestMessage *msg;
1032 struct GNUNET_MQ_Envelope *e;
1033
1035 "Creating new channel for session with key %s.\n",
1036 GNUNET_h2s (&s->session_id));
1038 s,
1039 &s->peer,
1040 &s->session_id,
1041 NULL,
1043 cadet_handlers);
1044 if (NULL == s->channel)
1045 {
1048 return;
1049 }
1052 &s->session_id,
1054 s);
1055 if (NULL == s->intersection_listen)
1056 {
1059 s->channel = NULL;
1061 return;
1062 }
1063
1064 e = GNUNET_MQ_msg (msg,
1066 msg->session_id = s->session_id;
1067 msg->public_key = my_pubkey;
1068 GNUNET_MQ_send (s->cadet_mq, e);
1069}

References AliceServiceSession::cadet_mq, cb_channel_destruction(), cb_intersection_request_alice(), cfg, AliceServiceSession::channel, GNUNET_CADET_channel_create(), GNUNET_CADET_channel_destroy(), GNUNET_CADET_get_mq(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SCALARPRODUCT_STATUS_FAILURE, GNUNET_SETI_listen(), AliceServiceSession::intersection_listen, msg, my_cadet, my_pubkey, AliceServiceSession::peer, prepare_client_end_notification(), AliceServiceSession::session_id, and AliceServiceSession::status.

Referenced by handle_alice_client_message(), and handle_alice_client_message_multipart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_alice_client_message_multipart()

static int check_alice_client_message_multipart ( void *  cls,
const struct ComputationBobCryptodataMultipartMessage msg 
)
static

We're receiving additional set data.

Check if msg is well-formed.

Parameters
clsclient identification of the client
msgthe actual message
Returns
GNUNET_OK if msg is well-formed

Definition at line 1081 of file gnunet-service-scalarproduct_alice.c.

1084{
1085 struct AliceServiceSession *s = cls;
1086 uint32_t contained_count;
1087 uint16_t msize;
1088
1089 msize = ntohs (msg->header.size);
1090 contained_count = ntohl (msg->element_count_contained);
1091 if ((msize !=
1093 + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))) ||
1094 (0 == contained_count) ||
1095 (s->total == s->client_received_element_count) ||
1096 (s->total < s->client_received_element_count + contained_count))
1097 {
1098 GNUNET_break_op (0);
1099 return GNUNET_SYSERR;
1100 }
1101 return GNUNET_OK;
1102}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, msg, AliceServiceSession::s, and GNUNET_MessageHeader::size.

◆ handle_alice_client_message_multipart()

static void handle_alice_client_message_multipart ( void *  cls,
const struct ComputationBobCryptodataMultipartMessage msg 
)
static

We're receiving additional set data.

Add it to our set and if we are done, initiate the transaction.

Parameters
clsclient identification of the client
msgthe actual message

Definition at line 1113 of file gnunet-service-scalarproduct_alice.c.

1116{
1117 struct AliceServiceSession *s = cls;
1118 uint32_t contained_count;
1119 const struct GNUNET_SCALARPRODUCT_Element *elements;
1120 struct GNUNET_SETI_Element set_elem;
1121 struct GNUNET_SCALARPRODUCT_Element *elem;
1122
1123 contained_count = ntohl (msg->element_count_contained);
1124 s->client_received_element_count += contained_count;
1125 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1126 for (uint32_t i = 0; i < contained_count; i++)
1127 {
1129 GNUNET_memcpy (elem,
1130 &elements[i],
1131 sizeof(struct GNUNET_SCALARPRODUCT_Element));
1134 &elem->key,
1135 elem,
1137 {
1138 GNUNET_break (0);
1139 GNUNET_free (elem);
1140 continue;
1141 }
1142 set_elem.data = &elem->key;
1143 set_elem.size = sizeof(elem->key);
1144 set_elem.element_type = 0;
1145 GNUNET_SETI_add_element (s->intersection_set, &set_elem, NULL, NULL);
1146 s->used_element_count++;
1147 }
1150 {
1151 /* more to come */
1152 return;
1153 }
1155}

References AliceServiceSession::client, AliceServiceSession::client_received_element_count, client_request_complete_alice(), GNUNET_SETI_Element::data, GNUNET_SETI_Element::element_type, GNUNET_break, GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_free, GNUNET_memcpy, GNUNET_new, GNUNET_SERVICE_client_continue(), GNUNET_SETI_add_element(), GNUNET_SYSERR, AliceServiceSession::intersected_elements, AliceServiceSession::intersection_set, GNUNET_SCALARPRODUCT_Element::key, msg, AliceServiceSession::s, GNUNET_SETI_Element::size, AliceServiceSession::total, and AliceServiceSession::used_element_count.

Here is the call graph for this function:

◆ check_alice_client_message()

static int check_alice_client_message ( void *  cls,
const struct AliceComputationMessage msg 
)
static

Handler for Alice's client request message.

Check that msg is well-formed.

Parameters
clsidentification of the client
msgthe actual message
Returns
GNUNET_OK if msg is well-formed

Definition at line 1167 of file gnunet-service-scalarproduct_alice.c.

1169{
1170 struct AliceServiceSession *s = cls;
1171 uint16_t msize;
1172 uint32_t total_count;
1173 uint32_t contained_count;
1174
1175 if (NULL != s->intersected_elements)
1176 {
1177 /* only one concurrent session per client connection allowed,
1178 simplifies logic a lot... */
1179 GNUNET_break (0);
1180 return GNUNET_SYSERR;
1181 }
1182 msize = ntohs (msg->header.size);
1183 total_count = ntohl (msg->element_count_total);
1184 contained_count = ntohl (msg->element_count_contained);
1185 if ((0 == total_count) || (0 == contained_count) ||
1186 (msize !=
1187 (sizeof(struct AliceComputationMessage)
1188 + contained_count * sizeof(struct GNUNET_SCALARPRODUCT_Element))))
1189 {
1190 GNUNET_break_op (0);
1191 return GNUNET_SYSERR;
1192 }
1193 return GNUNET_OK;
1194}

References GNUNET_break, GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, msg, AliceServiceSession::s, and GNUNET_MessageHeader::size.

◆ handle_alice_client_message()

static void handle_alice_client_message ( void *  cls,
const struct AliceComputationMessage msg 
)
static

Handler for Alice's client request message.

We are doing request-initiation to compute a scalar product with a peer.

Parameters
clsidentification of the client
msgthe actual message

Definition at line 1205 of file gnunet-service-scalarproduct_alice.c.

1207{
1208 struct AliceServiceSession *s = cls;
1209 uint32_t contained_count;
1210 uint32_t total_count;
1211 const struct GNUNET_SCALARPRODUCT_Element *elements;
1212 struct GNUNET_SETI_Element set_elem;
1213 struct GNUNET_SCALARPRODUCT_Element *elem;
1214
1215 total_count = ntohl (msg->element_count_total);
1216 contained_count = ntohl (msg->element_count_contained);
1217 s->peer = msg->peer;
1219 s->total = total_count;
1220 s->client_received_element_count = contained_count;
1221 s->session_id = msg->session_key;
1222 elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1226
1227 for (uint32_t i = 0; i < contained_count; i++)
1228 {
1229 if (0 == GNUNET_ntohll (elements[i].value))
1230 continue;
1232 GNUNET_memcpy (elem,
1233 &elements[i],
1234 sizeof(struct GNUNET_SCALARPRODUCT_Element));
1237 &elem->key,
1238 elem,
1240 {
1241 /* element with same key encountered twice! */
1242 GNUNET_break (0);
1243 GNUNET_free (elem);
1244 continue;
1245 }
1246 set_elem.data = &elem->key;
1247 set_elem.size = sizeof(elem->key);
1248 set_elem.element_type = 0;
1250 &set_elem,
1251 NULL,
1252 NULL);
1253 s->used_element_count++;
1254 }
1257 {
1258 /* wait for multipart msg */
1259 return;
1260 }
1262}

References cfg, AliceServiceSession::client, AliceServiceSession::client_received_element_count, client_request_complete_alice(), GNUNET_SETI_Element::data, GNUNET_SETI_Element::element_type, GNUNET_break, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_free, GNUNET_memcpy, GNUNET_new, GNUNET_ntohll(), GNUNET_SCALARPRODUCT_STATUS_ACTIVE, GNUNET_SERVICE_client_continue(), GNUNET_SETI_add_element(), GNUNET_SETI_create(), GNUNET_SYSERR, GNUNET_YES, AliceServiceSession::intersected_elements, AliceServiceSession::intersection_set, GNUNET_SCALARPRODUCT_Element::key, msg, AliceServiceSession::peer, AliceServiceSession::s, AliceServiceSession::session_id, GNUNET_SETI_Element::size, AliceServiceSession::status, AliceServiceSession::total, AliceServiceSession::used_element_count, and value.

Here is the call graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Task run during shutdown.

Parameters
clsunused

Definition at line 1271 of file gnunet-service-scalarproduct_alice.c.

1272{
1273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down, initiating cleanup.\n");
1274 // FIXME: we have to cut our connections to CADET first!
1275 if (NULL != my_cadet)
1276 {
1278 my_cadet = NULL;
1279 }
1280}

References GNUNET_CADET_disconnect(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and my_cadet.

Here is the call graph for this function:

◆ client_connect_cb()

static void * client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
struct GNUNET_MQ_Handle mq 
)
static

A client connected.

Setup the associated data structure.

Parameters
clsclosure, NULL
clientidentification of the client
mqmessage queue to communicate with client
Returns
our struct AliceServiceSession

Definition at line 1294 of file gnunet-service-scalarproduct_alice.c.

1297{
1298 struct AliceServiceSession *s;
1299
1300 s = GNUNET_new (struct AliceServiceSession);
1301 s->client = client;
1302 s->client_mq = mq;
1303 return s;
1304}

References AliceServiceSession::client, GNUNET_new, mq, and AliceServiceSession::s.

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  app_cls 
)
static

A client disconnected.

Remove the associated session(s), release data structures and cancel pending outgoing transmissions to the client.

Parameters
clsclosure, NULL
clientidentification of the client
app_clsour struct AliceServiceSession

Definition at line 1318 of file gnunet-service-scalarproduct_alice.c.

1321{
1322 struct AliceServiceSession *s = app_cls;
1323
1325 "Client %p disconnected from us.\n",
1326 client);
1327 s->client = NULL;
1328 s->client_mq = NULL;
1330}

References AliceServiceSession::client, destroy_service_session(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and AliceServiceSession::s.

Here is the call graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle service 
)
static

Initialization of the program and message handlers.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

Definition at line 1341 of file gnunet-service-scalarproduct_alice.c.

1344{
1345 cfg = c;
1346 /*
1347 offset has to be sufficiently small to allow computation of:
1348 m1+m2 mod n == (S + a) + (S + b) mod n,
1349 if we have more complex operations, this factor needs to be lowered */
1350 my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1351 gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
1355 if (NULL == my_cadet)
1356 {
1357 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to CADET failed\n"));
1359 return;
1360 }
1361}

References _, cfg, GNUNET_CADET_connect(), GNUNET_CRYPTO_PAILLIER_BITS, GNUNET_CRYPTO_paillier_create(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), my_cadet, my_offset, my_privkey, my_pubkey, and shutdown_task.

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( GNUNET_OS_project_data_gnunet()  ,
"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.

Variable Documentation

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

GNUnet configuration handle.

Definition at line 193 of file gnunet-service-scalarproduct_alice.c.

Referenced by client_request_complete_alice(), handle_alice_client_message(), and run().

◆ my_pubkey

struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey
static

◆ my_privkey

struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey
static

Service's own private key.

Definition at line 203 of file gnunet-service-scalarproduct_alice.c.

Referenced by compute_scalar_product(), and run().

◆ my_offset

gcry_mpi_t my_offset
static

Service's offset for values that could possibly be negative but are plaintext for encryption.

Definition at line 208 of file gnunet-service-scalarproduct_alice.c.

Referenced by compute_scalar_product(), run(), and send_alices_cryptodata_message().

◆ my_cadet

struct GNUNET_CADET_Handle* my_cadet
static

Handle to the CADET service.

Definition at line 213 of file gnunet-service-scalarproduct_alice.c.

Referenced by client_request_complete_alice(), run(), and shutdown_task().