-fix crash observed on FreeBSD
[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   // insert as last element with the highest key
1189   if (0 >= GNUNET_CRYPTO_hash_cmp (&s->a_tail->elem->key, &e->elem->key))
1190   {
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     s->used_element_count--;
1238     return;
1239
1240   case GNUNET_SET_STATUS_DONE:
1241     s->intersection_op = NULL;
1242     s->intersection_set = NULL;
1243
1244     if (2 > s->used_element_count)
1245     {
1246       // failed! do not leak information about our single remaining element!
1247       // continue after the loop
1248       break;
1249     }
1250
1251     GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
1252                                            &cb_insert_element_sorted,
1253                                            s);
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     if (NULL != s->intersection_listen)
1279     {
1280       GNUNET_SET_listen_cancel (s->intersection_listen);
1281       s->intersection_listen = NULL;
1282     }
1283     
1284     // the op failed and has already been invalidated by the set service
1285     s->intersection_op = NULL;
1286     s->intersection_set = NULL;
1287     break;
1288   }
1289
1290   //failed if we go here
1291   GNUNET_break_op (0);
1292
1293
1294   // and notify our client-session that we could not complete the session
1295   if (ALICE == s->role) {
1296     s->active = GNUNET_SYSERR;
1297     s->client_notification_task =
1298             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1299                                       s);
1300   }
1301   else
1302   {
1303     GNUNET_CONTAINER_DLL_remove (from_service_head,
1304                                  from_service_tail,
1305                                  s);
1306     free_session_variables (s);
1307     s->response->active = GNUNET_SYSERR;
1308     s->response->client_notification_task =
1309             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1310                                       s->response);
1311     GNUNET_free(s);
1312   }
1313 }
1314
1315
1316 /**
1317  * Called when another peer wants to do a set operation with the
1318  * local peer. If a listen error occurs, the @a request is NULL.
1319  *
1320  * @param cls closure
1321  * @param other_peer the other peer
1322  * @param context_msg message with application specific information from
1323  *        the other peer
1324  * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
1325  *        to accept it, otherwise the request will be refused
1326  *        Note that we can't just return value from the listen callback,
1327  *        as it is also necessary to specify the set we want to do the
1328  *        operation with, whith sometimes can be derived from the context
1329  *        message. It's necessary to specify the timeout.
1330  */
1331 static void
1332 cb_intersection_request_alice (void *cls,
1333                                const struct GNUNET_PeerIdentity *other_peer,
1334                                const struct GNUNET_MessageHeader *context_msg,
1335                                struct GNUNET_SET_Request *request)
1336 {
1337   struct ServiceSession * s = cls;
1338
1339   s->intersection_op = GNUNET_SET_accept (request,
1340                                           GNUNET_SET_RESULT_REMOVED,
1341                                           cb_intersection_element_removed,
1342                                           s);
1343   if (NULL == s->intersection_op)
1344   {
1345     s->active = GNUNET_SYSERR;
1346     s->client_notification_task =
1347             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1348                                       s);
1349     return;
1350   }
1351   if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set))
1352   {
1353     s->active = GNUNET_SYSERR;
1354     s->client_notification_task =
1355             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1356                                       s);
1357     return;
1358   }
1359   s->intersection_set = NULL;
1360   s->intersection_listen = NULL;
1361 }
1362
1363
1364 /**
1365  * prepare the response we will send to alice or bobs' clients.
1366  * in Bobs case the product will be NULL.
1367  *
1368  * @param cls the session associated with our client.
1369  * @param tc the task context handed to us by the scheduler, unused
1370  */
1371 static void
1372 prepare_client_response (void *cls,
1373                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1374 {
1375   struct ServiceSession * s = cls;
1376   struct ClientResponseMessage *msg;
1377   unsigned char * product_exported = NULL;
1378   size_t product_length = 0;
1379   uint32_t msg_length = 0;
1380   int8_t range = -1;
1381   gcry_error_t rc;
1382   int sign;
1383
1384   s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
1385
1386   if (s->product)
1387   {
1388     gcry_mpi_t value = gcry_mpi_new (0);
1389
1390     sign = gcry_mpi_cmp_ui (s->product, 0);
1391     // libgcrypt can not handle a print of a negative number
1392     // if (a->sign) return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
1393     if (0 > sign)
1394     {
1395       gcry_mpi_sub (value, value, s->product);
1396     }
1397     else if (0 < sign)
1398     {
1399       range = 1;
1400       gcry_mpi_add (value, value, s->product);
1401     }
1402     else
1403       range = 0;
1404
1405     gcry_mpi_release (s->product);
1406     s->product = NULL;
1407
1408     // get representation as string
1409     if (range
1410         && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD,
1411                                         &product_exported,
1412                                         &product_length,
1413                                         value))))
1414     {
1415       LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1416       product_length = 0;
1417       range = -1; // signal error with product-length = 0 and range = -1
1418     }
1419     gcry_mpi_release (value);
1420   }
1421
1422   msg_length = sizeof (struct ClientResponseMessage) + product_length;
1423   msg = GNUNET_malloc (msg_length);
1424   if (product_exported != NULL)
1425   {
1426     memcpy (&msg[1], product_exported, product_length);
1427     GNUNET_free (product_exported);
1428   }
1429   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
1430   msg->header.size = htons (msg_length);
1431   msg->range = range;
1432   msg->product_length = htonl (product_length);
1433   s->msg = (struct GNUNET_MessageHeader *) msg;
1434   s->client_transmit_handle =
1435           GNUNET_SERVER_notify_transmit_ready (s->client,
1436                                                msg_length,
1437                                                GNUNET_TIME_UNIT_FOREVER_REL,
1438                                                &cb_transfer_message,
1439                                                s);
1440   GNUNET_break (NULL != s->client_transmit_handle);
1441   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1442               _ ("Sent result to client (%p), this session (%s) has ended!\n"),
1443               s->client,
1444               GNUNET_h2s (&s->session_id));
1445 }
1446
1447
1448 /**
1449  * Executed by Alice, fills in a service-request message and sends it to the given peer
1450  *
1451  * @param session the session associated with this request
1452  */
1453 static void
1454 prepare_alices_computation_request (struct ServiceSession * s)
1455 {
1456   struct ServiceRequestMessage * msg;
1457
1458   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1459               _("Successfully created new channel to peer (%s)!\n"),
1460               GNUNET_i2s (&s->peer));
1461
1462   msg = GNUNET_new (struct ServiceRequestMessage);
1463   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION);
1464   memcpy (&msg->session_id, &s->session_id, sizeof (struct GNUNET_HashCode));
1465   msg->header.size = htons (sizeof (struct ServiceRequestMessage));
1466
1467   s->msg = (struct GNUNET_MessageHeader *) msg;
1468   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1469               _("Transmitting service request.\n"));
1470
1471   //transmit via cadet messaging
1472   s->service_transmit_handle
1473     = GNUNET_CADET_notify_transmit_ready (s->channel, GNUNET_YES,
1474                                           GNUNET_TIME_UNIT_FOREVER_REL,
1475                                           sizeof (struct ServiceRequestMessage),
1476                                           &cb_transfer_message,
1477                                           s);
1478   if (!s->service_transmit_handle)
1479   {
1480     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1481                 _("Could not send message to channel!\n"));
1482     GNUNET_free (msg);
1483     s->msg = NULL;
1484     s->active = GNUNET_SYSERR;
1485     s->client_notification_task =
1486             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1487                                       s);
1488     return;
1489   }
1490 }
1491
1492
1493 /**
1494  * Send a multi part chunk of a service request from alice to bob.
1495  * This element only contains a part of the elements-vector (session->a[]),
1496  * mask and public key set have to be contained within the first message
1497  *
1498  * This allows a ~32kbit key length while using 32000 elements or 62000 elements per request.
1499  *
1500  * @param cls the associated service session
1501  */
1502 static void
1503 prepare_alices_cyrptodata_message_multipart (void *cls)
1504 {
1505   struct ServiceSession * s = cls;
1506   struct MultipartMessage * msg;
1507   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
1508   unsigned int i;
1509   uint32_t msg_length;
1510   uint32_t todo_count;
1511   gcry_mpi_t a;
1512
1513   msg_length = sizeof (struct MultipartMessage);
1514   todo_count = s->used_element_count - s->transferred_element_count;
1515
1516   if (todo_count > MULTIPART_ELEMENT_CAPACITY)
1517     // send the currently possible maximum chunk
1518     todo_count = MULTIPART_ELEMENT_CAPACITY;
1519
1520   msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
1521   msg = GNUNET_malloc (msg_length);
1522   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART);
1523   msg->header.size = htons (msg_length);
1524   msg->contained_element_count = htonl (todo_count);
1525
1526   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
1527
1528   // now copy over the sorted element vector
1529   a = gcry_mpi_new (0);
1530   for (i = s->transferred_element_count; i < todo_count; i++)
1531   {
1532     gcry_mpi_add (a, s->sorted_elements[i], my_offset);
1533     GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[i - s->transferred_element_count]);
1534   }
1535   gcry_mpi_release (a);
1536   s->transferred_element_count += todo_count;
1537
1538   s->msg = (struct GNUNET_MessageHeader *) msg;
1539   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n"));
1540
1541   //transmit via cadet messaging
1542   s->service_transmit_handle = GNUNET_CADET_notify_transmit_ready (s->channel, GNUNET_YES,
1543                                                                         GNUNET_TIME_UNIT_FOREVER_REL,
1544                                                                         msg_length,
1545                                                                         &cb_transfer_message,
1546                                                                         s);
1547   if (!s->service_transmit_handle)
1548   {
1549     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1550                 _("Could not send service-request multipart message to channel!\n"));
1551     GNUNET_free (msg);
1552     s->msg = NULL;
1553     s->active = GNUNET_SYSERR;
1554     s->client_notification_task =
1555             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1556                                       s);
1557     return;
1558   }
1559 }
1560
1561
1562 /**
1563  * Our client has finished sending us its multipart message.
1564  *
1565  * @param session the service session context
1566  */
1567 static void
1568 client_request_complete_bob (struct ServiceSession * client_session)
1569 {
1570   struct ServiceSession * s;
1571
1572   //check if service queue contains a matching request
1573   s = find_matching_session (from_service_tail,
1574                                    &client_session->session_id,
1575                                    NULL);
1576   if (NULL != s)
1577   {
1578     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1579                 _ ("Got client-responder-session with key %s and a matching service-request-session set, processing.\n"),
1580                 GNUNET_h2s (&client_session->session_id));
1581
1582     s->response = client_session;
1583     s->intersected_elements = client_session->intersected_elements;
1584     client_session->intersected_elements = NULL;
1585     s->intersection_set = client_session->intersection_set;
1586     client_session->intersection_set = NULL;
1587
1588     s->intersection_op = GNUNET_SET_prepare (&s->peer,
1589                                                    &s->session_id,
1590                                                    NULL,
1591                                                    GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX),
1592                                                    GNUNET_SET_RESULT_REMOVED,
1593                                                    cb_intersection_element_removed,
1594                                                    s);
1595
1596     GNUNET_SET_commit (s->intersection_op, s->intersection_set);
1597   }
1598   else
1599   {
1600     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1601                 _ ("Got client-responder-session with key %s but NO matching service-request-session set, queuing element for later use.\n"),
1602                 GNUNET_h2s (&client_session->session_id));
1603     // no matching session exists yet, store the response
1604     // for later processing by handle_service_request()
1605   }
1606 }
1607
1608
1609 /**
1610  * Our client has finished sending us its multipart message.
1611  *
1612  * @param session the service session context
1613  */
1614 static void
1615 client_request_complete_alice (struct ServiceSession * s)
1616 {
1617   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1618               _ ("Creating new channel for session with key %s.\n"),
1619               GNUNET_h2s (&s->session_id));
1620   s->channel = GNUNET_CADET_channel_create (my_cadet, s,
1621                                                  &s->peer,
1622                                                  GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
1623                                                  GNUNET_CADET_OPTION_RELIABLE);
1624   if (NULL == s->channel)
1625   {
1626     s->active = GNUNET_SYSERR;
1627     s->client_notification_task =
1628             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1629                                       s);
1630     return;
1631   }
1632   s->intersection_listen = GNUNET_SET_listen (cfg,
1633                                               GNUNET_SET_OPERATION_INTERSECTION,
1634                                               &s->session_id,
1635                                               cb_intersection_request_alice,
1636                                               s);
1637   if (NULL == s->intersection_listen)
1638   {
1639     s->active = GNUNET_SYSERR;
1640     s->client_notification_task =
1641             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1642                                       s);
1643     return;
1644   }
1645   prepare_alices_computation_request (s);
1646 }
1647
1648
1649 static void
1650 handle_client_message_multipart (void *cls,
1651                                  struct GNUNET_SERVER_Client *client,
1652                                  const struct GNUNET_MessageHeader *message)
1653 {
1654   const struct ComputationMultipartMessage * msg = (const struct ComputationMultipartMessage *) message;
1655   struct ServiceSession *s;
1656   uint32_t contained_count;
1657   struct GNUNET_SCALARPRODUCT_Element *elements;
1658   uint32_t i;
1659
1660   // only one concurrent session per client connection allowed, simplifies logics a lot...
1661   s = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession);
1662   if (NULL == s) {
1663     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1664     return;
1665   }
1666
1667   contained_count = ntohl (msg->element_count_contained);
1668
1669   //sanity check: is the message as long as the message_count fields suggests?
1670   if ((ntohs (msg->header.size) != (sizeof (struct ComputationMultipartMessage) +contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element)))
1671       || (0 == contained_count) || (s->total < s->transferred_element_count + contained_count))
1672   {
1673     GNUNET_break_op (0);
1674     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1675     return;
1676   }
1677   s->transferred_element_count += contained_count;
1678
1679   elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
1680   for (i = 0; i < contained_count; i++)
1681   {
1682     struct GNUNET_SET_Element set_elem;
1683     struct GNUNET_SCALARPRODUCT_Element * elem;
1684
1685     if (0 == GNUNET_ntohll (elements[i].value))
1686       continue;
1687
1688     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1689     memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
1690
1691     if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1692                                                             &elem->key,
1693                                                             elem,
1694                                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1695     {
1696       GNUNET_free (elem);
1697       continue;
1698     }
1699     set_elem.data = &elem->key;
1700     set_elem.size = sizeof (elem->key);
1701     set_elem.type = 0; /* do we REALLY need this? */
1702     GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
1703     s->used_element_count++;
1704   }
1705
1706   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1707
1708   if (s->total != s->transferred_element_count)
1709     // multipart msg
1710     return;
1711
1712   if (ALICE == s->role)
1713     client_request_complete_alice (s);
1714   else
1715     client_request_complete_bob (s);
1716 }
1717
1718
1719 /**
1720  * Handler for a client request message.
1721  * Can either be type A or B
1722  *   A: request-initiation to compute a scalar product with a peer
1723  *   B: response role, keep the values + session and wait for a matching session or process a waiting request
1724  *
1725  * @param cls closure
1726  * @param client identification of the client
1727  * @param message the actual message
1728  */
1729 static void
1730 handle_client_message (void *cls,
1731                        struct GNUNET_SERVER_Client *client,
1732                        const struct GNUNET_MessageHeader *message)
1733 {
1734   const struct ComputationMessage * msg = (const struct ComputationMessage *) message;
1735   struct ServiceSession * s;
1736   uint32_t contained_count;
1737   uint32_t total_count;
1738   uint32_t msg_type;
1739   struct GNUNET_SCALARPRODUCT_Element * elements;
1740   uint32_t i;
1741
1742   // only one concurrent session per client connection allowed, simplifies logics a lot...
1743   s = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession);
1744   if (NULL != s)
1745   {
1746     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1747     return;
1748   }
1749
1750   msg_type = ntohs (msg->header.type);
1751   total_count = ntohl (msg->element_count_total);
1752   contained_count = ntohl (msg->element_count_contained);
1753
1754   if ((GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type)
1755       && (!memcmp (&msg->peer, &me, sizeof (struct GNUNET_PeerIdentity)))) {
1756     //session with ourself makes no sense!
1757     GNUNET_break_op (0);
1758     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1759     return;
1760   }
1761
1762   //sanity check: is the message as long as the message_count fields suggests?
1763   if ((ntohs (msg->header.size) !=
1764        (sizeof (struct ComputationMessage) + contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element)))
1765       || (0 == total_count))
1766   {
1767     GNUNET_break_op (0);
1768     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1769     return;
1770   }
1771
1772   // do we have a duplicate session here already?
1773   if (NULL != find_matching_session (from_client_tail,
1774                                      &msg->session_key,
1775                                      NULL)) {
1776     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1777                 _ ("Duplicate session information received, can not create new session with key `%s'\n"),
1778                 GNUNET_h2s (&msg->session_key));
1779     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1780     return;
1781   }
1782
1783   s = GNUNET_new (struct ServiceSession);
1784   s->active = GNUNET_YES;
1785   s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
1786   s->client = client;
1787   s->total = total_count;
1788   s->transferred_element_count = contained_count;
1789   // get our transaction key
1790   memcpy (&s->session_id, &msg->session_key, sizeof (struct GNUNET_HashCode));
1791
1792   elements = (struct GNUNET_SCALARPRODUCT_Element *) & msg[1];
1793   s->intersected_elements = GNUNET_CONTAINER_multihashmap_create (s->total, GNUNET_NO);
1794   s->intersection_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION);
1795   for (i = 0; i < contained_count; i++) {
1796     struct GNUNET_SET_Element set_elem;
1797     struct GNUNET_SCALARPRODUCT_Element * elem;
1798
1799     if (0 == GNUNET_ntohll (elements[i].value))
1800       continue;
1801
1802     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1803     memcpy (elem, &elements[i], sizeof (struct GNUNET_SCALARPRODUCT_Element));
1804
1805     if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1806                                                             &elem->key,
1807                                                             elem,
1808                                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) {
1809       GNUNET_free (elem);
1810       continue;
1811     }
1812     set_elem.data = &elem->key;
1813     set_elem.size = sizeof (elem->key);
1814     set_elem.type = 0; /* do we REALLY need this? */
1815     GNUNET_SET_add_element (s->intersection_set, &set_elem, NULL, NULL);
1816     s->used_element_count++;
1817   }
1818
1819   if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type) {
1820     s->role = ALICE;
1821     memcpy (&s->peer, &msg->peer, sizeof (struct GNUNET_PeerIdentity));
1822   }
1823   else {
1824     s->role = BOB;
1825   }
1826
1827   GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, s);
1828   GNUNET_SERVER_client_set_user_context (client, s);
1829   GNUNET_SERVER_receive_done (client, GNUNET_YES);
1830
1831   if (s->total != s->transferred_element_count)
1832     // multipart msg
1833     return;
1834
1835   if (ALICE == s->role)
1836     client_request_complete_alice (s);
1837   else
1838     client_request_complete_bob (s);
1839 }
1840
1841
1842 /**
1843  * Function called for inbound channels.
1844  *
1845  * @param cls closure
1846  * @param channel new handle to the channel
1847  * @param initiator peer that started the channel
1848  * @param port unused
1849  * @param options unused
1850  * @return session associated with the channel
1851  */
1852 static void *
1853 cb_channel_incoming (void *cls,
1854                           struct GNUNET_CADET_Channel *channel,
1855                           const struct GNUNET_PeerIdentity *initiator,
1856                           uint32_t port,
1857                      enum GNUNET_CADET_ChannelOption options)
1858 {
1859   struct ServiceSession *s = GNUNET_new (struct ServiceSession);
1860
1861   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1862               _ ("New incoming channel from peer %s.\n"),
1863               GNUNET_i2s (initiator));
1864   s->peer = *initiator;
1865   s->channel = channel;
1866   s->role = BOB;
1867   s->active = GNUNET_YES;
1868   return s;
1869 }
1870
1871
1872 /**
1873  * Function called whenever a channel is destroyed.  Should clean up
1874  * any associated state.
1875  *
1876  * It must NOT call GNUNET_CADET_channel_destroy on the channel.
1877  *
1878  * @param cls closure (set from GNUNET_CADET_connect)
1879  * @param channel connection to the other end (henceforth invalid)
1880  * @param channel_ctx place where local state associated
1881  *                   with the channel is stored
1882  */
1883 static void
1884 cb_channel_destruction (void *cls,
1885                         const struct GNUNET_CADET_Channel *channel,
1886                         void *channel_ctx)
1887 {
1888   struct ServiceSession * s = channel_ctx;
1889   struct ServiceSession * client_session;
1890
1891   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1892               _ ("Peer disconnected, terminating session %s with peer (%s)\n"),
1893               GNUNET_h2s (&s->session_id),
1894               GNUNET_i2s (&s->peer));
1895
1896   // as we have only one peer connected in each session, just remove the session
1897   s->channel = NULL;
1898
1899   if ((ALICE == s->role) && (GNUNET_YES == s->active) && (!do_shutdown))
1900   {
1901     // if this happened before we received the answer, we must terminate the session
1902     s->role = GNUNET_SYSERR;
1903     s->client_notification_task =
1904             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
1905                                       s);
1906   }
1907   else if ((BOB == s->role) && (GNUNET_SYSERR != s->active))
1908   {
1909     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
1910       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
1911
1912     // there is a client waiting for this service session, terminate it, too!
1913     // i assume the tupel of key and element count is unique. if it was not the rest of the code would not work either.
1914     client_session = s->response;
1915     if ((NULL != s->response ) && (GNUNET_NO == s->active) && (GNUNET_YES == client_session->active))
1916       client_session->active = GNUNET_NO;
1917     free_session_variables (s);
1918     GNUNET_free (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   }
1929 }
1930
1931
1932 /**
1933  * Compute our scalar product, done by Alice
1934  *
1935  * @param session - the session associated with this computation
1936  * @return product as MPI, never NULL
1937  */
1938 static gcry_mpi_t
1939 compute_scalar_product (struct ServiceSession *session)
1940 {
1941   uint32_t count;
1942   gcry_mpi_t t;
1943   gcry_mpi_t u;
1944   gcry_mpi_t u_prime;
1945   gcry_mpi_t p;
1946   gcry_mpi_t p_prime;
1947   gcry_mpi_t tmp;
1948   gcry_mpi_t r[session->used_element_count];
1949   gcry_mpi_t r_prime[session->used_element_count];
1950   gcry_mpi_t s;
1951   gcry_mpi_t s_prime;
1952   unsigned int i;
1953
1954   count = session->used_element_count;
1955   // due to the introduced static offset S, we now also have to remove this
1956   // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each,
1957   // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi)
1958   for (i = 0; i < count; i++)
1959   {
1960     GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1961                                     &session->r[i], r[i]);
1962     gcry_mpi_sub (r[i], r[i], my_offset);
1963     gcry_mpi_sub (r[i], r[i], my_offset);
1964     GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1965                                     &session->r_prime[i], r_prime[i]);
1966     gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
1967     gcry_mpi_sub (r_prime[i], r_prime[i], my_offset);
1968   }
1969
1970   // calculate t = sum(ai)
1971   t = compute_square_sum (session->sorted_elements, count);
1972
1973   // calculate U
1974   u = gcry_mpi_new (0);
1975   tmp = compute_square_sum (r, count);
1976   gcry_mpi_sub (u, u, tmp);
1977   gcry_mpi_release (tmp);
1978
1979   //calculate U'
1980   u_prime = gcry_mpi_new (0);
1981   tmp = compute_square_sum (r_prime, count);
1982   gcry_mpi_sub (u_prime, u_prime, tmp);
1983
1984   GNUNET_assert (p = gcry_mpi_new (0));
1985   GNUNET_assert (p_prime = gcry_mpi_new (0));
1986   GNUNET_assert (s = gcry_mpi_new (0));
1987   GNUNET_assert (s_prime = gcry_mpi_new (0));
1988
1989   // compute P
1990   GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1991                                   session->s, s);
1992   GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey,
1993                                   session->s_prime, s_prime);
1994
1995   // compute P
1996   gcry_mpi_add (p, s, t);
1997   gcry_mpi_add (p, p, u);
1998
1999   // compute P'
2000   gcry_mpi_add (p_prime, s_prime, t);
2001   gcry_mpi_add (p_prime, p_prime, u_prime);
2002
2003   gcry_mpi_release (t);
2004   gcry_mpi_release (u);
2005   gcry_mpi_release (u_prime);
2006   gcry_mpi_release (s);
2007   gcry_mpi_release (s_prime);
2008
2009   // compute product
2010   gcry_mpi_sub (p, p, p_prime);
2011   gcry_mpi_release (p_prime);
2012   tmp = gcry_mpi_set_ui (tmp, 2);
2013   gcry_mpi_div (p, NULL, p, tmp, 0);
2014
2015   gcry_mpi_release (tmp);
2016   for (i = 0; i < count; i++)
2017   {
2018     gcry_mpi_release (session->sorted_elements[i]);
2019     gcry_mpi_release (r[i]);
2020     gcry_mpi_release (r_prime[i]);
2021   }
2022   GNUNET_free (session->a_head);
2023   session->a_head = NULL;
2024   GNUNET_free (session->s);
2025   session->s = NULL;
2026   GNUNET_free (session->s_prime);
2027   session->s_prime = NULL;
2028   GNUNET_free (session->r);
2029   session->r = NULL;
2030   GNUNET_free (session->r_prime);
2031   session->r_prime = NULL;
2032
2033   return p;
2034 }
2035
2036
2037 /**
2038  * Handle a multipart-chunk of a request from another service to calculate a scalarproduct with us.
2039  *
2040  * @param cls closure (set from #GNUNET_CADET_connect)
2041  * @param channel connection to the other end
2042  * @param channel_ctx place to store local state associated with the channel
2043  * @param message the actual message
2044  * @return #GNUNET_OK to keep the connection open,
2045  *         #GNUNET_SYSERR to close it (signal serious error)
2046  */
2047 static int
2048 handle_alices_cyrptodata_message_multipart (void *cls,
2049                                             struct GNUNET_CADET_Channel * channel,
2050                                             void **channel_ctx,
2051                                             const struct GNUNET_MessageHeader * message)
2052 {
2053   struct ServiceSession * s;
2054   const struct MultipartMessage * msg = (const struct MultipartMessage *) message;
2055   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
2056   uint32_t contained_elements;
2057   uint32_t msg_length;
2058
2059   // are we in the correct state?
2060   s = (struct ServiceSession *) * channel_ctx;
2061   //we are not bob
2062   if ((NULL == s->e_a) || //or we did not expect this message yet
2063       (s->used_element_count == s->transferred_element_count))
2064   { //we are not expecting multipart messages
2065     goto except;
2066   }
2067   // shorter than minimum?
2068   if (ntohs (msg->header.size) <= sizeof (struct MultipartMessage))
2069   {
2070     goto except;
2071   }
2072   contained_elements = ntohl (msg->contained_element_count);
2073   msg_length = sizeof (struct MultipartMessage)
2074           +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2075   //sanity check
2076   if ((ntohs (msg->header.size) != msg_length)
2077       || (s->used_element_count < contained_elements + s->transferred_element_count)
2078       || (0 == contained_elements))
2079   {
2080     goto except;
2081   }
2082   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
2083   // Convert each vector element to MPI_value
2084   memcpy (&s->e_a[s->transferred_element_count], payload,
2085           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements);
2086
2087   s->transferred_element_count += contained_elements;
2088
2089   if (contained_elements == s->used_element_count)
2090   {
2091     // single part finished
2092     if (NULL == s->intersection_op)
2093       // intersection has already finished, so we can proceed
2094       compute_service_response (s);
2095   }
2096
2097   return GNUNET_OK;
2098 except:
2099   s->channel = NULL;
2100   // and notify our client-session that we could not complete the session
2101   free_session_variables (s);
2102   if (NULL != s->client)
2103   {
2104     //Alice
2105     s->active = GNUNET_SYSERR;
2106     s->client_notification_task =
2107           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2108                                     s);
2109   }
2110   else
2111   {
2112     //Bob
2113     if (NULL != s->response){
2114       s->response->active = GNUNET_SYSERR;
2115       s->response->client_notification_task =
2116             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2117                                       s->response);
2118     }
2119     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2120       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2121     GNUNET_free (s);
2122   }
2123   return GNUNET_SYSERR;
2124 }
2125
2126
2127 /**
2128  * Handle a request from another service to calculate a scalarproduct with us.
2129  *
2130  * @param cls closure (set from #GNUNET_CADET_connect)
2131  * @param channel connection to the other end
2132  * @param channel_ctx place to store local state associated with the channel
2133  * @param message the actual message
2134  * @return #GNUNET_OK to keep the connection open,
2135  *         #GNUNET_SYSERR to close it (signal serious error)
2136  */
2137 static int
2138 handle_alices_cyrptodata_message (void *cls,
2139                                   struct GNUNET_CADET_Channel * channel,
2140                                   void **channel_ctx,
2141                                   const struct GNUNET_MessageHeader * message)
2142 {
2143   struct ServiceSession * s;
2144   const struct AliceCryptodataMessage * msg = (const struct AliceCryptodataMessage *) message;
2145   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
2146   uint32_t contained_elements = 0;
2147   uint32_t msg_length;
2148
2149   s = (struct ServiceSession *) * channel_ctx;
2150   //we are not bob
2151   if ((BOB != s->role)
2152       //we are expecting multipart messages instead
2153       || (NULL != s->e_a)
2154       //or we did not expect this message yet
2155       || //intersection OP has not yet finished
2156       !((NULL != s->intersection_op)
2157         //intersection OP done
2158         || (s->response->sorted_elements)
2159         ))
2160   {
2161     goto invalid_msg;
2162   }
2163
2164   // shorter than minimum?
2165   if (ntohs (msg->header.size) <= sizeof (struct MultipartMessage))
2166   {
2167     goto invalid_msg;
2168   }
2169
2170   contained_elements = ntohl (msg->contained_element_count);
2171   msg_length = sizeof (struct AliceCryptodataMessage)
2172           +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2173
2174   //sanity check: is the message as long as the message_count fields suggests?
2175   if ((ntohs (msg->header.size) != msg_length) ||
2176       (s->used_element_count < s->transferred_element_count + contained_elements) ||
2177       (0 == contained_elements))
2178   {
2179     goto invalid_msg;
2180   }
2181
2182   s->transferred_element_count = contained_elements;
2183   payload = (struct GNUNET_CRYPTO_PaillierCiphertext*) &msg[1];
2184
2185   s->e_a = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
2186   memcpy (&s->e_a[0], payload, contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2187   if (contained_elements == s->used_element_count)
2188   {
2189     // single part finished
2190     if (NULL == s->intersection_op)
2191       // intersection has already finished, so we can proceed
2192       compute_service_response (s);
2193   }
2194   return GNUNET_OK;
2195 invalid_msg:
2196   GNUNET_break_op (0);
2197   s->channel = NULL;
2198   // and notify our client-session that we could not complete the session
2199   free_session_variables (s);
2200   if (NULL != s->client)
2201   {
2202     //Alice
2203     s->active = GNUNET_SYSERR;
2204     s->client_notification_task =
2205           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2206                                     s);
2207   }
2208   else
2209   {
2210     //Bob
2211     if (NULL != s->response)
2212     {
2213       s->response->active = GNUNET_SYSERR;
2214       s->response->client_notification_task =
2215               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2216                                         s->response);
2217     }
2218     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2219       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2220     GNUNET_free(s);
2221   }
2222   return GNUNET_SYSERR;
2223 }
2224
2225
2226 /**
2227  * Handle a request from another service to calculate a scalarproduct with us.
2228  *
2229  * @param cls closure (set from #GNUNET_CADET_connect)
2230  * @param channel connection to the other end
2231  * @param channel_ctx place to store local state associated with the channel
2232  * @param message the actual message
2233  * @return #GNUNET_OK to keep the connection open,
2234  *         #GNUNET_SYSERR to close it (signal serious error)
2235  */
2236 static int
2237 handle_alices_computation_request (void *cls,
2238                         struct GNUNET_CADET_Channel * channel,
2239                         void **channel_ctx,
2240                         const struct GNUNET_MessageHeader * message)
2241 {
2242   struct ServiceSession * s;
2243   struct ServiceSession * client_session;
2244   const struct ServiceRequestMessage * msg = (const struct ServiceRequestMessage *) message;
2245
2246   s = (struct ServiceSession *) * channel_ctx;
2247   if ((BOB != s->role) || (s->total != 0))
2248   {
2249     // must be a fresh session
2250     goto invalid_msg;
2251   }
2252   // Check if message was sent by me, which would be bad!
2253   if (!memcmp (&s->peer, &me, sizeof (struct GNUNET_PeerIdentity)))
2254   {
2255     GNUNET_free (s);
2256     GNUNET_break (0);
2257     return GNUNET_SYSERR;
2258   }
2259   // shorter than expected?
2260   if (ntohs (msg->header.size) != sizeof (struct ServiceRequestMessage))
2261   {
2262     GNUNET_free (s);
2263     GNUNET_break_op (0);
2264     return GNUNET_SYSERR;
2265   }
2266   if (find_matching_session (from_service_tail,
2267                              &msg->session_id,
2268                              NULL)) {
2269     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2270                 _ ("Got message with duplicate session key (`%s'), ignoring service request.\n"),
2271                 (const char *) &(msg->session_id));
2272     GNUNET_free (s);
2273     return GNUNET_SYSERR;
2274   }
2275
2276   s->channel = channel;
2277
2278   // session key
2279   memcpy (&s->session_id, &msg->session_id, sizeof (struct GNUNET_HashCode));
2280
2281   // public key
2282   s->remote_pubkey = GNUNET_new (struct GNUNET_CRYPTO_PaillierPublicKey);
2283   memcpy (s->remote_pubkey, &msg->public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
2284
2285   //check if service queue contains a matching request
2286   client_session = find_matching_session (from_client_tail,
2287                                           &s->session_id,
2288                                           NULL);
2289
2290   GNUNET_CONTAINER_DLL_insert (from_service_head, from_service_tail, s);
2291
2292   if ((NULL != client_session)
2293       && (client_session->transferred_element_count == client_session->total))
2294   {
2295
2296     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2297                 _("Got session with key %s and a matching element set, processing.\n"),
2298                 GNUNET_h2s (&s->session_id));
2299
2300     s->response = client_session;
2301     s->intersected_elements = client_session->intersected_elements;
2302     client_session->intersected_elements = NULL;
2303     s->intersection_set = client_session->intersection_set;
2304     client_session->intersection_set = NULL;
2305
2306     s->intersection_op = GNUNET_SET_prepare (&s->peer,
2307                                                    &s->session_id,
2308                                                    NULL,
2309                                                    GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX),
2310                                                    GNUNET_SET_RESULT_REMOVED,
2311                                                    cb_intersection_element_removed,
2312                                                    s);
2313
2314     GNUNET_SET_commit (s->intersection_op, s->intersection_set);
2315   }
2316   else
2317   {
2318     GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a matching element set, queueing.\n"), GNUNET_h2s (&s->session_id));
2319   }
2320
2321   return GNUNET_OK;
2322 invalid_msg:
2323   GNUNET_break_op (0);
2324   s->channel = NULL;
2325   // and notify our client-session that we could not complete the session
2326   free_session_variables (s);
2327   if (NULL != s->client)
2328   {
2329     //Alice
2330     s->active = GNUNET_SYSERR;
2331     s->client_notification_task =
2332           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2333                                     s);
2334   }
2335   else
2336   {
2337     //Bob
2338     if (NULL != s->response) {
2339       s->response->active = GNUNET_SYSERR;
2340       s->response->client_notification_task =
2341               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2342                                         s->response);
2343     }
2344     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2345       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2346     GNUNET_free(s);
2347   }
2348   return GNUNET_SYSERR;
2349 }
2350
2351
2352 /**
2353  * Handle a multipart chunk of a response we got from another service we wanted to calculate a scalarproduct with.
2354  *
2355  * @param cls closure (set from #GNUNET_CADET_connect)
2356  * @param channel connection to the other end
2357  * @param channel_ctx place to store local state associated with the channel
2358  * @param message the actual message
2359  * @return #GNUNET_OK to keep the connection open,
2360  *         #GNUNET_SYSERR to close it (signal serious error)
2361  */
2362 static int
2363 handle_bobs_cryptodata_multipart (void *cls,
2364                                    struct GNUNET_CADET_Channel * channel,
2365                                    void **channel_ctx,
2366                                    const struct GNUNET_MessageHeader * message)
2367 {
2368   struct ServiceSession * s;
2369   const struct MultipartMessage * msg = (const struct MultipartMessage *) message;
2370   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
2371   size_t i;
2372   uint32_t contained = 0;
2373   size_t msg_size;
2374   size_t required_size;
2375
2376   GNUNET_assert (NULL != message);
2377   // are we in the correct state?
2378   s = (struct ServiceSession *) * channel_ctx;
2379   if ((ALICE != s->role) || (NULL == s->sorted_elements))
2380   {
2381     goto invalid_msg;
2382   }
2383   msg_size = ntohs (msg->header.size);
2384   required_size = sizeof (struct MultipartMessage)
2385           + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2386   // shorter than minimum?
2387   if (required_size > msg_size)
2388   {
2389     goto invalid_msg;
2390   }
2391   contained = ntohl (msg->contained_element_count);
2392   required_size = sizeof (struct MultipartMessage)
2393           + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2394   //sanity check: is the message as long as the message_count fields suggests?
2395   if ((required_size != msg_size) || (s->used_element_count < s->transferred_element_count + contained))
2396   {
2397     goto invalid_msg;
2398   }
2399   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
2400   // Convert each k[][perm] to its MPI_value
2401   for (i = 0; i < contained; i++) {
2402     memcpy (&s->r[s->transferred_element_count + i], &payload[2 * i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2403     memcpy (&s->r_prime[s->transferred_element_count + i], &payload[2 * i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2404   }
2405   s->transferred_element_count += contained;
2406   if (s->transferred_element_count != s->used_element_count)
2407     return GNUNET_OK;
2408   s->product = compute_scalar_product (s); //never NULL
2409
2410 invalid_msg:
2411   GNUNET_break_op (NULL != s->product);
2412   s->channel = NULL;
2413   // send message with product to client
2414   if (NULL != s->client)
2415   {
2416     //Alice
2417     if (NULL != s->product)
2418       s->active = GNUNET_NO;
2419     else
2420       s->active = GNUNET_SYSERR;
2421     s->client_notification_task =
2422           GNUNET_SCHEDULER_add_now (&prepare_client_response,
2423                                     s);
2424   }
2425   else
2426   {
2427     //Bob
2428     if (NULL != s->response){
2429       s->response->active = GNUNET_SYSERR;
2430       s->response->client_notification_task =
2431               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2432                                         s->response);
2433     }
2434     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2435       GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2436     free_session_variables (s);
2437     GNUNET_free(s);
2438   }
2439   // the channel has done its job, terminate our connection and the channel
2440   // the peer will be notified that the channel was destroyed via channel_destruction_handler
2441   // just close the connection, as recommended by Christian
2442   return GNUNET_SYSERR;
2443 }
2444
2445
2446 /**
2447  * Handle a response we got from another service we wanted to calculate a scalarproduct with.
2448  *
2449  * @param cls closure (set from #GNUNET_CADET_connect)
2450  * @param channel connection to the other end
2451  * @param channel_ctx place to store local state associated with the channel
2452  * @param message the actual message
2453  * @return #GNUNET_OK to keep the connection open,
2454  *         #GNUNET_SYSERR to close it (we are done)
2455  */
2456 static int
2457 handle_bobs_cryptodata_message (void *cls,
2458                          struct GNUNET_CADET_Channel *channel,
2459                          void **channel_ctx,
2460                          const struct GNUNET_MessageHeader *message)
2461 {
2462   struct ServiceSession * s;
2463   const struct ServiceResponseMessage *msg = (const struct ServiceResponseMessage *) message;
2464   struct GNUNET_CRYPTO_PaillierCiphertext * payload;
2465   size_t i;
2466   uint32_t contained = 0;
2467   size_t msg_size;
2468   size_t required_size;
2469
2470   GNUNET_assert (NULL != message);
2471   s = (struct ServiceSession *) * channel_ctx;
2472   // are we in the correct state?
2473   if (NULL == s->sorted_elements
2474       || NULL != s->msg
2475       || s->used_element_count != s->transferred_element_count)
2476   {
2477     goto invalid_msg;
2478   }
2479   //we need at least a full message without elements attached
2480   msg_size = ntohs (msg->header.size);
2481   required_size = sizeof (struct ServiceResponseMessage) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2482
2483   if (required_size > msg_size)
2484   {
2485     goto invalid_msg;
2486   }
2487   contained = ntohl (msg->contained_element_count);
2488   required_size = sizeof (struct ServiceResponseMessage)
2489           + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)
2490           + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
2491   //sanity check: is the message as long as the message_count fields suggests?
2492   if ((msg_size != required_size) || (s->used_element_count < contained))
2493   {
2494     goto invalid_msg;
2495   }
2496   s->transferred_element_count = contained;
2497   //convert s
2498   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
2499
2500   s->s = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2501   s->s_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2502   memcpy (s->s, &payload[0], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2503   memcpy (s->s_prime, &payload[1], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2504
2505   s->r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
2506   s->r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * s->used_element_count);
2507
2508   payload = &payload[2];
2509   // Convert each k[][perm] to its MPI_value
2510   for (i = 0; i < contained; i++)
2511   {
2512     memcpy (&s->r[i], &payload[2 * i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2513     memcpy (&s->r_prime[i], &payload[2 * i + 1], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
2514   }
2515   if (s->transferred_element_count != s->used_element_count)
2516     return GNUNET_OK; //wait for the other multipart chunks
2517   s->product = compute_scalar_product (s); //never NULL
2518
2519 invalid_msg:
2520   GNUNET_break_op (NULL != s->product);
2521   s->channel = NULL;
2522   // send message with product to client
2523   if (NULL != s->client)
2524   {
2525     //Alice
2526     s->client_notification_task =
2527           GNUNET_SCHEDULER_add_now (&prepare_client_response,
2528                                     s);
2529   }
2530   else
2531   {
2532     //Bob
2533     if (NULL != s->response)
2534     {
2535       s->response->active = GNUNET_SYSERR;
2536       s->response->client_notification_task =
2537               GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
2538                                         s->response);
2539     }
2540     if ((s == from_service_head) || ((NULL != from_service_head) && ((NULL != s->next) || (NULL != s->a_tail))))
2541         GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, s);
2542     free_session_variables (s);
2543     GNUNET_free(s);
2544   }
2545   // the channel has done its job, terminate our connection and the channel
2546   // the peer will be notified that the channel was destroyed via channel_destruction_handler
2547   // just close the connection, as recommended by Christian
2548   return GNUNET_SYSERR;
2549 }
2550
2551
2552 /**
2553  * Task run during shutdown.
2554  *
2555  * @param cls unused
2556  * @param tc unused
2557  */
2558 static void
2559 shutdown_task (void *cls,
2560                const struct GNUNET_SCHEDULER_TaskContext *tc)
2561 {
2562   struct ServiceSession * s;
2563
2564   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2565               _("Shutting down, initiating cleanup.\n"));
2566
2567   do_shutdown = GNUNET_YES;
2568
2569   // terminate all owned open channels.
2570   for (s = from_client_head; NULL != s; s = s->next)
2571   {
2572     if ((GNUNET_NO != s->active) && (NULL != s->channel))
2573     {
2574       GNUNET_CADET_channel_destroy (s->channel);
2575       s->channel = NULL;
2576     }
2577     if (GNUNET_SCHEDULER_NO_TASK != s->client_notification_task)
2578     {
2579       GNUNET_SCHEDULER_cancel (s->client_notification_task);
2580       s->client_notification_task = GNUNET_SCHEDULER_NO_TASK;
2581     }
2582     if (NULL != s->client)
2583     {
2584       GNUNET_SERVER_client_disconnect (s->client);
2585       s->client = NULL;
2586     }
2587   }
2588   for (s = from_service_head; NULL != s; s = s->next)
2589     if (NULL != s->channel)
2590     {
2591       GNUNET_CADET_channel_destroy (s->channel);
2592       s->channel = NULL;
2593     }
2594
2595   if (my_cadet)
2596   {
2597     GNUNET_CADET_disconnect (my_cadet);
2598     my_cadet = NULL;
2599   }
2600 }
2601
2602
2603 /**
2604  * Initialization of the program and message handlers
2605  *
2606  * @param cls closure
2607  * @param server the initialized server
2608  * @param c configuration to use
2609  */
2610 static void
2611 run (void *cls,
2612      struct GNUNET_SERVER_Handle *server,
2613      const struct GNUNET_CONFIGURATION_Handle *c)
2614 {
2615   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
2616     {&handle_client_message, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE, 0},
2617     {&handle_client_message, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB, 0},
2618     {&handle_client_message_multipart, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART, 0},
2619     {NULL, NULL, 0, 0}
2620   };
2621   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
2622     { &handle_alices_computation_request, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION, 0},
2623     { &handle_alices_cyrptodata_message, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA, 0},
2624     { &handle_alices_cyrptodata_message_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA_MULTIPART, 0},
2625     { &handle_bobs_cryptodata_message, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA, 0},
2626     { &handle_bobs_cryptodata_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART, 0},
2627     {NULL, 0, 0}
2628   };
2629   static const uint32_t ports[] = {
2630     GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
2631     0
2632   };
2633   cfg = c;
2634
2635   //generate private/public key set
2636   GNUNET_CRYPTO_paillier_create (&my_pubkey, &my_privkey);
2637
2638   // offset has to be sufficiently small to allow computation of:
2639   // m1+m2 mod n == (S + a) + (S + b) mod n,
2640   // if we have more complex operations, this factor needs to be lowered
2641   my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
2642   gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3);
2643
2644   // register server callbacks and disconnect handler
2645   GNUNET_SERVER_add_handlers (server, server_handlers);
2646   GNUNET_SERVER_disconnect_notify (server,
2647                                    &cb_client_disconnect,
2648                                    NULL);
2649   GNUNET_break (GNUNET_OK ==
2650                 GNUNET_CRYPTO_get_peer_identity (cfg,
2651                                                  &me));
2652   my_cadet = GNUNET_CADET_connect (cfg, NULL,
2653                                  &cb_channel_incoming,
2654                                  &cb_channel_destruction,
2655                                  cadet_handlers, ports);
2656   if (!my_cadet)
2657   {
2658     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2659                 _("Connect to CADET failed\n"));
2660     GNUNET_SCHEDULER_shutdown ();
2661     return;
2662   }
2663   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2664               _("CADET initialized\n"));
2665   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2666                                 &shutdown_task,
2667                                 NULL);
2668 }
2669
2670
2671 /**
2672  * The main function for the scalarproduct service.
2673  *
2674  * @param argc number of arguments from the command line
2675  * @param argv command line arguments
2676  * @return 0 ok, 1 on error
2677  */
2678 int
2679 main (int argc, char *const *argv)
2680 {
2681   return (GNUNET_OK ==
2682           GNUNET_SERVICE_run (argc, argv,
2683                               "scalarproduct",
2684                               GNUNET_SERVICE_OPTION_NONE,
2685                               &run, NULL)) ? 0 : 1;
2686 }
2687
2688 /* end of gnunet-service-scalarproduct.c */