Changed find_finger and verify_successor timeouts
[oweals/gnunet.git] / src / scalarproduct / gnunet-service-scalarproduct.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013, 2014 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file scalarproduct/gnunet-service-scalarproduct.c
23  * @brief scalarproduct service implementation
24  * @author Christian M. Fuchs
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include <limits.h>
29 #include <gcrypt.h>
30 #include "gnunet_util_lib.h"
31 #include "gnunet_core_service.h"
32 #include "gnunet_cadet_service.h"
33 #include "gnunet_applications.h"
34 #include "gnunet_protocols.h"
35 #include "gnunet_scalarproduct_service.h"
36 #include "gnunet_set_service.h"
37 #include "scalarproduct.h"
38
39 #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct", __VA_ARGS__)
40
41
42 /**
43  * Maximum count of elements we can put into a multipart message
44  */
45 #define MULTIPART_ELEMENT_CAPACITY ((GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct MultipartMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
46
47
48 GNUNET_NETWORK_STRUCT_BEGIN
49
50 /**
51  * Message type passed from requesting service Alice to responding
52  * service Bob to initiate a request and make Bob participate in our
53  * protocol
54  */
55 struct ServiceRequestMessage
56 {
57   /**
58    * GNUNET message header
59    */
60   struct GNUNET_MessageHeader header;
61
62   /**
63    * the transaction/session key used to identify a session
64    */
65   struct GNUNET_HashCode session_id;
66
67   /**
68    * Alice's public key
69    */
70   struct GNUNET_CRYPTO_PaillierPublicKey public_key;
71
72 };
73
74
75 /**
76  * FIXME.
77  */
78 struct AliceCryptodataMessage
79 {
80   /**
81    * GNUNET message header
82    */
83   struct GNUNET_MessageHeader header;
84
85   /**
86    * how many elements we appended to this message
87    */
88   uint32_t contained_element_count GNUNET_PACKED;
89
90   /**
91    * struct GNUNET_CRYPTO_PaillierCiphertext[contained_element_count]
92    */
93 };
94
95
96 /**
97  * Multipart Message type passed between to supply additional elements
98  * for the peer
99  */
100 struct MultipartMessage
101 {
102   /**
103    * GNUNET message header
104    */
105   struct GNUNET_MessageHeader header;
106
107   /**
108    * how many elements we supply within this message
109    */
110   uint32_t contained_element_count GNUNET_PACKED;
111
112   // struct GNUNET_CRYPTO_PaillierCiphertext[multipart_element_count]
113 };
114
115
116 /**
117  * Message type passed from responding service Bob to responding service Alice
118  * to complete a request and allow Alice to compute the result
119  */
120 struct ServiceResponseMessage
121 {
122   /**
123    * GNUNET message header
124    */
125   struct GNUNET_MessageHeader header;
126
127   /**
128    * how many elements the session input had
129    */
130   uint32_t total_element_count GNUNET_PACKED;
131
132   /**
133    * how many elements were included after the mask was applied
134    * including all multipart msgs.
135    */
136   uint32_t used_element_count GNUNET_PACKED;
137
138   /**
139    * how many elements this individual message delivers
140    */
141   uint32_t contained_element_count GNUNET_PACKED;
142
143   /**
144    * the transaction/session key used to identify a session
145    */
146   struct GNUNET_HashCode key;
147
148   /**
149    * followed by s | s' | k[i][perm]
150    */
151 };
152
153 GNUNET_NETWORK_STRUCT_END
154
155
156 /**
157  * role a peer in a session can assume
158  */
159 enum PeerRole
160 {
161   ALICE,
162   BOB
163 };
164
165 /**
166  * DLL for sorting elements
167  */
168 struct SortedValue
169 {
170   /**
171    * Sorted Values are kept in a DLL
172    */
173   struct SortedValue * next;
174
175   /**
176    * Sorted Values are kept in a DLL
177    */
178   struct SortedValue * prev;
179
180   /**
181    * The element's id+integer-value
182    */
183   struct GNUNET_SCALARPRODUCT_Element * elem;
184
185   /**
186    * the element's value converted to MPI
187    */
188   gcry_mpi_t val;
189 };
190
191
192 /**
193  * A scalarproduct session which tracks:
194  *
195  * a request form the client to our final response.
196  * or
197  * a request from a service to us(service).
198  */
199 struct ServiceSession
200 {
201   /**
202    * Is this session active (#GNUNET_YES), Concluded (#GNUNET_NO), or had an error (#GNUNET_SYSERR)
203    */
204   int32_t active;
205
206   /**
207    * the role this peer has
208    */
209   enum PeerRole role;
210
211   /**
212    * session information is kept in a DLL
213    */
214   struct ServiceSession *next;
215
216   /**
217    * session information is kept in a DLL
218    */
219   struct ServiceSession *prev;
220
221   /**
222    * (hopefully) unique transaction ID
223    */
224   struct GNUNET_HashCode session_id;
225
226   /**
227    * Alice or Bob's peerID
228    */
229   struct GNUNET_PeerIdentity peer;
230
231   /**
232    * the client this request is related to
233    */
234   struct GNUNET_SERVER_Client *client;
235
236   /**
237    * The message to send
238    */
239   struct GNUNET_MessageHeader *msg;
240
241   /**
242    * how many elements we were supplied with from the client
243    */
244   uint32_t total;
245
246   /**
247    * all non-0-value'd elements transmitted to us
248    */
249   struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
250
251   /**
252    * how many elements actually are used for the scalar product
253    */
254   uint32_t used_element_count;
255
256   /**
257    * already transferred elements (sent/received) for multipart messages, less or equal than @e used_element_count for
258    */
259   uint32_t transferred_element_count;
260
261   /**
262    * Set of elements for which will conduction an intersection.
263    * the resulting elements are then used for computing the scalar product.
264    */
265   struct GNUNET_SET_Handle *intersection_set;
266
267   /**
268    * Set of elements for which will conduction an intersection.
269    * the resulting elements are then used for computing the scalar product.
270    */
271   struct GNUNET_SET_OperationHandle *intersection_op;
272
273   /**
274    * Handle to Alice's Intersection operation listening for Bob
275    */
276   struct GNUNET_SET_ListenHandle *intersection_listen;
277
278   /**
279    * Public key of the remote service, only used by Bob
280    */
281   struct GNUNET_CRYPTO_PaillierPublicKey *remote_pubkey;
282
283   /**
284    * DLL for sorting elements after intersection
285    */
286   struct SortedValue *a_head;
287
288   /**
289    * a(Alice)
290    */
291   struct SortedValue *a_tail;
292
293   /**
294    * a(Alice)
295    */
296   gcry_mpi_t *sorted_elements;
297
298   /**
299    * E(ai)(Bob) after applying the mask
300    */
301   struct GNUNET_CRYPTO_PaillierCiphertext *e_a;
302
303   /**
304    * Bob's permutation p of R
305    */
306   struct GNUNET_CRYPTO_PaillierCiphertext *r;
307
308   /**
309    * Bob's permutation q of R
310    */
311   struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
312
313   /**
314    * Bob's s
315    */
316   struct GNUNET_CRYPTO_PaillierCiphertext *s;
317
318   /**
319    * Bob's s'
320    */
321   struct GNUNET_CRYPTO_PaillierCiphertext *s_prime;
322
323   /**
324    * Bob's matching response session from the client
325    */
326   struct ServiceSession *response;
327
328   /**
329    * The computed scalar
330    */
331   gcry_mpi_t product;
332
333   /**
334    * My transmit handle for the current message to a Alice/Bob
335    */
336   struct GNUNET_CADET_TransmitHandle *service_transmit_handle;
337
338   /**
339    * My transmit handle for the current message to the client
340    */
341   struct GNUNET_SERVER_TransmitHandle *client_transmit_handle;
342
343   /**
344    * channel-handle associated with our cadet handle
345    */
346   struct GNUNET_CADET_Channel *channel;
347
348   /**
349    * Handle to a task that sends a msg to the our client
350    */
351   GNUNET_SCHEDULER_TaskIdentifier client_notification_task;
352 };
353
354
355 /**
356  * Send a multi part chunk of a service request from alice to bob.
357  * This element only contains a part of the elements-vector (session->a[]),
358  * mask and public key set have to be contained within the first message
359  *
360  * This allows a ~32kbit key length while using 32000 elements or 62000 elements per request.
361  *
362  * @param cls the associated service session
363  */
364 static void
365 prepare_alices_cyrptodata_message_multipart (void *cls);
366
367
368 /**
369  * Send a multi part chunk of a service response from Bob to Alice.
370  * This element only contains the two permutations of R, R'.
371  *
372  * @param cls the associated service session
373  */
374 static void
375 prepare_bobs_cryptodata_message_multipart (void *cls);
376
377
378
379 /**
380  * GNUnet configuration handle
381  */
382 static const struct GNUNET_CONFIGURATION_Handle * cfg;
383
384 /**
385  * Handle to the core service (NULL until we've connected to it).
386  */
387 static struct GNUNET_CADET_Handle *my_cadet;
388
389 /**
390  * The identity of this host.
391  */
392 static struct GNUNET_PeerIdentity me;
393
394 /**
395  * Service's own public key
396  */
397 static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey;
398
399 /**
400  * Service's own private key
401  */
402 static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey;
403
404 /**
405  * Service's offset for values that could possibly be negative but are plaintext for encryption.
406  */
407 static gcry_mpi_t my_offset;
408
409 /**
410  * Head of our double linked list for client-requests sent to us.
411  * for all of these elements we calculate a scalar product with a remote peer
412  * split between service->service and client->service for simplicity
413  */
414 static struct ServiceSession *from_client_head;
415
416 /**
417  * Tail of our double linked list for client-requests sent to us.
418  * for all of these elements we calculate a scalar product with a remote peer
419  * split between service->service and client->service for simplicity
420  */
421 static struct ServiceSession *from_client_tail;
422
423 /**
424  * Head of our double linked list for service-requests sent to us.
425  * for all of these elements we help the requesting service in calculating a scalar product
426  * split between service->service and client->service for simplicity
427  */
428 static struct ServiceSession *from_service_head;
429
430 /**
431  * Tail of our double linked list for service-requests sent to us.
432  * for all of these elements we help the requesting service in calculating a scalar product
433  * split between service->service and client->service for simplicity
434  */
435 static struct ServiceSession *from_service_tail;
436
437 /**
438  * Certain events (callbacks for server & cadet operations) must not be queued after shutdown.
439  */
440 static int do_shutdown;
441
442
443 /**
444  * computes the square sum over a vector of a given length.
445  *
446  * @param vector the vector to encrypt
447  * @param length the length of the vector
448  * @return an MPI value containing the calculated sum, never NULL
449  */
450 static gcry_mpi_t
451 compute_square_sum (gcry_mpi_t *vector,
452                     uint32_t length)
453 {
454   gcry_mpi_t elem;
455   gcry_mpi_t sum;
456   int32_t i;
457
458   GNUNET_assert (sum = gcry_mpi_new (0));
459   GNUNET_assert (elem = gcry_mpi_new (0));
460
461   // calculare E(sum (ai ^ 2), publickey)
462   for (i = 0; i < length; i++) {
463     gcry_mpi_mul (elem, vector[i], vector[i]);
464     gcry_mpi_add (sum, sum, elem);
465   }
466   gcry_mpi_release (elem);
467
468   return sum;
469 }
470
471
472 /**
473  * Safely frees ALL memory areas referenced by a session.
474  *
475  * @param session - the session to free elements from
476  */
477 static void
478 free_session_variables (struct ServiceSession *s)
479 {
480   while (NULL != s->a_head)
481   {
482     struct SortedValue * e = s->a_head;
483
484     GNUNET_free (e->elem);
485     gcry_mpi_release (e->val);
486     GNUNET_CONTAINER_DLL_remove (s->a_head, s->a_tail, e);
487     GNUNET_free (e);
488   }
489   if (s->e_a)
490   {
491     GNUNET_free (s->e_a);
492     s->e_a = NULL;
493   }
494   if (s->remote_pubkey)
495   {
496     GNUNET_free(s->remote_pubkey);
497     s->remote_pubkey=NULL;
498   }
499   if (s->sorted_elements)
500   {
501     GNUNET_free (s->sorted_elements);
502     s->sorted_elements = NULL;
503   }
504   if (s->intersected_elements)
505   {
506     GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
507     //elements are freed independently in session->a_head/tail
508     s->intersected_elements = NULL;
509   }
510   if (s->intersection_listen)
511   {
512     GNUNET_SET_listen_cancel (s->intersection_listen);
513     s->intersection_listen = NULL;
514   }
515   if (s->intersection_op)
516   {
517     GNUNET_SET_operation_cancel (s->intersection_op);
518     s->intersection_op = NULL;
519   }
520   if (s->intersection_set)
521   {
522     GNUNET_SET_destroy (s->intersection_set);
523     s->intersection_set = NULL;
524   }
525   if (s->msg)
526   {
527     GNUNET_free (s->msg);
528     s->msg = NULL;
529   }
530   if (s->r)
531   {
532     GNUNET_free (s->r);
533     s->r = NULL;
534   }
535   if (s->r_prime)
536   {
537     GNUNET_free (s->r_prime);
538     s->r_prime = NULL;
539   }
540   if (s->s)
541   {
542     GNUNET_free (s->s);
543     s->s = NULL;
544   }
545   if (s->s_prime)
546   {
547     GNUNET_free (s->s_prime);
548     s->s_prime = NULL;
549   }
550   if (s->product)
551   {
552     gcry_mpi_release (s->product);
553     s->product = NULL;
554   }
555 }
556
557
558 /**
559  * Primitive callback for copying over a message, as they
560  * usually are too complex to be handled in the callback itself.
561  * clears a session-callback, if a session was handed over and the transmit handle was stored
562  *
563  * @param cls the session containing the message object
564  * @param size the size of the buffer we got
565  * @param buf the buffer to copy the message to
566  * @return 0 if we couldn't copy, else the size copied over
567  */
568 static size_t
569 cb_transfer_message (void *cls,
570                      size_t size,
571                      void *buf)
572 {
573   struct ServiceSession * s = cls;
574   uint16_t type;
575
576   GNUNET_assert (buf);
577   if (ntohs (s->msg->size) != size)
578   {
579     GNUNET_break (0);
580     return 0;
581   }
582
583   type = ntohs (s->msg->type);
584   memcpy (buf, s->msg, size);
585   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
586               "Sent a message of type %hu.\n",
587               type);
588   GNUNET_free (s->msg);
589   s->msg = NULL;
590
591   switch (type)
592   {
593   case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT:
594     s->client_transmit_handle = NULL;
595     free_session_variables (s);
596     break;
597
598   case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION:
599     s->service_transmit_handle = NULL;
600     break;
601
602   case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA:
603   case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART:
604     s->service_transmit_handle = NULL;
605     if (s->used_element_count != s->transferred_element_count)
606       prepare_alices_cyrptodata_message_multipart (s);
607     else
608       s->channel = NULL;
609     break;
610
611   case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA:
612   case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART:
613     s->service_transmit_handle = NULL;
614     if (s->used_element_count != s->transferred_element_count)
615       prepare_bobs_cryptodata_message_multipart (s);
616     else
617       s->channel = NULL;
618     break;
619   default:
620     GNUNET_assert (0);
621   }
622   return size;
623 }
624
625
626 /**
627  * Finds a not terminated client/service session in the
628  * given DLL based on session key, element count and state.
629  *
630  * @param tail - the tail of the DLL
631  * @param key - the key we want to search for
632  * @param peerid - a pointer to the peer ID of the associated peer, NULL to ignore
633  * @return a pointer to a matching session, or NULL
634  */
635 static struct ServiceSession *
636 find_matching_session (struct ServiceSession * tail,
637                        const struct GNUNET_HashCode * key,
638                        const struct GNUNET_PeerIdentity * peerid)
639 {
640   struct ServiceSession * s;
641
642   for (s = tail; NULL != s; s = s->prev)
643   {
644     // if the key matches, and the element_count is same
645     if (0 == memcmp (&s->session_id, key, sizeof (struct GNUNET_HashCode)))
646     {
647       // if peerid is NULL OR same as the peer Id in the queued request
648       if ((NULL == peerid)
649           || (0 == memcmp (&s->peer, peerid, sizeof (struct GNUNET_PeerIdentity))))
650         // matches and is not an already terminated session
651         return s;
652     }
653   }
654
655   return NULL;
656 }
657
658
659 /**
660  * A client disconnected.
661  *
662  * Remove the associated session(s), release data structures
663  * and cancel pending outgoing transmissions to the client.
664  * if the session has not yet completed, we also cancel Alice's request to Bob.
665  *
666  * @param cls closure, NULL
667  * @param client identification of the client
668  */
669 static void
670 cb_client_disconnect (void *cls,
671                       struct GNUNET_SERVER_Client *client)
672 {
673   struct ServiceSession *s;
674
675   if (NULL == client)
676     return;
677   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678               _ ("Client %p disconnected from us.\n"), client);
679   s = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession);
680   if (NULL == s)
681     return;
682   GNUNET_CONTAINER_DLL_remove (from_client_head,
683                                from_client_tail,
684                                s);
685   if (NULL != s->service_transmit_handle)
686   {
687     GNUNET_CADET_notify_transmit_ready_cancel (s->service_transmit_handle);
688     s->service_transmit_handle = NULL;
689   }
690   if (NULL != s->channel)
691   {
692     GNUNET_CADET_channel_destroy (s->channel);
693     s->channel = NULL;
694   }
695   if (GNUNET_SCHEDULER_NO_TASK != s->client_notification_task)
696   {
697     GNUNET_SCHEDULER_cancel (s->client_notification_task);
698     s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
699   }
700   if (NULL != s->client_transmit_handle)
701   {
702     GNUNET_SERVER_notify_transmit_ready_cancel (s->client_transmit_handle);
703     s->client_transmit_handle = NULL;
704   }
705   free_session_variables (s);
706   GNUNET_free (s);
707 }
708
709
710 /**
711  * Notify the client that the session has succeeded or failed completely.
712  * This message gets sent to
713  * * alice's client if bob disconnected or to
714  * * bob's client if the operation completed or alice disconnected
715  *
716  * @param cls the associated client session
717  * @param tc the task context handed to us by the scheduler, unused
718  */
719 static void
720 prepare_client_end_notification (void * cls,
721                                  const struct GNUNET_SCHEDULER_TaskContext * tc)
722 {
723   struct ServiceSession * s = cls;
724   struct ClientResponseMessage *msg;
725
726   s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
727
728   msg = GNUNET_new (struct ClientResponseMessage);
729   msg->header.size = htons (sizeof (struct ClientResponseMessage));
730   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
731   // signal error if not signalized, positive result-range field but zero length.
732   msg->product_length = htonl (0);
733   msg->status = htonl(s->active);
734   s->msg = &msg->header;
735
736   //transmit this message to our client
737   s->client_transmit_handle
738     = GNUNET_SERVER_notify_transmit_ready (s->client,
739                                            sizeof (struct ClientResponseMessage),
740                                            GNUNET_TIME_UNIT_FOREVER_REL,
741                                            &cb_transfer_message,
742                                            s);
743
744   // if we could not even queue our request, something is wrong
745   if (NULL == s->client_transmit_handle)
746   {
747     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
748                 _("Could not send message to client (%p)!\n"),
749                 s->client);
750     GNUNET_SERVER_client_disconnect (s->client);
751     free_session_variables(s);
752     GNUNET_CONTAINER_DLL_remove (from_client_head,
753                                  from_client_tail,
754                                  s);
755     GNUNET_free(s);
756     return;
757   }
758   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
759               _("Sending session-end notification to client (%p) for session %s\n"),
760               s->client,
761               GNUNET_h2s (&s->session_id));
762 }
763
764
765 /**
766  * Executed by Alice, fills in a service-request message and sends it to the given peer
767  *
768  * @param cls the session associated with this request
769  */
770 static void
771 prepare_alices_cyrptodata_message (void *cls)
772 {
773   struct ServiceSession * s = cls;
774   struct AliceCryptodataMessage * msg;
775   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
776   unsigned int i;
777   uint32_t msg_length;
778   gcry_mpi_t a;
779
780   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
781               _ ("Successfully created new channel to peer (%s)!\n"),
782               GNUNET_i2s (&s->peer));
783
784   msg_length = sizeof (struct AliceCryptodataMessage)
785           +s->used_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
786
787   if (GNUNET_SERVER_MAX_MESSAGE_SIZE > msg_length) {
788     s->transferred_element_count = s->used_element_count;
789   }
790   else
791   {
792     //create a multipart msg, first we calculate a new msg size for the head msg
793     s->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct AliceCryptodataMessage))
794             / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
795     msg_length = sizeof (struct AliceCryptodataMessage)
796             +s->transferred_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
797   }
798
799   msg = GNUNET_malloc (msg_length);
800   msg->header.size = htons (msg_length);
801   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA);
802   msg->contained_element_count = htonl (s->transferred_element_count);
803
804   // fill in the payload
805   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
806
807   // now copy over the sorted element vector
808   a = gcry_mpi_new (0);
809   for (i = 0; i < s->transferred_element_count; i++)
810   {
811     gcry_mpi_add (a, s->sorted_elements[i], my_offset);
812     GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i]);
813   }
814   gcry_mpi_release (a);
815
816   s->msg = (struct GNUNET_MessageHeader *) msg;
817   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
818               _("Transmitting service request.\n"));
819
820   //transmit via cadet messaging
821   s->service_transmit_handle = GNUNET_CADET_notify_transmit_ready (s->channel,
822                                                                    GNUNET_YES,
823                                                                    GNUNET_TIME_UNIT_FOREVER_REL,
824                                                                    msg_length,
825                                                                    &cb_transfer_message,
826                                                                    s);
827   if (NULL == s->service_transmit_handle)
828   {
829     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
830                 _("Could not send message to channel!\n"));
831     GNUNET_free (msg);
832     s->msg = NULL;
833     s->active = GNUNET_SYSERR;
834     s->client_notification_task =
835             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
836                                       s);
837     return;
838   }
839 }
840
841
842 /**
843  * Send a multipart chunk of a service response from bob to alice.
844  * This element only contains the two permutations of R, R'.
845  *
846  * @param cls the associated service session
847  */
848 static void
849 prepare_bobs_cryptodata_message_multipart (void *cls)
850 {
851   struct ServiceSession * s = cls;
852   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
853   struct MultipartMessage * msg;
854   unsigned int i;
855   unsigned int j;
856   uint32_t msg_length;
857   uint32_t todo_count;
858
859   msg_length = sizeof (struct MultipartMessage);
860   todo_count = s->used_element_count - s->transferred_element_count;
861
862   if (todo_count > MULTIPART_ELEMENT_CAPACITY / 2)
863     // send the currently possible maximum chunk, we always transfer both permutations
864     todo_count = MULTIPART_ELEMENT_CAPACITY / 2;
865
866   msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2;
867   msg = GNUNET_malloc (msg_length);
868   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART);
869   msg->header.size = htons (msg_length);
870   msg->contained_element_count = htonl (todo_count);
871
872   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
873   for (i = s->transferred_element_count, j = 0; i < s->transferred_element_count + todo_count; i++)
874   {
875     //r[i][p] and r[i][q]
876     memcpy (&payload[j++], &s->r[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
877     memcpy (&payload[j++], &s->r_prime[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
878   }
879   s->transferred_element_count += todo_count;
880   s->msg = (struct GNUNET_MessageHeader *) msg;
881   s->service_transmit_handle =
882           GNUNET_CADET_notify_transmit_ready (s->channel,
883                                              GNUNET_YES,
884                                              GNUNET_TIME_UNIT_FOREVER_REL,
885                                              msg_length,
886                                              &cb_transfer_message,
887                                              s);
888   if (NULL == s->service_transmit_handle)
889   {
890     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
891                 _("Could not send service-response message via cadet!)\n"));
892
893     GNUNET_free (msg);
894     s->msg = NULL;
895     GNUNET_CADET_channel_destroy(s->channel);
896     s->response->active = GNUNET_SYSERR;
897
898     GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
899
900     s->response->client_notification_task =
901             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
902                                       s->response);
903     free_session_variables(s);
904     GNUNET_free(s);
905     return;
906   }
907   if (s->transferred_element_count == s->used_element_count)
908   {
909     // final part
910     s->active = GNUNET_NO;
911     GNUNET_free (s->r_prime);
912     GNUNET_free (s->r);
913     s->r_prime = NULL;
914     s->r = NULL;
915   }
916 }
917
918
919 /**
920  * Bob executes:
921  * generates the response message to be sent to alice after computing
922  * the values (1), (2), S and S'
923  *  (1)[]: $E_A(a_{pi(i)}) times E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
924  *  (2)[]: $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
925  *      S: $S := E_A(sum (r_i + b_i)^2)$
926  *     S': $S' := E_A(sum r_i^2)$
927  *
928  * @param session  the associated requesting session with alice
929  */
930 static void
931 prepare_bobs_cryptodata_message (void *cls,
932                           const struct GNUNET_SCHEDULER_TaskContext
933                           * tc)
934 {
935   struct ServiceSession * s = cls;
936   struct ServiceResponseMessage * msg;
937   uint32_t msg_length = 0;
938   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
939   int i;
940
941   msg_length = sizeof (struct ServiceResponseMessage)
942           + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); // s, stick
943
944   if (GNUNET_SERVER_MAX_MESSAGE_SIZE >
945       msg_length + 2 * s->used_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
946   { //r, r'
947     msg_length += 2 * s->used_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
948     s->transferred_element_count = s->used_element_count;
949   }
950   else
951     s->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - msg_length) /
952     (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2);
953
954   msg = GNUNET_malloc (msg_length);
955   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA);
956   msg->header.size = htons (msg_length);
957   msg->total_element_count = htonl (s->total);
958   msg->used_element_count = htonl (s->used_element_count);
959   msg->contained_element_count = htonl (s->transferred_element_count);
960   memcpy (&msg->key, &s->session_id, sizeof (struct GNUNET_HashCode));
961
962   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
963   memcpy (&payload[0], s->s, sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
964   memcpy (&payload[1], s->s_prime, sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
965   GNUNET_free (s->s_prime);
966   s->s_prime = NULL;
967   GNUNET_free (s->s);
968   s->s = NULL;
969
970   payload = &payload[2];
971   // convert k[][]
972   for (i = 0; i < s->transferred_element_count; i++)
973   {
974     //k[i][p] and k[i][q]
975     memcpy (&payload[i * 2], &s->r[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
976     memcpy (&payload[i * 2 + 1], &s->r_prime[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
977   }
978
979   s->msg = (struct GNUNET_MessageHeader *) msg;
980   s->service_transmit_handle =
981           GNUNET_CADET_notify_transmit_ready (s->channel,
982                                              GNUNET_YES,
983                                              GNUNET_TIME_UNIT_FOREVER_REL,
984                                              msg_length,
985                                              &cb_transfer_message,
986                                              s);
987   if (NULL == s->service_transmit_handle)
988   {
989     //disconnect our client
990     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
991                 _("Could not send service-response message via cadet!)\n"));
992
993     GNUNET_free (msg);
994     s->msg = NULL;
995     GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
996     GNUNET_CADET_channel_destroy(s->channel);
997     s->response->active = GNUNET_SYSERR;
998
999     s->response->client_notification_task =
1000             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1001                                       s->response);
1002     free_session_variables(s);
1003     GNUNET_free(s);
1004     return;
1005   }
1006   if (s->transferred_element_count != s->used_element_count)
1007   {
1008     // multipart
1009   }
1010   else
1011   {
1012     //singlepart
1013     s->active = GNUNET_NO;
1014     GNUNET_free (s->r);
1015     s->r = NULL;
1016     GNUNET_free (s->r_prime);
1017     s->r_prime = NULL;
1018   }
1019 }
1020
1021
1022 /**
1023  * executed by bob:
1024  * compute the values
1025  *  (1)[]: $E_A(a_{pi(i)}) otimes E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$
1026  *  (2)[]: $E_A(a_{pi'(i)}) otimes E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
1027  *      S: $S := E_A(sum (r_i + b_i)^2)$
1028  *     S': $S' := E_A(sum r_i^2)$
1029  *
1030  * @param request the requesting session + bob's requesting peer
1031  */
1032 static void
1033 compute_service_response (struct ServiceSession *session)
1034 {
1035   int i;
1036   unsigned int * p;
1037   unsigned int * q;
1038   uint32_t count;
1039   gcry_mpi_t * rand = NULL;
1040   gcry_mpi_t tmp;
1041   gcry_mpi_t * b;
1042   struct GNUNET_CRYPTO_PaillierCiphertext * a;
1043   struct GNUNET_CRYPTO_PaillierCiphertext * r;
1044   struct GNUNET_CRYPTO_PaillierCiphertext * r_prime;
1045   struct GNUNET_CRYPTO_PaillierCiphertext * s;
1046   struct GNUNET_CRYPTO_PaillierCiphertext * s_prime;
1047
1048   count = session->used_element_count;
1049   a = session->e_a;
1050   b = session->sorted_elements;
1051   q = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count);
1052   p = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count);
1053
1054   for (i = 0; i < count; i++)
1055     GNUNET_assert (NULL != (rand[i] = gcry_mpi_new (0)));
1056   r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
1057   r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
1058   s = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
1059   s_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
1060
1061   for (i = 0; i < count; i++)
1062   {
1063     int32_t svalue;
1064
1065     svalue = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
1066
1067     // long to gcry_mpi_t
1068     if (svalue < 0)
1069       gcry_mpi_sub_ui (rand[i],
1070                        rand[i],
1071                        -svalue);
1072     else
1073       rand[i] = gcry_mpi_set_ui (rand[i], svalue);
1074   }
1075
1076   tmp = gcry_mpi_new (0);
1077   // encrypt the element
1078   // for the sake of readability I decided to have dedicated permutation
1079   // vectors, which get rid of all the lookups in p/q.
1080   // however, ap/aq are not absolutely necessary but are just abstraction
1081   // Calculate Kp = E(S + a_pi) (+) E(S - r_pi - b_pi)
1082   for (i = 0; i < count; i++) {
1083     // E(S - r_pi - b_pi)
1084     gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
1085     gcry_mpi_sub (tmp, tmp, b[p[i]]);
1086     GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
1087                                     tmp,
1088                                     2,
1089                                     &r[i]);
1090
1091     // E(S - r_pi - b_pi) * E(S + a_pi) ==  E(2*S + a - r - b)
1092     GNUNET_CRYPTO_paillier_hom_add (session->remote_pubkey,
1093                                     &r[i],
1094                                     &a[p[i]],
1095                                     &r[i]);
1096   }
1097
1098   // Calculate Kq = E(S + a_qi) (+) E(S - r_qi)
1099   for (i = 0; i < count; i++) {
1100     // E(S - r_qi)
1101     gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
1102     GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
1103                                                         tmp,
1104                                                         2,
1105                                                         &r_prime[i]));
1106
1107     // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
1108     GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (session->remote_pubkey,
1109                                                         &r_prime[i],
1110                                                         &a[q[i]],
1111                                                         &r_prime[i]));
1112   }
1113
1114   // Calculate S' =  E(SUM( r_i^2 ))
1115   tmp = compute_square_sum (rand, count);
1116   GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
1117                                   tmp,
1118                                   1,
1119                                   s_prime);
1120
1121   // Calculate S = E(SUM( (r_i + b_i)^2 ))
1122   for (i = 0; i < count; i++)
1123     gcry_mpi_add (rand[i], rand[i], b[i]);
1124   tmp = compute_square_sum (rand, count);
1125   GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
1126                                   tmp,
1127                                   1,
1128                                   s);
1129
1130   session->r = r;
1131   session->r_prime = r_prime;
1132   session->s = s;
1133   session->s_prime = s_prime;
1134
1135   // release rand, b and a
1136   for (i = 0; i < count; i++) {
1137     gcry_mpi_release (rand[i]);
1138     gcry_mpi_release (b[i]);
1139   }
1140   gcry_mpi_release (tmp);
1141   GNUNET_free (session->e_a);
1142   session->e_a = NULL;
1143   GNUNET_free (p);
1144   GNUNET_free (q);
1145   GNUNET_free (b);
1146   GNUNET_free (rand);
1147
1148   // copy the r[], r_prime[], S and Stick into a new message, prepare_service_response frees these
1149   GNUNET_SCHEDULER_add_now (&prepare_bobs_cryptodata_message, s);
1150 }
1151
1152
1153 /**
1154  * Iterator over all hash map entries in session->intersected_elements.
1155  *
1156  * @param cls closure
1157  * @param key current key code
1158  * @param value value in the hash map
1159  * @return #GNUNET_YES if we should continue to
1160  *         iterate,
1161  *         #GNUNET_NO if not.
1162  */
1163 int
1164 cb_insert_element_sorted (void *cls,
1165                           const struct GNUNET_HashCode *key,
1166                           void *value)
1167 {
1168   struct ServiceSession * s = (struct ServiceSession*) cls;
1169   struct SortedValue * e = GNUNET_new (struct SortedValue);
1170   struct SortedValue * o = s->a_head;
1171   int64_t val;
1172
1173   e->elem = value;
1174   e->val = gcry_mpi_new (0);
1175   val = (int64_t) GNUNET_ntohll (e->elem->value);
1176   if (0 > val)
1177     gcry_mpi_sub_ui (e->val, e->val, -val);
1178   else
1179     gcry_mpi_add_ui (e->val, e->val, val);
1180
1181   // insert as first element with the lowest key
1182   if (NULL == s->a_head
1183       || (0 <= GNUNET_CRYPTO_hash_cmp (&s->a_head->elem->key, &e->elem->key)))
1184   {
1185     GNUNET_CONTAINER_DLL_insert (s->a_head, s->a_tail, e);
1186     return GNUNET_YES;
1187   }
1188   else if (0 > GNUNET_CRYPTO_hash_cmp (&s->a_tail->elem->key, &e->elem->key))
1189   {
1190     // insert as last element with the highest key
1191     GNUNET_CONTAINER_DLL_insert_tail (s->a_head, s->a_tail, e);
1192     return GNUNET_YES;
1193   }
1194   // insert before the first higher/equal element
1195   do
1196   {
1197     if (0 <= GNUNET_CRYPTO_hash_cmp (&o->elem->key, &e->elem->key))
1198     {
1199       GNUNET_CONTAINER_DLL_insert_before (s->a_head, s->a_tail, o, e);
1200       return GNUNET_YES;
1201     }
1202     o = o->next;
1203   }
1204   while (NULL != o);
1205   // broken DLL
1206   GNUNET_assert (0);
1207 }
1208
1209
1210 /**
1211  * Callback for set operation results. Called for each element
1212  * in the result set.
1213  *
1214  * @param cls closure
1215  * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
1216  * @param status see `enum GNUNET_SET_Status`
1217  */
1218 static void
1219 cb_intersection_element_removed (void *cls,
1220                                  const struct GNUNET_SET_Element *element,
1221                                  enum GNUNET_SET_Status status)
1222 {
1223   struct ServiceSession * s = cls;
1224   struct GNUNET_SCALARPRODUCT_Element * se;
1225   int i;
1226
1227   switch (status)
1228   {
1229   case GNUNET_SET_STATUS_OK:
1230     //this element has been removed from the set
1231     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
1232                                             element->data);
1233
1234     GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
1235                                           element->data,
1236                                           se);
1237     LOG (GNUNET_ERROR_TYPE_DEBUG, "%s: removed element with key %s value %d\n", s->role == ALICE ? "ALICE" : "BOB", GNUNET_h2s(&se->key), se->value);
1238     return;
1239
1240   case GNUNET_SET_STATUS_DONE:
1241     s->intersection_op = NULL;
1242     s->intersection_set = NULL;
1243
1244     s->used_element_count = GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
1245                                            &cb_insert_element_sorted,
1246                                            s);
1247     LOG (GNUNET_ERROR_TYPE_DEBUG, "%s: Finished intersection, %d items remain\n", s->role == ALICE ? "ALICE" : "BOB", s->used_element_count);
1248     if (2 > s->used_element_count)
1249     {
1250       // failed! do not leak information about our single remaining element!
1251       // continue after the loop
1252       break;
1253     }
1254
1255     s->sorted_elements = GNUNET_malloc (s->used_element_count * sizeof (gcry_mpi_t));
1256     for (i = 0; NULL != s->a_head; i++)
1257     {
1258       struct SortedValue* a = s->a_head;
1259       GNUNET_assert (i < s->used_element_count);
1260
1261       s->sorted_elements[i] = a->val;
1262       GNUNET_CONTAINER_DLL_remove (s->a_head, s->a_tail, a);
1263       GNUNET_free (a->elem);
1264     }
1265     GNUNET_assert (i == s->used_element_count);
1266
1267     if (ALICE == s->role) {
1268       prepare_alices_cyrptodata_message (s);
1269       return;
1270     }
1271     else if (s->used_element_count == s->transferred_element_count)
1272     {
1273       compute_service_response (s);
1274       return;
1275     }
1276     break;
1277   default:
1278     LOG (GNUNET_ERROR_TYPE_DEBUG, "%s: OOOPS %d", s->role == ALICE ? "ALICE" : "BOB", status);
1279     if (NULL != s->intersection_listen)
1280     {
1281       GNUNET_SET_listen_cancel (s->intersection_listen);
1282       s->intersection_listen = NULL;
1283     }
1284
1285     // the op failed and has already been invalidated by the set service
1286     break;
1287   }
1288
1289   s->intersection_op = NULL;
1290   s->intersection_set = NULL;
1291
1292   //failed if we go here
1293   GNUNET_break_op (0);
1294
1295   // and notify our client-session that we could not complete the session
1296   if (ALICE == s->role) {
1297     s->active = GNUNET_SYSERR;
1298     s->client_notification_task =
1299             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1300                                       s);
1301   }
1302   else
1303   {
1304     GNUNET_CONTAINER_DLL_remove (from_service_head,
1305                                  from_service_tail,
1306                                  s);
1307     free_session_variables (s);
1308     s->response->active = GNUNET_SYSERR;
1309     s->response->client_notification_task =
1310             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1311                                       s->response);
1312     GNUNET_free(s);
1313   }
1314 }
1315
1316
1317 /**
1318  * Called when another peer wants to do a set operation with the
1319  * local peer. If a listen error occurs, the @a request is NULL.
1320  *
1321  * @param cls closure
1322  * @param other_peer the other peer
1323  * @param context_msg message with application specific information from
1324  *        the other peer
1325  * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
1326  *        to accept it, otherwise the request will be refused
1327  *        Note that we can't just return value from the listen callback,
1328  *        as it is also necessary to specify the set we want to do the
1329  *        operation with, whith sometimes can be derived from the context
1330  *        message. It's necessary to specify the timeout.
1331  */
1332 static void
1333 cb_intersection_request_alice (void *cls,
1334                                const struct GNUNET_PeerIdentity *other_peer,
1335                                const struct GNUNET_MessageHeader *context_msg,
1336                                struct GNUNET_SET_Request *request)
1337 {
1338   struct ServiceSession * s = cls;
1339
1340   s->intersection_op = GNUNET_SET_accept (request,
1341                                           GNUNET_SET_RESULT_REMOVED,
1342                                           cb_intersection_element_removed,
1343                                           s);
1344   if (NULL == s->intersection_op)
1345   {
1346     s->active = GNUNET_SYSERR;
1347     s->client_notification_task =
1348             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1349                                       s);
1350     return;
1351   }
1352   if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set))
1353   {
1354     s->active = GNUNET_SYSERR;
1355     s->client_notification_task =
1356             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1357                                       s);
1358     return;
1359   }
1360   s->intersection_set = NULL;
1361   s->intersection_listen = NULL;
1362 }
1363
1364
1365 /**
1366  * prepare the response we will send to alice or bobs' clients.
1367  * in Bobs case the product will be NULL.
1368  *
1369  * @param cls the session associated with our client.
1370  * @param tc the task context handed to us by the scheduler, unused
1371  */
1372 static void
1373 prepare_client_response (void *cls,
1374                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1375 {
1376   struct ServiceSession * s = cls;
1377   struct ClientResponseMessage *msg;
1378   unsigned char * product_exported = NULL;
1379   size_t product_length = 0;
1380   uint32_t msg_length = 0;
1381   int8_t range = -1;
1382   gcry_error_t rc;
1383   int sign;
1384
1385   s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
1386
1387   if (s->product)
1388   {
1389     gcry_mpi_t value = gcry_mpi_new (0);
1390
1391     sign = gcry_mpi_cmp_ui (s->product, 0);
1392     // libgcrypt can not handle a print of a negative number
1393     // if (a->sign) return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
1394     if (0 > sign)
1395     {
1396       gcry_mpi_sub (value, value, s->product);
1397     }
1398     else if (0 < sign)
1399     {
1400       range = 1;
1401       gcry_mpi_add (value, value, s->product);
1402     }
1403     else
1404       range = 0;
1405
1406     gcry_mpi_release (s->product);
1407     s->product = NULL;
1408
1409     // get representation as string
1410     if (range
1411         && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
1412                                         &product_exported,
1413                                         &product_length,
1414                                         value))))
1415     {
1416       LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1417       product_length = 0;
1418       range = -1; // signal error with product-length = 0 and range = -1
1419     }
1420     gcry_mpi_release (value);
1421   }
1422
1423   msg_length = sizeof (struct ClientResponseMessage) + product_length;
1424   msg = GNUNET_malloc (msg_length);
1425   if (product_exported != NULL)
1426   {
1427     memcpy (&msg[1], product_exported, product_length);
1428     GNUNET_free (product_exported);
1429   }
1430   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
1431   msg->header.size = htons (msg_length);
1432   msg->range = range;
1433   msg->product_length = htonl (product_length);
1434   s->msg = (struct GNUNET_MessageHeader *) msg;
1435   s->client_transmit_handle =
1436           GNUNET_SERVER_notify_transmit_ready (s->client,
1437                                                msg_length,
1438                                                GNUNET_TIME_UNIT_FOREVER_REL,
1439                                                &cb_transfer_message,
1440                                                s);
1441   GNUNET_break (NULL != s->client_transmit_handle);
1442   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1443               _ ("Sent result to client (%p), this session (%s) has ended!\n"),
1444               s->client,
1445               GNUNET_h2s (&s->session_id));
1446 }
1447
1448
1449 /**
1450  * Executed by Alice, fills in a service-request message and sends it to the given peer
1451  *
1452  * @param session the session associated with this request
1453  */
1454 static void
1455 prepare_alices_computation_request (struct ServiceSession * s)
1456 {
1457   struct ServiceRequestMessage * msg;
1458
1459   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1460               _("Successfully created new channel to peer (%s)!\n"),
1461               GNUNET_i2s (&s->peer));
1462
1463   msg = GNUNET_new (struct ServiceRequestMessage);
1464   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION);
1465   memcpy (&msg->session_id, &s->session_id, sizeof (struct GNUNET_HashCode));
1466   msg->header.size = htons (sizeof (struct ServiceRequestMessage));
1467
1468   s->msg = (struct GNUNET_MessageHeader *) msg;
1469   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1470               _("Transmitting service request.\n"));
1471
1472   //transmit via cadet messaging
1473   s->service_transmit_handle
1474     = GNUNET_CADET_notify_transmit_ready (s->channel, GNUNET_YES,
1475                                           GNUNET_TIME_UNIT_FOREVER_REL,
1476                                           sizeof (struct ServiceRequestMessage),
1477                                           &cb_transfer_message,
1478                                           s);
1479   if (!s->service_transmit_handle)
1480   {
1481     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1482                 _("Could not send message to channel!\n"));
1483     GNUNET_free (msg);
1484     s->msg = NULL;
1485     s->active = GNUNET_SYSERR;
1486     s->client_notification_task =
1487             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1488                                       s);
1489     return;
1490   }
1491 }
1492
1493
1494 /**
1495  * Send a multi part chunk of a service request from alice to bob.
1496  * This element only contains a part of the elements-vector (session->a[]),
1497  * mask and public key set have to be contained within the first message
1498  *
1499  * This allows a ~32kbit key length while using 32000 elements or 62000 elements per request.
1500  *
1501  * @param cls the associated service session
1502  */
1503 static void
1504 prepare_alices_cyrptodata_message_multipart (void *cls)
1505 {
1506   struct ServiceSession * s = cls;
1507   struct MultipartMessage * msg;
1508   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
1509   unsigned int i;
1510   uint32_t msg_length;
1511   uint32_t todo_count;
1512   gcry_mpi_t a;
1513
1514   msg_length = sizeof (struct MultipartMessage);
1515   todo_count = s->used_element_count - s->transferred_element_count;
1516
1517   if (todo_count > MULTIPART_ELEMENT_CAPACITY)
1518     // send the currently possible maximum chunk
1519     todo_count = MULTIPART_ELEMENT_CAPACITY;
1520
1521   msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
1522   msg = GNUNET_malloc (msg_length);
1523   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART);
1524   msg->header.size = htons (msg_length);
1525   msg->contained_element_count = htonl (todo_count);
1526
1527   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
1528
1529   // now copy over the sorted element vector
1530   a = gcry_mpi_new (0);
1531   for (i = s->transferred_element_count; i < todo_count; i++)
1532   {
1533     gcry_mpi_add (a, s->sorted_elements[i], my_offset);
1534     GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i - s->transferred_element_count]);
1535   }
1536   gcry_mpi_release (a);
1537   s->transferred_element_count += todo_count;
1538
1539   s->msg = (struct GNUNET_MessageHeader *) msg;
1540   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n"));
1541
1542   //transmit via cadet messaging
1543   s->service_transmit_handle = GNUNET_CADET_notify_transmit_ready (s->channel, GNUNET_YES,
1544                                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1545                                                                         msg_length,
1546                                                                         &cb_transfer_message,
1547                                                                         s);
1548   if (!s->service_transmit_handle)
1549   {
1550     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1551                 _("Could not send service-request multipart message to channel!\n"));
1552     GNUNET_free (msg);
1553     s->msg = NULL;
1554     s->active = GNUNET_SYSERR;
1555     s->client_notification_task =
1556             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1557                                       s);
1558     return;
1559   }
1560 }
1561
1562
1563 /**
1564  * Our client has finished sending us its multipart message.
1565  *
1566  * @param session the service session context
1567  */
1568 static void
1569 client_request_complete_bob (struct ServiceSession * client_session)
1570 {
1571   struct ServiceSession * s;
1572
1573   //check if service queue contains a matching request
1574   s = find_matching_session (from_service_tail,
1575                                    &client_session->session_id,
1576                                    NULL);
1577   if (NULL != s)
1578   {
1579     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1580                 _ ("Got client-responder-session with key %s and a matching service-request-session set, processing.\n"),
1581                 GNUNET_h2s (&client_session->session_id));
1582
1583     s->response = client_session;
1584     s->intersected_elements = client_session->intersected_elements;
1585     client_session->intersected_elements = NULL;
1586     s->intersection_set = client_session->intersection_set;
1587     client_session->intersection_set = NULL;
1588
1589     s->intersection_op = GNUNET_SET_prepare (&s->peer,
1590                                                    &s->session_id,
1591                                                    NULL,
1592                                                    GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX),
1593                                                    GNUNET_SET_RESULT_REMOVED,
1594                                                    cb_intersection_element_removed,
1595                                                    s);
1596
1597     GNUNET_SET_commit (s->intersection_op, s->intersection_set);
1598   }
1599   else
1600   {
1601     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1602                 _ ("Got client-responder-session with key %s but NO matching service-request-session set, queuing element for later use.\n"),
1603                 GNUNET_h2s (&client_session->session_id));
1604     // no matching session exists yet, store the response
1605     // for later processing by handle_service_request()
1606   }
1607 }
1608
1609
1610 /**
1611  * Our client has finished sending us its multipart message.
1612  *
1613  * @param session the service session context
1614  */
1615 static void
1616 client_request_complete_alice (struct ServiceSession * s)
1617 {
1618   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1619               _ ("Creating new channel for session with key %s.\n"),
1620               GNUNET_h2s (&s->session_id));
1621   s->channel = GNUNET_CADET_channel_create (my_cadet, s,
1622                                                  &s->peer,
1623                                                  GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
1624                                                  GNUNET_CADET_OPTION_RELIABLE);
1625   if (NULL == s->channel)
1626   {
1627     s->active = GNUNET_SYSERR;
1628     s->client_notification_task =
1629             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1630                                       s);
1631     return;
1632   }
1633   s->intersection_listen = GNUNET_SET_listen (cfg,
1634                                               GNUNET_SET_OPERATION_INTERSECTION,
1635                                               &s->session_id,
1636                                               cb_intersection_request_alice,
1637                                               s);
1638   if (NULL == s->intersection_listen)
1639   {
1640     s->active = GNUNET_SYSERR;
1641     s->client_notification_task =
1642             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1643                                       s);
1644     return;
1645   }
1646   prepare_alices_computation_request (s);
1647 }
1648
1649
1650 static void
1651 handle_client_message_multipart (void *cls,
1652                                  struct GNUNET_SERVER_Client *client,
1653                                  const struct GNUNET_MessageHeader *message)
1654 {
1655   const struct ComputationMultipartMessage * msg = (const struct ComputationMultipartMessage *) message;
1656   struct ServiceSession *s;
1657   uint32_t contained_count;
1658   struct GNUNET_SCALARPRODUCT_Element *elements;
1659   uint32_t i;
1660
1661   // only one concurrent session per client connection allowed, simplifies logics a lot...
1662   s = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession);
1663   if (NULL == s) {
1664     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1665     return;
1666   }
1667
1668   contained_count = ntohl (msg->element_count_contained);
1669
1670   //sanity check: is the message as long as the message_count fields suggests?
1671   if ((ntohs (msg->header.size) != (sizeof (struct ComputationMultipartMessage) +contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element)))
1672       || (0 == contained_count) || (s->total < s->transferred_element_count + contained_count))
1673   {
1674     GNUNET_break_op (0);
1675     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1676     return;
1677   }
1678   s->transferred_element_count += contained_count;
1679
1680   elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
1681   for (i = 0; i < contained_count; i++)
1682   {
1683     struct GNUNET_SET_Element set_elem;
1684     struct GNUNET_SCALARPRODUCT_Element * elem;
1685
1686     if (0 == GNUNET_ntohll (elements[i].value))
1687       continue;
1688
1689     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1690     memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
1691
1692     if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1693                                                             &elem->key,
1694                                                             elem,
1695                                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1696     {
1697       GNUNET_free (elem);
1698       continue;
1699     }
1700     set_elem.data = &elem->key;
1701     set_elem.size = sizeof (elem->key);
1702     set_elem.type = 0; /* do we REALLY need this? */
1703     GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
1704     s->used_element_count++;
1705   }
1706
1707   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1708
1709   if (s->total != s->transferred_element_count)
1710     // multipart msg
1711     return;
1712
1713   if (ALICE == s->role)
1714     client_request_complete_alice (s);
1715   else
1716     client_request_complete_bob (s);
1717 }
1718
1719
1720 /**
1721  * Handler for a client request message.
1722  * Can either be type A or B
1723  *   A: request-initiation to compute a scalar product with a peer
1724  *   B: response role, keep the values + session and wait for a matching session or process a waiting request
1725  *
1726  * @param cls closure
1727  * @param client identification of the client
1728  * @param message the actual message
1729  */
1730 static void
1731 handle_client_message (void *cls,
1732                        struct GNUNET_SERVER_Client *client,
1733                        const struct GNUNET_MessageHeader *message)
1734 {
1735   const struct ComputationMessage * msg = (const struct ComputationMessage *) message;
1736   struct ServiceSession * s;
1737   uint32_t contained_count;
1738   uint32_t total_count;
1739   uint32_t msg_type;
1740   struct GNUNET_SCALARPRODUCT_Element * elements;
1741   uint32_t i;
1742
1743   // only one concurrent session per client connection allowed, simplifies logics a lot...
1744   s = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession);
1745   if (NULL != s)
1746   {
1747     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1748     return;
1749   }
1750
1751   msg_type = ntohs (msg->header.type);
1752   total_count = ntohl (msg->element_count_total);
1753   contained_count = ntohl (msg->element_count_contained);
1754
1755   if ((GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type)
1756       && (!memcmp (&msg->peer, &me, sizeof (struct GNUNET_PeerIdentity)))) {
1757     //session with ourself makes no sense!
1758     GNUNET_break_op (0);
1759     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1760     return;
1761   }
1762
1763   //sanity check: is the message as long as the message_count fields suggests?
1764   if ((ntohs (msg->header.size) !=
1765        (sizeof (struct ComputationMessage) + contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element)))
1766       || (0 == total_count))
1767   {
1768     GNUNET_break_op (0);
1769     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1770     return;
1771   }
1772
1773   // do we have a duplicate session here already?
1774   if (NULL != find_matching_session (from_client_tail,
1775                                      &msg->session_key,
1776                                      NULL)) {
1777     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1778                 _ ("Duplicate session information received, can not create new session with key `%s'\n"),
1779                 GNUNET_h2s (&msg->session_key));
1780     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1781     return;
1782   }
1783
1784   s = GNUNET_new (struct ServiceSession);
1785   s->active = GNUNET_YES;
1786   s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
1787   s->client = client;
1788   s->total = total_count;
1789   s->transferred_element_count = contained_count;
1790   // get our transaction key
1791   memcpy (&s->session_id, &msg->session_key, sizeof (struct GNUNET_HashCode));
1792
1793   elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
1794   s->intersected_elements = GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_NO);
1795   s->intersection_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION);
1796   for (i = 0; i < contained_count; i++) {
1797     struct GNUNET_SET_Element set_elem;
1798     struct GNUNET_SCALARPRODUCT_Element * elem;
1799
1800     if (0 == GNUNET_ntohll (elements[i].value))
1801       continue;
1802
1803     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1804     memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
1805
1806     if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1807                                                             &elem->key,
1808                                                             elem,
1809                                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) {
1810       GNUNET_free (elem);
1811       continue;
1812     }
1813     set_elem.data = &elem->key;
1814     set_elem.size = sizeof (elem->key);
1815     set_elem.type = 0; /* do we REALLY need this? */
1816     GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
1817     s->used_element_count++;
1818   }
1819
1820   if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type) {
1821     s->role = ALICE;
1822     memcpy (&s->peer, &msg->peer, sizeof (struct GNUNET_PeerIdentity));
1823   }
1824   else {
1825     s->role = BOB;
1826   }
1827
1828   GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, s);
1829   GNUNET_SERVER_client_set_user_context (client, s);
1830   GNUNET_SERVER_receive_done (client, GNUNET_YES);
1831
1832   if (s->total != s->transferred_element_count)
1833     // multipart msg
1834     return;
1835
1836   if (ALICE == s->role)
1837     client_request_complete_alice (s);
1838   else
1839     client_request_complete_bob (s);
1840 }
1841
1842
1843 /**
1844  * Function called for inbound channels.
1845  *
1846  * @param cls closure
1847  * @param channel new handle to the channel
1848  * @param initiator peer that started the channel
1849  * @param port unused
1850  * @param options unused
1851  * @return session associated with the channel
1852  */
1853 static void *
1854 cb_channel_incoming (void *cls,
1855                           struct GNUNET_CADET_Channel *channel,
1856                           const struct GNUNET_PeerIdentity *initiator,
1857                           uint32_t port,
1858                      enum GNUNET_CADET_ChannelOption options)
1859 {
1860   struct ServiceSession *s = GNUNET_new (struct ServiceSession);
1861
1862   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1863               _ ("New incoming channel from peer %s.\n"),
1864               GNUNET_i2s (initiator));
1865   s->peer = *initiator;
1866   s->channel = channel;
1867   s->role = BOB;
1868   s->active = GNUNET_YES;
1869   return s;
1870 }
1871
1872
1873 /**
1874  * Function called whenever a channel is destroyed.  Should clean up
1875  * any associated state.
1876  *
1877  * It must NOT call GNUNET_CADET_channel_destroy on the channel.
1878  *
1879  * @param cls closure (set from GNUNET_CADET_connect)
1880  * @param channel connection to the other end (henceforth invalid)
1881  * @param channel_ctx place where local state associated
1882  *                   with the channel is stored
1883  */
1884 static void
1885 cb_channel_destruction (void *cls,
1886                         const struct GNUNET_CADET_Channel *channel,
1887                         void *channel_ctx)
1888 {
1889   struct ServiceSession * s = channel_ctx;
1890   struct ServiceSession * client_session;
1891
1892   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1893               _ ("Peer disconnected, terminating session %s with peer (%s)\n"),
1894               GNUNET_h2s (&s->session_id),
1895               GNUNET_i2s (&s->peer));
1896
1897   // as we have only one peer connected in each session, just remove the session
1898   s->channel = NULL;
1899
1900   if ((ALICE == s->role) && (GNUNET_YES == s->active) && (!do_shutdown))
1901   {
1902     // if this happened before we received the answer, we must terminate the session
1903     s->role = GNUNET_SYSERR;
1904     s->client_notification_task =
1905             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1906                                       s);
1907   }
1908   else if ((BOB == s->role) && (GNUNET_SYSERR != s->active))
1909   {
1910     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
1911       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
1912
1913     // there is a client waiting for this service session, terminate it, too!
1914     // i assume the tupel of key and element count is unique. if it was not the rest of the code would not work either.
1915     client_session = s->response;
1916     if ((NULL != s->response ) && (GNUNET_NO == s->active) && (GNUNET_YES == client_session->active))
1917       client_session->active = GNUNET_NO;
1918     free_session_variables (s);
1919
1920     // the client has to check if it was waiting for a result
1921     // or if it was a responder, no point in adding more statefulness
1922     if ((NULL != s->response ) && (!do_shutdown))
1923     {
1924       client_session->client_notification_task =
1925               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1926                                         client_session);
1927     }
1928     GNUNET_free (s);
1929   }
1930 }
1931
1932
1933 /**
1934  * Compute our scalar product, done by Alice
1935  *
1936  * @param session - the session associated with this computation
1937  * @return product as MPI, never NULL
1938  */
1939 static gcry_mpi_t
1940 compute_scalar_product (struct ServiceSession *session)
1941 {
1942   uint32_t count;
1943   gcry_mpi_t t;
1944   gcry_mpi_t u;
1945   gcry_mpi_t u_prime;
1946   gcry_mpi_t p;
1947   gcry_mpi_t p_prime;
1948   gcry_mpi_t tmp;
1949   gcry_mpi_t r[session->used_element_count];
1950   gcry_mpi_t r_prime[session->used_element_count];
1951   gcry_mpi_t s;
1952   gcry_mpi_t s_prime;
1953   unsigned int i;
1954
1955   count = session->used_element_count;
1956   // due to the introduced static offset S, we now also have to remove this
1957   // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
1958   // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
1959   for (i = 0; i < count; i++)
1960   {
1961     GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1962                                     &session->r[i], r[i]);
1963     gcry_mpi_sub (r[i], r[i], my_offset);
1964     gcry_mpi_sub (r[i], r[i], my_offset);
1965     GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1966                                     &session->r_prime[i], r_prime[i]);
1967     gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
1968     gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
1969   }
1970
1971   // calculate t = sum(ai)
1972   t = compute_square_sum (session->sorted_elements, count);
1973
1974   // calculate U
1975   u = gcry_mpi_new (0);
1976   tmp = compute_square_sum (r, count);
1977   gcry_mpi_sub (u, u, tmp);
1978   gcry_mpi_release (tmp);
1979
1980   //calculate U'
1981   u_prime = gcry_mpi_new (0);
1982   tmp = compute_square_sum (r_prime, count);
1983   gcry_mpi_sub (u_prime, u_prime, tmp);
1984
1985   GNUNET_assert (p = gcry_mpi_new (0));
1986   GNUNET_assert (p_prime = gcry_mpi_new (0));
1987   GNUNET_assert (s = gcry_mpi_new (0));
1988   GNUNET_assert (s_prime = gcry_mpi_new (0));
1989
1990   // compute P
1991   GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1992                                   session->s, s);
1993   GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1994                                   session->s_prime, s_prime);
1995
1996   // compute P
1997   gcry_mpi_add (p, s, t);
1998   gcry_mpi_add (p, p, u);
1999
2000   // compute P'
2001   gcry_mpi_add (p_prime, s_prime, t);
2002   gcry_mpi_add (p_prime, p_prime, u_prime);
2003
2004   gcry_mpi_release (t);
2005   gcry_mpi_release (u);
2006   gcry_mpi_release (u_prime);
2007   gcry_mpi_release (s);
2008   gcry_mpi_release (s_prime);
2009
2010   // compute product
2011   gcry_mpi_sub (p, p, p_prime);
2012   gcry_mpi_release (p_prime);
2013   tmp = gcry_mpi_set_ui (tmp, 2);
2014   gcry_mpi_div (p, NULL, p, tmp, 0);
2015
2016   gcry_mpi_release (tmp);
2017   for (i = 0; i < count; i++)
2018   {
2019     gcry_mpi_release (session->sorted_elements[i]);
2020     gcry_mpi_release (r[i]);
2021     gcry_mpi_release (r_prime[i]);
2022   }
2023   GNUNET_free (session->a_head);
2024   session->a_head = NULL;
2025   GNUNET_free (session->s);
2026   session->s = NULL;
2027   GNUNET_free (session->s_prime);
2028   session->s_prime = NULL;
2029   GNUNET_free (session->r);
2030   session->r = NULL;
2031   GNUNET_free (session->r_prime);
2032   session->r_prime = NULL;
2033
2034   return p;
2035 }
2036
2037
2038 /**
2039  * Handle a multipart-chunk of a request from another service to calculate a scalarproduct with us.
2040  *
2041  * @param cls closure (set from #GNUNET_CADET_connect)
2042  * @param channel connection to the other end
2043  * @param channel_ctx place to store local state associated with the channel
2044  * @param message the actual message
2045  * @return #GNUNET_OK to keep the connection open,
2046  *         #GNUNET_SYSERR to close it (signal serious error)
2047  */
2048 static int
2049 handle_alices_cyrptodata_message_multipart (void *cls,
2050                                             struct GNUNET_CADET_Channel * channel,
2051                                             void **channel_ctx,
2052                                             const struct GNUNET_MessageHeader * message)
2053 {
2054   struct ServiceSession * s;
2055   const struct MultipartMessage * msg = (const struct MultipartMessage *) message;
2056   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
2057   uint32_t contained_elements;
2058   uint32_t msg_length;
2059
2060   // are we in the correct state?
2061   s = (struct ServiceSession *) * channel_ctx;
2062   //we are not bob
2063   if ((NULL == s->e_a) || //or we did not expect this message yet
2064       (s->used_element_count == s->transferred_element_count))
2065   { //we are not expecting multipart messages
2066     goto except;
2067   }
2068   // shorter than minimum?
2069   if (ntohs (msg->header.size) <= sizeof (struct MultipartMessage))
2070   {
2071     goto except;
2072   }
2073   contained_elements = ntohl (msg->contained_element_count);
2074   msg_length = sizeof (struct MultipartMessage)
2075           +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2076   //sanity check
2077   if ((ntohs (msg->header.size) != msg_length)
2078       || (s->used_element_count < contained_elements + s->transferred_element_count)
2079       || (0 == contained_elements))
2080   {
2081     goto except;
2082   }
2083   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
2084   // Convert each vector element to MPI_value
2085   memcpy (&s->e_a[s->transferred_element_count], payload,
2086           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements);
2087
2088   s->transferred_element_count += contained_elements;
2089
2090   if (contained_elements == s->used_element_count)
2091   {
2092     // single part finished
2093     if (NULL == s->intersection_op)
2094       // intersection has already finished, so we can proceed
2095       compute_service_response (s);
2096   }
2097
2098   return GNUNET_OK;
2099 except:
2100   s->channel = NULL;
2101   // and notify our client-session that we could not complete the session
2102   free_session_variables (s);
2103   if (NULL != s->client)
2104   {
2105     //Alice
2106     s->active = GNUNET_SYSERR;
2107     s->client_notification_task =
2108           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2109                                     s);
2110   }
2111   else
2112   {
2113     //Bob
2114     if (NULL != s->response){
2115       s->response->active = GNUNET_SYSERR;
2116       s->response->client_notification_task =
2117             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2118                                       s->response);
2119     }
2120     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2121       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2122     GNUNET_free (s);
2123   }
2124   return GNUNET_SYSERR;
2125 }
2126
2127
2128 /**
2129  * Handle a request from another service to calculate a scalarproduct with us.
2130  *
2131  * @param cls closure (set from #GNUNET_CADET_connect)
2132  * @param channel connection to the other end
2133  * @param channel_ctx place to store local state associated with the channel
2134  * @param message the actual message
2135  * @return #GNUNET_OK to keep the connection open,
2136  *         #GNUNET_SYSERR to close it (signal serious error)
2137  */
2138 static int
2139 handle_alices_cyrptodata_message (void *cls,
2140                                   struct GNUNET_CADET_Channel * channel,
2141                                   void **channel_ctx,
2142                                   const struct GNUNET_MessageHeader * message)
2143 {
2144   struct ServiceSession * s;
2145   const struct AliceCryptodataMessage * msg = (const struct AliceCryptodataMessage *) message;
2146   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
2147   uint32_t contained_elements = 0;
2148   uint32_t msg_length;
2149
2150   s = (struct ServiceSession *) * channel_ctx;
2151   //we are not bob
2152   if ((BOB != s->role)
2153       //we are expecting multipart messages instead
2154       || (NULL != s->e_a)
2155       //or we did not expect this message yet
2156       || //intersection OP has not yet finished
2157       !((NULL != s->intersection_op)
2158         //intersection OP done
2159         || (s->response->sorted_elements)
2160         ))
2161   {
2162     goto invalid_msg;
2163   }
2164
2165   // shorter than minimum?
2166   if (ntohs (msg->header.size) <= sizeof (struct MultipartMessage))
2167   {
2168     goto invalid_msg;
2169   }
2170
2171   contained_elements = ntohl (msg->contained_element_count);
2172   msg_length = sizeof (struct AliceCryptodataMessage)
2173           +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2174
2175   //sanity check: is the message as long as the message_count fields suggests?
2176   if ((ntohs (msg->header.size) != msg_length) ||
2177       (s->used_element_count < s->transferred_element_count + contained_elements) ||
2178       (0 == contained_elements))
2179   {
2180     goto invalid_msg;
2181   }
2182
2183   s->transferred_element_count = contained_elements;
2184   payload = (struct GNUNET_CRYPTO_PaillierCiphertext*) &msg[1];
2185
2186   s->e_a = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
2187   memcpy (&s->e_a[0], payload, contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2188   if (contained_elements == s->used_element_count)
2189   {
2190     // single part finished
2191     if (NULL == s->intersection_op)
2192       // intersection has already finished, so we can proceed
2193       compute_service_response (s);
2194   }
2195   return GNUNET_OK;
2196 invalid_msg:
2197   GNUNET_break_op (0);
2198   s->channel = NULL;
2199   // and notify our client-session that we could not complete the session
2200   free_session_variables (s);
2201   if (NULL != s->client)
2202   {
2203     //Alice
2204     s->active = GNUNET_SYSERR;
2205     s->client_notification_task =
2206           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2207                                     s);
2208   }
2209   else
2210   {
2211     //Bob
2212     if (NULL != s->response)
2213     {
2214       s->response->active = GNUNET_SYSERR;
2215       s->response->client_notification_task =
2216               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2217                                         s->response);
2218     }
2219     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2220       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2221     GNUNET_free(s);
2222   }
2223   return GNUNET_SYSERR;
2224 }
2225
2226
2227 /**
2228  * Handle a request from another service to calculate a scalarproduct with us.
2229  *
2230  * @param cls closure (set from #GNUNET_CADET_connect)
2231  * @param channel connection to the other end
2232  * @param channel_ctx place to store local state associated with the channel
2233  * @param message the actual message
2234  * @return #GNUNET_OK to keep the connection open,
2235  *         #GNUNET_SYSERR to close it (signal serious error)
2236  */
2237 static int
2238 handle_alices_computation_request (void *cls,
2239                         struct GNUNET_CADET_Channel * channel,
2240                         void **channel_ctx,
2241                         const struct GNUNET_MessageHeader * message)
2242 {
2243   struct ServiceSession * s;
2244   struct ServiceSession * client_session;
2245   const struct ServiceRequestMessage * msg = (const struct ServiceRequestMessage *) message;
2246
2247   s = (struct ServiceSession *) * channel_ctx;
2248   if ((BOB != s->role) || (s->total != 0))
2249   {
2250     // must be a fresh session
2251     goto invalid_msg;
2252   }
2253   // Check if message was sent by me, which would be bad!
2254   if (!memcmp (&s->peer, &me, sizeof (struct GNUNET_PeerIdentity)))
2255   {
2256     GNUNET_free (s);
2257     GNUNET_break (0);
2258     return GNUNET_SYSERR;
2259   }
2260   // shorter than expected?
2261   if (ntohs (msg->header.size) != sizeof (struct ServiceRequestMessage))
2262   {
2263     GNUNET_free (s);
2264     GNUNET_break_op (0);
2265     return GNUNET_SYSERR;
2266   }
2267   if (find_matching_session (from_service_tail,
2268                              &msg->session_id,
2269                              NULL)) {
2270     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2271                 _ ("Got message with duplicate session key (`%s'), ignoring service request.\n"),
2272                 (const char *) &(msg->session_id));
2273     GNUNET_free (s);
2274     return GNUNET_SYSERR;
2275   }
2276
2277   s->channel = channel;
2278
2279   // session key
2280   memcpy (&s->session_id, &msg->session_id, sizeof (struct GNUNET_HashCode));
2281
2282   // public key
2283   s->remote_pubkey = GNUNET_new (struct GNUNET_CRYPTO_PaillierPublicKey);
2284   memcpy (s->remote_pubkey, &msg->public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
2285
2286   //check if service queue contains a matching request
2287   client_session = find_matching_session (from_client_tail,
2288                                           &s->session_id,
2289                                           NULL);
2290
2291   GNUNET_CONTAINER_DLL_insert (from_service_head, from_service_tail, s);
2292
2293   if ((NULL != client_session)
2294       && (client_session->transferred_element_count == client_session->total))
2295   {
2296
2297     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2298                 _("Got session with key %s and a matching element set, processing.\n"),
2299                 GNUNET_h2s (&s->session_id));
2300
2301     s->response = client_session;
2302     s->intersected_elements = client_session->intersected_elements;
2303     client_session->intersected_elements = NULL;
2304     s->intersection_set = client_session->intersection_set;
2305     client_session->intersection_set = NULL;
2306
2307     s->intersection_op = GNUNET_SET_prepare (&s->peer,
2308                                                    &s->session_id,
2309                                                    NULL,
2310                                                    GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX),
2311                                                    GNUNET_SET_RESULT_REMOVED,
2312                                                    cb_intersection_element_removed,
2313                                                    s);
2314
2315     GNUNET_SET_commit (s->intersection_op, s->intersection_set);
2316   }
2317   else
2318   {
2319     GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a matching element set, queueing.\n"), GNUNET_h2s (&s->session_id));
2320   }
2321
2322   return GNUNET_OK;
2323 invalid_msg:
2324   GNUNET_break_op (0);
2325   s->channel = NULL;
2326   // and notify our client-session that we could not complete the session
2327   free_session_variables (s);
2328   if (NULL != s->client)
2329   {
2330     //Alice
2331     s->active = GNUNET_SYSERR;
2332     s->client_notification_task =
2333           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2334                                     s);
2335   }
2336   else
2337   {
2338     //Bob
2339     if (NULL != s->response) {
2340       s->response->active = GNUNET_SYSERR;
2341       s->response->client_notification_task =
2342               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2343                                         s->response);
2344     }
2345     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2346       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2347     GNUNET_free(s);
2348   }
2349   return GNUNET_SYSERR;
2350 }
2351
2352
2353 /**
2354  * Handle a multipart chunk of a response we got from another service we wanted to calculate a scalarproduct with.
2355  *
2356  * @param cls closure (set from #GNUNET_CADET_connect)
2357  * @param channel connection to the other end
2358  * @param channel_ctx place to store local state associated with the channel
2359  * @param message the actual message
2360  * @return #GNUNET_OK to keep the connection open,
2361  *         #GNUNET_SYSERR to close it (signal serious error)
2362  */
2363 static int
2364 handle_bobs_cryptodata_multipart (void *cls,
2365                                    struct GNUNET_CADET_Channel * channel,
2366                                    void **channel_ctx,
2367                                    const struct GNUNET_MessageHeader * message)
2368 {
2369   struct ServiceSession * s;
2370   const struct MultipartMessage * msg = (const struct MultipartMessage *) message;
2371   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
2372   size_t i;
2373   uint32_t contained = 0;
2374   size_t msg_size;
2375   size_t required_size;
2376
2377   GNUNET_assert (NULL != message);
2378   // are we in the correct state?
2379   s = (struct ServiceSession *) * channel_ctx;
2380   if ((ALICE != s->role) || (NULL == s->sorted_elements))
2381   {
2382     goto invalid_msg;
2383   }
2384   msg_size = ntohs (msg->header.size);
2385   required_size = sizeof (struct MultipartMessage)
2386           + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2387   // shorter than minimum?
2388   if (required_size > msg_size)
2389   {
2390     goto invalid_msg;
2391   }
2392   contained = ntohl (msg->contained_element_count);
2393   required_size = sizeof (struct MultipartMessage)
2394           + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2395   //sanity check: is the message as long as the message_count fields suggests?
2396   if ((required_size != msg_size) || (s->used_element_count < s->transferred_element_count + contained))
2397   {
2398     goto invalid_msg;
2399   }
2400   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
2401   // Convert each k[][perm] to its MPI_value
2402   for (i = 0; i < contained; i++) {
2403     memcpy (&s->r[s->transferred_element_count + i], &payload[2 * i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2404     memcpy (&s->r_prime[s->transferred_element_count + i], &payload[2 * i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2405   }
2406   s->transferred_element_count += contained;
2407   if (s->transferred_element_count != s->used_element_count)
2408     return GNUNET_OK;
2409   s->product = compute_scalar_product (s); //never NULL
2410
2411 invalid_msg:
2412   GNUNET_break_op (NULL != s->product);
2413   s->channel = NULL;
2414   // send message with product to client
2415   if (NULL != s->client)
2416   {
2417     //Alice
2418     if (NULL != s->product)
2419       s->active = GNUNET_NO;
2420     else
2421       s->active = GNUNET_SYSERR;
2422     s->client_notification_task =
2423           GNUNET_SCHEDULER_add_now (&prepare_client_response,
2424                                     s);
2425   }
2426   else
2427   {
2428     //Bob
2429     if (NULL != s->response){
2430       s->response->active = GNUNET_SYSERR;
2431       s->response->client_notification_task =
2432               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2433                                         s->response);
2434     }
2435     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2436       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2437     free_session_variables (s);
2438     GNUNET_free(s);
2439   }
2440   // the channel has done its job, terminate our connection and the channel
2441   // the peer will be notified that the channel was destroyed via channel_destruction_handler
2442   // just close the connection, as recommended by Christian
2443   return GNUNET_SYSERR;
2444 }
2445
2446
2447 /**
2448  * Handle a response we got from another service we wanted to calculate a scalarproduct with.
2449  *
2450  * @param cls closure (set from #GNUNET_CADET_connect)
2451  * @param channel connection to the other end
2452  * @param channel_ctx place to store local state associated with the channel
2453  * @param message the actual message
2454  * @return #GNUNET_OK to keep the connection open,
2455  *         #GNUNET_SYSERR to close it (we are done)
2456  */
2457 static int
2458 handle_bobs_cryptodata_message (void *cls,
2459                          struct GNUNET_CADET_Channel *channel,
2460                          void **channel_ctx,
2461                          const struct GNUNET_MessageHeader *message)
2462 {
2463   struct ServiceSession * s;
2464   const struct ServiceResponseMessage *msg = (const struct ServiceResponseMessage *) message;
2465   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
2466   size_t i;
2467   uint32_t contained = 0;
2468   size_t msg_size;
2469   size_t required_size;
2470
2471   GNUNET_assert (NULL != message);
2472   s = (struct ServiceSession *) * channel_ctx;
2473   // are we in the correct state?
2474   if (NULL == s->sorted_elements
2475       || NULL != s->msg
2476       || s->used_element_count != s->transferred_element_count)
2477   {
2478     goto invalid_msg;
2479   }
2480   //we need at least a full message without elements attached
2481   msg_size = ntohs (msg->header.size);
2482   required_size = sizeof (struct ServiceResponseMessage) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2483
2484   if (required_size > msg_size)
2485   {
2486     goto invalid_msg;
2487   }
2488   contained = ntohl (msg->contained_element_count);
2489   required_size = sizeof (struct ServiceResponseMessage)
2490           + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)
2491           + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2492   //sanity check: is the message as long as the message_count fields suggests?
2493   if ((msg_size != required_size) || (s->used_element_count < contained))
2494   {
2495     goto invalid_msg;
2496   }
2497   s->transferred_element_count = contained;
2498   //convert s
2499   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
2500
2501   s->s = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2502   s->s_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2503   memcpy (s->s, &payload[0], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2504   memcpy (s->s_prime, &payload[1], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2505
2506   s->r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
2507   s->r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
2508
2509   payload = &payload[2];
2510   // Convert each k[][perm] to its MPI_value
2511   for (i = 0; i < contained; i++)
2512   {
2513     memcpy (&s->r[i], &payload[2 * i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2514     memcpy (&s->r_prime[i], &payload[2 * i + 1], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2515   }
2516   if (s->transferred_element_count != s->used_element_count)
2517     return GNUNET_OK; //wait for the other multipart chunks
2518   s->product = compute_scalar_product (s); //never NULL
2519
2520 invalid_msg:
2521   GNUNET_break_op (NULL != s->product);
2522   s->channel = NULL;
2523   // send message with product to client
2524   if (NULL != s->client)
2525   {
2526     //Alice
2527     s->client_notification_task =
2528           GNUNET_SCHEDULER_add_now (&prepare_client_response,
2529                                     s);
2530   }
2531   else
2532   {
2533     //Bob
2534     if (NULL != s->response)
2535     {
2536       s->response->active = GNUNET_SYSERR;
2537       s->response->client_notification_task =
2538               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2539                                         s->response);
2540     }
2541     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2542         GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2543     free_session_variables (s);
2544     GNUNET_free(s);
2545   }
2546   // the channel has done its job, terminate our connection and the channel
2547   // the peer will be notified that the channel was destroyed via channel_destruction_handler
2548   // just close the connection, as recommended by Christian
2549   return GNUNET_SYSERR;
2550 }
2551
2552
2553 /**
2554  * Task run during shutdown.
2555  *
2556  * @param cls unused
2557  * @param tc unused
2558  */
2559 static void
2560 shutdown_task (void *cls,
2561                const struct GNUNET_SCHEDULER_TaskContext *tc)
2562 {
2563   struct ServiceSession * s;
2564
2565   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2566               _("Shutting down, initiating cleanup.\n"));
2567
2568   do_shutdown = GNUNET_YES;
2569
2570   // terminate all owned open channels.
2571   for (s = from_client_head; NULL != s; s = s->next)
2572   {
2573     if ((GNUNET_NO != s->active) && (NULL != s->channel))
2574     {
2575       GNUNET_CADET_channel_destroy (s->channel);
2576       s->channel = NULL;
2577     }
2578     if (GNUNET_SCHEDULER_NO_TASK != s->client_notification_task)
2579     {
2580       GNUNET_SCHEDULER_cancel (s->client_notification_task);
2581       s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
2582     }
2583     if (NULL != s->client)
2584     {
2585       GNUNET_SERVER_client_disconnect (s->client);
2586       s->client = NULL;
2587     }
2588   }
2589   for (s = from_service_head; NULL != s; s = s->next)
2590     if (NULL != s->channel)
2591     {
2592       GNUNET_CADET_channel_destroy (s->channel);
2593       s->channel = NULL;
2594     }
2595
2596   if (my_cadet)
2597   {
2598     GNUNET_CADET_disconnect (my_cadet);
2599     my_cadet = NULL;
2600   }
2601 }
2602
2603
2604 /**
2605  * Initialization of the program and message handlers
2606  *
2607  * @param cls closure
2608  * @param server the initialized server
2609  * @param c configuration to use
2610  */
2611 static void
2612 run (void *cls,
2613      struct GNUNET_SERVER_Handle *server,
2614      const struct GNUNET_CONFIGURATION_Handle *c)
2615 {
2616   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
2617     {&handle_client_message, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE, 0},
2618     {&handle_client_message, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB, 0},
2619     {&handle_client_message_multipart, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART, 0},
2620     {NULL, NULL, 0, 0}
2621   };
2622   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2623     { &handle_alices_computation_request, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION, 0},
2624     { &handle_alices_cyrptodata_message, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA, 0},
2625     { &handle_alices_cyrptodata_message_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART, 0},
2626     { &handle_bobs_cryptodata_message, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA, 0},
2627     { &handle_bobs_cryptodata_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART, 0},
2628     {NULL, 0, 0}
2629   };
2630   static const uint32_t ports[] = {
2631     GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
2632     0
2633   };
2634   cfg = c;
2635
2636   //generate private/public key set
2637   GNUNET_CRYPTO_paillier_create (&my_pubkey, &my_privkey);
2638
2639   // offset has to be sufficiently small to allow computation of:
2640   // m1+m2 mod n == (S + a) + (S + b) mod n,
2641   // if we have more complex operations, this factor needs to be lowered
2642   my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
2643   gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
2644
2645   // register server callbacks and disconnect handler
2646   GNUNET_SERVER_add_handlers (server, server_handlers);
2647   GNUNET_SERVER_disconnect_notify (server,
2648                                    &cb_client_disconnect,
2649                                    NULL);
2650   GNUNET_break (GNUNET_OK ==
2651                 GNUNET_CRYPTO_get_peer_identity (cfg,
2652                                                  &me));
2653   my_cadet = GNUNET_CADET_connect (cfg, NULL,
2654                                  &cb_channel_incoming,
2655                                  &cb_channel_destruction,
2656                                  cadet_handlers, ports);
2657   if (!my_cadet)
2658   {
2659     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2660                 _("Connect to CADET failed\n"));
2661     GNUNET_SCHEDULER_shutdown ();
2662     return;
2663   }
2664   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2665               _("CADET initialized\n"));
2666   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2667                                 &shutdown_task,
2668                                 NULL);
2669 }
2670
2671
2672 /**
2673  * The main function for the scalarproduct service.
2674  *
2675  * @param argc number of arguments from the command line
2676  * @param argv command line arguments
2677  * @return 0 ok, 1 on error
2678  */
2679 int
2680 main (int argc, char *const *argv)
2681 {
2682   return (GNUNET_OK ==
2683           GNUNET_SERVICE_run (argc, argv,
2684                               "scalarproduct",
2685                               GNUNET_SERVICE_OPTION_NONE,
2686                               &run, NULL)) ? 0 : 1;
2687 }
2688
2689 /* end of gnunet-service-scalarproduct.c */