massive rework of scalarproduct service, splitting into Alice and Bob
[oweals/gnunet.git] / src / scalarproduct / gnunet-service-scalarproduct_bob.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  * @file scalarproduct/gnunet-service-scalarproduct_bob.c
22  * @brief scalarproduct service implementation
23  * @author Christian M. Fuchs
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include <limits.h>
28 #include <gcrypt.h>
29 #include "gnunet_util_lib.h"
30 #include "gnunet_core_service.h"
31 #include "gnunet_cadet_service.h"
32 #include "gnunet_applications.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_scalarproduct_service.h"
35 #include "gnunet_set_service.h"
36 #include "scalarproduct.h"
37 #include "gnunet-service-scalarproduct.h"
38
39 #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct-bob", __VA_ARGS__)
40
41
42 /**
43  * An encrypted element key-value pair.
44  */
45 struct MpiElement
46 {
47   /**
48    * Key used to identify matching pairs of values to multiply.
49    * Points into an existing data structure, to avoid copying
50    * and doubling memory use.
51    */
52   const struct GNUNET_HashCode *key;
53
54   /**
55    * Value represented (a).
56    */
57   gcry_mpi_t value;
58 };
59
60
61 /**
62  * An incoming session from CADET.
63  */
64 struct CadetIncomingSession;
65
66
67 /**
68  * A scalarproduct session which tracks an offer for a
69  * multiplication service by a local client.
70  */
71 struct BobServiceSession
72 {
73
74   /**
75    * (hopefully) unique transaction ID
76    */
77   struct GNUNET_HashCode session_id;
78
79   /**
80    * The client this request is related to.
81    */
82   struct GNUNET_SERVER_Client *client;
83
84   /**
85    * Client message queue.
86    */
87   struct GNUNET_MQ_Handle *client_mq;
88
89   /**
90    * All non-0-value'd elements transmitted to us.
91    */
92   struct GNUNET_CONTAINER_MultiHashMap *intersected_elements;
93
94   /**
95    * Set of elements for which we will be conducting an intersection.
96    * The resulting elements are then used for computing the scalar product.
97    */
98   struct GNUNET_SET_Handle *intersection_set;
99
100   /**
101    * Set of elements for which will conduction an intersection.
102    * the resulting elements are then used for computing the scalar product.
103    */
104   struct GNUNET_SET_OperationHandle *intersection_op;
105
106   /**
107    * a(Alice)
108    */
109   struct MpiElement *sorted_elements;
110
111   /**
112    * E(ai)(Bob) after applying the mask
113    */
114   struct GNUNET_CRYPTO_PaillierCiphertext *e_a;
115
116   /**
117    * Bob's permutation p of R
118    */
119   struct GNUNET_CRYPTO_PaillierCiphertext *r;
120
121   /**
122    * Bob's permutation q of R
123    */
124   struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
125
126   /**
127    * Bob's "s"
128    */
129   struct GNUNET_CRYPTO_PaillierCiphertext s;
130
131   /**
132    * Bob's "s'"
133    */
134   struct GNUNET_CRYPTO_PaillierCiphertext s_prime;
135
136   /**
137    * Handle for our associated incoming CADET session, or NULL
138    * if we have not gotten one yet.
139    */
140   struct CadetIncomingSession *cadet;
141
142   /**
143    * The computed scalar
144    */
145   gcry_mpi_t product;
146
147   /**
148    * How many elements we were supplied with from the client
149    */
150   uint32_t total;
151
152   /**
153    * how many elements actually are used for the scalar product.
154    * Size of the arrays in @e r and @e r_prime.
155    */
156   uint32_t used_element_count;
157
158   /**
159    * already transferred elements (sent/received) for multipart messages, less or equal than @e used_element_count for
160    */
161   uint32_t transferred_element_count;
162
163   /**
164    * Is this session active (#GNUNET_YES), Concluded (#GNUNET_NO), or had an error (#GNUNET_SYSERR)
165    */
166   int32_t active;
167
168   /**
169    * Are we already in #destroy_service_session()?
170    */
171   int in_destroy;
172
173 };
174
175
176 /**
177  * An incoming session from CADET.
178  */
179 struct CadetIncomingSession
180 {
181
182   /**
183    * Associated client session, or NULL.
184    */
185   struct BobServiceSession *s;
186
187   /**
188    * The CADET channel.
189    */
190   struct GNUNET_CADET_Channel *channel;
191
192   /**
193    * Originator's peer identity. (Only for diagnostics.)
194    */
195   struct GNUNET_PeerIdentity peer;
196
197   /**
198    * (hopefully) unique transaction ID
199    */
200   struct GNUNET_HashCode session_id;
201
202   /**
203    * Public key of the remote service.
204    */
205   struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey;
206
207   /**
208    * The message queue for this channel.
209    */
210   struct GNUNET_MQ_Handle *cadet_mq;
211
212   /**
213    * Has this CADET session been added to the map yet?
214    * #GNUNET_YES if so, in which case @e session_id is
215    * the key.
216    */
217   int in_map;
218
219   /**
220    * Are we already in #destroy_cadet_session()?
221    */
222   int in_destroy;
223
224 };
225
226
227 /**
228  * GNUnet configuration handle
229  */
230 static const struct GNUNET_CONFIGURATION_Handle *cfg;
231
232 /**
233  * Service's own public key
234  */
235 static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey;
236
237 /**
238  * Service's own private key
239  */
240 static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey;
241
242 /**
243  * Service's offset for values that could possibly be negative but are plaintext for encryption.
244  */
245 static gcry_mpi_t my_offset;
246
247 /**
248  * Map of `struct BobServiceSession`, by session keys.
249  */
250 static struct GNUNET_CONTAINER_MultiHashMap *client_sessions;
251
252 /**
253  * Map of `struct CadetIncomingSession`, by session keys.
254  */
255 static struct GNUNET_CONTAINER_MultiHashMap *cadet_sessions;
256
257 /**
258  * Handle to the CADET service.
259  */
260 static struct GNUNET_CADET_Handle *my_cadet;
261
262 /**
263  * Certain events (callbacks for server & cadet operations) must not
264  * be queued after shutdown.
265  */
266 static int do_shutdown;
267
268
269
270 /**
271  * Finds a not terminated client session in the respective map based on
272  * session key.
273  *
274  * @param key the session key we want to search for
275  * @return the matching session, or NULL for none
276  */
277 static struct BobServiceSession *
278 find_matching_client_session (const struct GNUNET_HashCode *key)
279 {
280   return GNUNET_CONTAINER_multihashmap_get (client_sessions,
281                                             key);
282 }
283
284
285 /**
286  * Finds a CADET session in the respective map based on session key.
287  *
288  * @param key the session key we want to search for
289  * @return the matching session, or NULL for none
290  */
291 static struct CadetIncomingSession *
292 find_matching_cadet_session (const struct GNUNET_HashCode *key)
293 {
294   return GNUNET_CONTAINER_multihashmap_get (cadet_sessions,
295                                             key);
296 }
297
298
299 /**
300  * Destroy session state, we are done with it.
301  *
302  * @param session the session to free elements from
303  */
304 static void
305 destroy_cadet_session (struct CadetIncomingSession *s);
306
307
308 /**
309  * Destroy session state, we are done with it.
310  *
311  * @param session the session to free elements from
312  */
313 static void
314 destroy_service_session (struct BobServiceSession *s)
315 {
316   struct CadetIncomingSession *in;
317   unsigned int i;
318
319   if (GNUNET_YES == s->in_destroy)
320     return;
321   s->in_destroy = GNUNET_YES;
322   if (NULL != (in = s->cadet))
323   {
324     s->cadet = NULL;
325     destroy_cadet_session (in);
326   }
327   if (NULL != s->client_mq)
328   {
329     GNUNET_MQ_destroy (s->client_mq);
330     s->client_mq = NULL;
331   }
332   if (NULL != s->client)
333   {
334     GNUNET_SERVER_client_disconnect (s->client);
335     s->client = NULL;
336   }
337   GNUNET_assert (GNUNET_YES ==
338                  GNUNET_CONTAINER_multihashmap_remove (client_sessions,
339                                                        &s->session_id,
340                                                        s));
341   if (NULL != s->intersected_elements)
342   {
343     /* FIXME: free elements */
344     GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements);
345     s->intersected_elements = NULL;
346   }
347   if (NULL != s->intersection_op)
348   {
349     GNUNET_SET_operation_cancel (s->intersection_op);
350     s->intersection_op = NULL;
351   }
352   if (NULL != s->intersection_set)
353   {
354     GNUNET_SET_destroy (s->intersection_set);
355     s->intersection_set = NULL;
356   }
357   if (NULL != s->e_a)
358   {
359     GNUNET_free (s->e_a);
360     s->e_a = NULL;
361   }
362   if (NULL != s->sorted_elements)
363   {
364     for (i=0;i<s->used_element_count;i++)
365       gcry_mpi_release (s->sorted_elements[i].value);
366     GNUNET_free (s->sorted_elements);
367     s->sorted_elements = NULL;
368   }
369   if (NULL != s->r)
370   {
371     GNUNET_free (s->r);
372     s->r = NULL;
373   }
374   if (NULL != s->r_prime)
375   {
376     GNUNET_free (s->r_prime);
377     s->r_prime = NULL;
378   }
379   if (NULL != s->product)
380   {
381     gcry_mpi_release (s->product);
382     s->product = NULL;
383   }
384   GNUNET_free (s);
385 }
386
387
388 /**
389  * Destroy incoming CADET session state, we are done with it.
390  *
391  * @param in the session to free elements from
392  */
393 static void
394 destroy_cadet_session (struct CadetIncomingSession *in)
395 {
396   struct BobServiceSession *s;
397
398   if (GNUNET_YES == in->in_destroy)
399     return;
400   in->in_destroy = GNUNET_YES;
401   if (NULL != (s = in->s))
402   {
403     in->s = NULL;
404     destroy_service_session (s);
405   }
406   if (GNUNET_YES == in->in_map)
407   {
408     GNUNET_assert (GNUNET_YES ==
409                    GNUNET_CONTAINER_multihashmap_remove (cadet_sessions,
410                                                          &in->session_id,
411                                                          in));
412     in->in_map = GNUNET_NO;
413   }
414   if (NULL != in->cadet_mq)
415   {
416     GNUNET_MQ_destroy (in->cadet_mq);
417     in->cadet_mq = NULL;
418   }
419   if (NULL != in->channel)
420   {
421     GNUNET_CADET_channel_destroy (in->channel);
422     in->channel = NULL;
423   }
424   GNUNET_free (in);
425 }
426
427
428 /**
429  * Notify the client that the session has succeeded or failed.  This
430  * message gets sent to Bob's client if the operation completed or
431  * Alice disconnected.
432  *
433  * @param session the associated client session to fail or succeed
434  */
435 static void
436 prepare_client_end_notification (struct BobServiceSession *session)
437 {
438   struct ClientResponseMessage *msg;
439   struct GNUNET_MQ_Envelope *e;
440
441   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
442               "Sending session-end notification with status %d to client for session %s\n",
443               session->active,
444               GNUNET_h2s (&session->session_id));
445   e = GNUNET_MQ_msg (msg,
446                      GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT);
447   msg->range = 0;
448   msg->product_length = htonl (0);
449   msg->status = htonl (session->active);
450   GNUNET_MQ_send (session->client_mq,
451                   e);
452 }
453
454
455 /**
456  * Function called whenever a channel is destroyed.  Should clean up
457  * any associated state.
458  *
459  * It must NOT call #GNUNET_CADET_channel_destroy() on the channel.
460  *
461  * @param cls closure (set from #GNUNET_CADET_connect())
462  * @param channel connection to the other end (henceforth invalid)
463  * @param channel_ctx place where local state associated
464  *                   with the channel is stored
465  */
466 static void
467 cb_channel_destruction (void *cls,
468                         const struct GNUNET_CADET_Channel *channel,
469                         void *channel_ctx)
470 {
471   struct CadetIncomingSession *in = channel_ctx;
472   struct BobServiceSession *s;
473
474   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
475               "Peer disconnected, terminating session %s with peer %s\n",
476               GNUNET_h2s (&in->session_id),
477               GNUNET_i2s (&in->peer));
478   in->channel = NULL;
479   if (NULL != (s = in->s))
480   {
481     if (GNUNET_YES == s->active)
482     {
483       s->active = GNUNET_SYSERR;
484       prepare_client_end_notification (s);
485     }
486   }
487   destroy_cadet_session (in);
488 }
489
490
491 /**
492  * MQ finished giving our last message to CADET, now notify
493  * the client that we are finished.
494  */
495 static void
496 bob_cadet_done_cb (void *cls)
497 {
498   struct BobServiceSession *session = cls;
499
500   session->active = GNUNET_NO; /* that means, done */
501   prepare_client_end_notification (session);
502 }
503
504
505 /**
506  * Maximum count of elements we can put into a multipart message
507  */
508 #define ELEMENT_CAPACITY ((GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct MultipartMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext))
509
510
511 /**
512  * Send a multipart chunk of a service response from Bob to Alice.
513  * This element only contains the two permutations of R, R'.
514  *
515  * @param s the associated service session
516  */
517 static void
518 transmit_bobs_cryptodata_message_multipart (struct BobServiceSession *s)
519 {
520   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
521   struct MultipartMessage *msg;
522   struct GNUNET_MQ_Envelope *e;
523   unsigned int i;
524   unsigned int j;
525   uint32_t todo_count;
526
527   while (s->transferred_element_count != s->used_element_count)
528   {
529     todo_count = s->used_element_count - s->transferred_element_count;
530     if (todo_count > ELEMENT_CAPACITY / 2)
531       todo_count = ELEMENT_CAPACITY / 2;
532
533     e = GNUNET_MQ_msg_extra (msg,
534                              todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2,
535                              GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART);
536     msg->contained_element_count = htonl (todo_count);
537     payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
538     for (i = s->transferred_element_count, j = 0; i < s->transferred_element_count + todo_count; i++)
539     {
540       //r[i][p] and r[i][q]
541       memcpy (&payload[j++],
542               &s->r[i],
543               sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
544       memcpy (&payload[j++],
545               &s->r_prime[i],
546               sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
547     }
548     s->transferred_element_count += todo_count;
549     if (s->transferred_element_count == s->used_element_count)
550       GNUNET_MQ_notify_sent (e,
551                              &bob_cadet_done_cb,
552                              s);
553     GNUNET_MQ_send (s->cadet->cadet_mq,
554                     e);
555   }
556 }
557
558
559 /**
560  * Bob generates the response message to be sent to Alice after
561  * computing the values (1), (2), S and S'.
562  *
563  *  (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)})$
564  *  (2)[]: $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
565  *      S: $S := E_A(sum (r_i + b_i)^2)$
566  *     S': $S' := E_A(sum r_i^2)$
567  *
568  * @param s the associated requesting session with Alice
569  */
570 static void
571 transmit_bobs_cryptodata_message (struct BobServiceSession *s)
572 {
573   struct ServiceResponseMessage *msg;
574   struct GNUNET_MQ_Envelope *e;
575   struct GNUNET_CRYPTO_PaillierCiphertext *payload;
576   unsigned int i;
577
578   s->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct ServiceResponseMessage)) /
579     (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2) - 2;
580   if (s->transferred_element_count > s->used_element_count)
581     s->transferred_element_count = s->used_element_count;
582
583   e = GNUNET_MQ_msg_extra (msg,
584                            (2 + s->transferred_element_count * 2)
585                            * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext),
586                            GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_CRYPTODATA);
587   msg->total_element_count = htonl (s->total);
588   msg->used_element_count = htonl (s->used_element_count);
589   msg->contained_element_count = htonl (s->transferred_element_count);
590   msg->key = s->session_id;
591
592   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
593   memcpy (&payload[0],
594           &s->s,
595           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
596   memcpy (&payload[1],
597           &s->s_prime,
598           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
599
600   payload = &payload[2];
601   // convert k[][]
602   for (i = 0; i < s->transferred_element_count; i++)
603   {
604     //k[i][p] and k[i][q]
605     memcpy (&payload[i * 2],
606             &s->r[i],
607             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
608     memcpy (&payload[i * 2 + 1],
609             &s->r_prime[i],
610             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
611   }
612   if (s->transferred_element_count == s->used_element_count)
613     GNUNET_MQ_notify_sent (e,
614                            &bob_cadet_done_cb,
615                            s);
616   GNUNET_MQ_send (s->cadet->cadet_mq,
617                   e);
618   transmit_bobs_cryptodata_message_multipart (s);
619 }
620
621
622 /**
623  * Computes the square sum over a vector of a given length.
624  *
625  * @param vector the vector to compute over
626  * @param length the length of the vector
627  * @return an MPI value containing the calculated sum, never NULL
628  */
629 static gcry_mpi_t
630 compute_square_sum (const gcry_mpi_t *vector,
631                     uint32_t length)
632 {
633   gcry_mpi_t elem;
634   gcry_mpi_t sum;
635   uint32_t i;
636
637   GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
638   GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
639   for (i = 0; i < length; i++)
640   {
641     gcry_mpi_mul (elem, vector[i], vector[i]);
642     gcry_mpi_add (sum, sum, elem);
643   }
644   gcry_mpi_release (elem);
645   return sum;
646 }
647
648
649 /**
650  * Compute the values
651  *  (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)})$
652  *  (2)[]: $E_A(a_{pi'(i)}) otimes E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
653  *      S: $S := E_A(sum (r_i + b_i)^2)$
654  *     S': $S' := E_A(sum r_i^2)$
655  *
656  * @param request the requesting session + bob's requesting peer
657  */
658 static void
659 compute_service_response (struct BobServiceSession *session)
660 {
661   uint32_t i;
662   unsigned int *p;
663   unsigned int *q;
664   uint32_t count;
665   gcry_mpi_t *rand;
666   gcry_mpi_t tmp;
667   const struct MpiElement *b;
668   struct GNUNET_CRYPTO_PaillierCiphertext *a;
669   struct GNUNET_CRYPTO_PaillierCiphertext *r;
670   struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
671
672   count = session->used_element_count;
673   a = session->e_a;
674   b = session->sorted_elements;
675   q = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
676                                     count);
677   p = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
678                                     count);
679   rand = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
680   for (i = 0; i < count; i++)
681     GNUNET_assert (NULL != (rand[i] = gcry_mpi_new (0)));
682   r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
683   r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
684
685   for (i = 0; i < count; i++)
686   {
687     int32_t svalue;
688
689     svalue = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
690                                                  UINT32_MAX);
691     // long to gcry_mpi_t
692     if (svalue < 0)
693       gcry_mpi_sub_ui (rand[i],
694                        rand[i],
695                        - svalue);
696     else
697       rand[i] = gcry_mpi_set_ui (rand[i], svalue);
698   }
699
700   tmp = gcry_mpi_new (0);
701   // encrypt the element
702   // for the sake of readability I decided to have dedicated permutation
703   // vectors, which get rid of all the lookups in p/q.
704   // however, ap/aq are not absolutely necessary but are just abstraction
705   // Calculate Kp = E(S + a_pi) (+) E(S - r_pi - b_pi)
706   for (i = 0; i < count; i++)
707   {
708     // E(S - r_pi - b_pi)
709     gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
710     gcry_mpi_sub (tmp, tmp, b[p[i]].value);
711     GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
712                                     tmp,
713                                     2,
714                                     &r[i]);
715
716     // E(S - r_pi - b_pi) * E(S + a_pi) ==  E(2*S + a - r - b)
717     GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
718                                     &r[i],
719                                     &a[p[i]],
720                                     &r[i]);
721   }
722
723   // Calculate Kq = E(S + a_qi) (+) E(S - r_qi)
724   for (i = 0; i < count; i++)
725   {
726     // E(S - r_qi)
727     gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
728     GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
729                                                         tmp,
730                                                         2,
731                                                         &r_prime[i]));
732
733     // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
734     GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
735                                                         &r_prime[i],
736                                                         &a[q[i]],
737                                                         &r_prime[i]));
738   }
739
740   // Calculate S' =  E(SUM( r_i^2 ))
741   tmp = compute_square_sum (rand, count);
742   GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
743                                   tmp,
744                                   1,
745                                   &session->s_prime);
746
747   // Calculate S = E(SUM( (r_i + b_i)^2 ))
748   for (i = 0; i < count; i++)
749     gcry_mpi_add (rand[i], rand[i], b[i].value);
750   tmp = compute_square_sum (rand, count);
751   GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
752                                   tmp,
753                                   1,
754                                   &session->s);
755
756   session->r = r;
757   session->r_prime = r_prime;
758
759   // release rand, b and a
760   for (i = 0; i < count; i++)
761     gcry_mpi_release (rand[i]);
762   gcry_mpi_release (tmp);
763   GNUNET_free (session->e_a);
764   session->e_a = NULL;
765   GNUNET_free (p);
766   GNUNET_free (q);
767   GNUNET_free (rand);
768
769   // copy the r[], r_prime[], S and Stick into a new message, prepare_service_response frees these
770 }
771
772
773
774
775
776 /**
777  * Iterator to copy over messages from the hash map
778  * into an array for sorting.
779  *
780  * @param cls the `struct AliceServiceSession *`
781  * @param key the key (unused)
782  * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
783  */
784 static int
785 copy_element_cb (void *cls,
786                  const struct GNUNET_HashCode *key,
787                  void *value)
788 {
789   struct BobServiceSession *s = cls;
790   struct GNUNET_SCALARPRODUCT_Element *e = value;
791   gcry_mpi_t mval;
792   int64_t val;
793
794   mval = gcry_mpi_new (0);
795   val = (int64_t) GNUNET_ntohll (e->value);
796   if (0 > val)
797     gcry_mpi_sub_ui (mval, mval, -val);
798   else
799     gcry_mpi_add_ui (mval, mval, val);
800   s->sorted_elements [s->used_element_count].value = mval;
801   s->sorted_elements [s->used_element_count].key = &e->key;
802   s->used_element_count++;
803   return GNUNET_OK;
804 }
805
806
807 /**
808  * Compare two `struct MpiValue`s by key for sorting.
809  *
810  * @param a pointer to first `struct MpiValue *`
811  * @param b pointer to first `struct MpiValue *`
812  * @return -1 for a < b, 0 for a=b, 1 for a > b.
813  */
814 static int
815 element_cmp (const void *a,
816              const void *b)
817 {
818   const struct MpiElement *ma = *(const struct MpiElement **) a;
819   const struct MpiElement *mb = *(const struct MpiElement **) b;
820
821   return GNUNET_CRYPTO_hash_cmp (ma->key,
822                                  mb->key);
823 }
824
825
826 /**
827  * Intersection operation and receiving data via CADET from
828  * Alice are both done, compute and transmit our reply via
829  * CADET.
830  *
831  * @param s session to transmit reply for.
832  */
833 static void
834 transmit_cryptographic_reply (struct BobServiceSession *s)
835 {
836   s->sorted_elements
837     = GNUNET_malloc (GNUNET_CONTAINER_multihashmap_size (s->intersected_elements) *
838                      sizeof (struct MpiElement));
839   s->used_element_count = 0;
840   GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
841                                          &copy_element_cb,
842                                          s);
843   LOG (GNUNET_ERROR_TYPE_DEBUG,
844        "Finished intersection, %d items remain\n",
845        s->used_element_count);
846   qsort (s->intersected_elements,
847          s->used_element_count,
848          sizeof (struct MpiElement),
849          &element_cmp);
850   compute_service_response (s);
851   transmit_bobs_cryptodata_message (s);
852 }
853
854
855 /**
856  * Handle a multipart-chunk of a request from another service to
857  * calculate a scalarproduct with us.
858  *
859  * @param cls closure (set from #GNUNET_CADET_connect)
860  * @param channel connection to the other end
861  * @param channel_ctx place to store local state associated with the @a channel
862  * @param message the actual message
863  * @return #GNUNET_OK to keep the connection open,
864  *         #GNUNET_SYSERR to close it (signal serious error)
865  */
866 static int
867 handle_alices_cryptodata_message (void *cls,
868                                   struct GNUNET_CADET_Channel *channel,
869                                   void **channel_ctx,
870                                   const struct GNUNET_MessageHeader *message)
871 {
872   struct CadetIncomingSession *in = *channel_ctx;
873   struct BobServiceSession *s;
874   const struct AliceCryptodataMessage *msg;
875   const struct GNUNET_CRYPTO_PaillierCiphertext *payload;
876   uint32_t contained_elements;
877   size_t msg_length;
878   uint16_t msize;
879   unsigned int max;
880
881   if (NULL == in)
882   {
883     GNUNET_break_op (0);
884     return GNUNET_SYSERR;
885   }
886   s = in->s;
887   if (NULL == s)
888   {
889     GNUNET_break_op (0);
890     return GNUNET_SYSERR;
891   }
892   msize = ntohs (message->size);
893   if (msize <= sizeof (struct AliceCryptodataMessage))
894   {
895     GNUNET_break_op (0);
896     return GNUNET_SYSERR;
897   }
898   msg = (const struct AliceCryptodataMessage *) message;
899   contained_elements = ntohl (msg->contained_element_count);
900   /* Our intersection may still be ongoing, but this is nevertheless
901      an upper bound on the required array size */
902   max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
903   msg_length = sizeof (struct AliceCryptodataMessage)
904     + contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
905   if ( (msize != msg_length) ||
906        (0 == contained_elements) ||
907        (contained_elements > UINT16_MAX) ||
908        (max < contained_elements + s->transferred_element_count) )
909   {
910     GNUNET_break_op (0);
911     return GNUNET_SYSERR;
912   }
913
914   payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
915   if (NULL == s->e_a)
916     s->e_a = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) *
917                             max);
918   memcpy (&s->e_a[s->transferred_element_count],
919           payload,
920           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements);
921   s->transferred_element_count += contained_elements;
922
923   if ( (s->transferred_element_count == max) &&
924        (NULL == s->intersection_op) )
925   {
926     /* intersection has finished also on our side, and
927        we got the full set, so we can proceed with the
928        CADET response(s) */
929     transmit_cryptographic_reply (s);
930   }
931   return GNUNET_OK;
932 }
933
934
935 /**
936  * Callback for set operation results. Called for each element
937  * that needs to be removed from the result set.
938  *
939  * @param cls closure with the `struct BobServiceSession`
940  * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
941  * @param status what has happened with the set intersection?
942  */
943 static void
944 cb_intersection_element_removed (void *cls,
945                                  const struct GNUNET_SET_Element *element,
946                                  enum GNUNET_SET_Status status)
947 {
948   struct BobServiceSession *s = cls;
949   struct GNUNET_SCALARPRODUCT_Element *se;
950
951   switch (status)
952   {
953   case GNUNET_SET_STATUS_OK:
954     /* this element has been removed from the set */
955     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
956                                             element->data);
957     LOG (GNUNET_ERROR_TYPE_DEBUG,
958          "Removed element with key %s and value %lld\n",
959          GNUNET_h2s (&se->key),
960          (long long) GNUNET_ntohll (se->value));
961     GNUNET_assert (GNUNET_YES ==
962                    GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
963                                                          element->data,
964                                                          se));
965     GNUNET_free (se);
966     return;
967   case GNUNET_SET_STATUS_DONE:
968     s->intersection_op = NULL;
969     s->intersection_set = NULL;
970     if (s->transferred_element_count ==
971         GNUNET_CONTAINER_multihashmap_size (s->intersected_elements))
972     {
973       /* CADET transmission from Alice is also already done,
974          start with our own reply */
975       transmit_cryptographic_reply (s);
976     }
977     return;
978   case GNUNET_SET_STATUS_HALF_DONE:
979     /* unexpected for intersection */
980     GNUNET_break (0);
981     return;
982   case GNUNET_SET_STATUS_FAILURE:
983     /* unhandled status code */
984     LOG (GNUNET_ERROR_TYPE_DEBUG,
985          "Set intersection failed!\n");
986     s->intersection_op = NULL;
987     s->intersection_set = NULL;
988     s->active = GNUNET_SYSERR;
989     prepare_client_end_notification (s);
990     return;
991   default:
992     GNUNET_break (0);
993     return;
994   }
995 }
996
997
998 /**
999  * We've paired up a client session with an incoming CADET request.
1000  * Initiate set intersection work.
1001  *
1002  * @param s client session to start intersection for
1003  */
1004 static void
1005 start_intersection (struct BobServiceSession *s)
1006 {
1007   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008               "Got session with key %s and a matching element set, processing.\n",
1009               GNUNET_h2s (&s->session_id));
1010
1011   s->intersection_op
1012     = GNUNET_SET_prepare (&s->cadet->peer,
1013                           &s->session_id,
1014                           NULL,
1015                           GNUNET_SET_RESULT_REMOVED,
1016                           &cb_intersection_element_removed,
1017                           s);
1018   GNUNET_SET_commit (s->intersection_op,
1019                      s->intersection_set);
1020 }
1021
1022
1023 /**
1024  * Handle a request from Alice to calculate a scalarproduct with us (Bob).
1025  *
1026  * @param cls closure (set from #GNUNET_CADET_connect)
1027  * @param channel connection to the other end
1028  * @param channel_ctx place to store the `struct CadetIncomingSession *`
1029  * @param message the actual message
1030  * @return #GNUNET_OK to keep the connection open,
1031  *         #GNUNET_SYSERR to close it (signal serious error)
1032  */
1033 static int
1034 handle_alices_computation_request (void *cls,
1035                                    struct GNUNET_CADET_Channel *channel,
1036                                    void **channel_ctx,
1037                                    const struct GNUNET_MessageHeader *message)
1038 {
1039   struct CadetIncomingSession *in = *channel_ctx;
1040   struct BobServiceSession *s;
1041   const struct ServiceRequestMessage *msg;
1042
1043   if (ntohs (message->size) != sizeof (struct ServiceRequestMessage))
1044   {
1045     GNUNET_break_op (0);
1046     return GNUNET_SYSERR;
1047   }
1048   msg = (const struct ServiceRequestMessage *) message;
1049   if (GNUNET_YES == in->in_map)
1050   {
1051     GNUNET_break_op (0);
1052     return GNUNET_SYSERR;
1053   }
1054   if (NULL != find_matching_cadet_session (&msg->session_id))
1055   {
1056     /* not unique, got one like this already */
1057     GNUNET_break_op (0);
1058     return GNUNET_SYSERR;
1059   }
1060   in->session_id = msg->session_id;
1061   in->remote_pubkey = msg->public_key;
1062   GNUNET_assert (GNUNET_YES ==
1063                  GNUNET_CONTAINER_multihashmap_put (cadet_sessions,
1064                                                     &in->session_id,
1065                                                     in,
1066                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1067   s = find_matching_client_session (&in->session_id);
1068   if (NULL == s)
1069   {
1070     /* no client waiting for this request, wait for client */
1071     return GNUNET_OK;
1072   }
1073   GNUNET_assert (NULL == s->cadet);
1074   /* pair them up */
1075   in->s = s;
1076   s->cadet = in;
1077   if (s->transferred_element_count == s->total)
1078     start_intersection (s);
1079   return GNUNET_OK;
1080 }
1081
1082
1083 /**
1084  * Function called for inbound channels on Bob's end.  Does some
1085  * preliminary initialization, more happens after we get Alice's first
1086  * message.
1087  *
1088  * @param cls closure
1089  * @param channel new handle to the channel
1090  * @param initiator peer that started the channel
1091  * @param port unused
1092  * @param options unused
1093  * @return session associated with the channel
1094  */
1095 static void *
1096 cb_channel_incoming (void *cls,
1097                      struct GNUNET_CADET_Channel *channel,
1098                      const struct GNUNET_PeerIdentity *initiator,
1099                      uint32_t port,
1100                      enum GNUNET_CADET_ChannelOption options)
1101 {
1102   struct CadetIncomingSession *in;
1103
1104   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105               "New incoming channel from peer %s.\n",
1106               GNUNET_i2s (initiator));
1107   in = GNUNET_new (struct CadetIncomingSession);
1108   in->peer = *initiator;
1109   in->channel = channel;
1110   return in;
1111 }
1112
1113
1114 /**
1115  * We're receiving additional set data. Add it to our
1116  * set and if we are done, initiate the transaction.
1117  *
1118  * @param cls closure
1119  * @param client identification of the client
1120  * @param message the actual message
1121  */
1122 static void
1123 GSS_handle_bob_client_message_multipart (void *cls,
1124                                          struct GNUNET_SERVER_Client *client,
1125                                          const struct GNUNET_MessageHeader *message)
1126 {
1127   const struct ComputationMultipartMessage * msg;
1128   struct BobServiceSession *s;
1129   uint32_t contained_count;
1130   const struct GNUNET_SCALARPRODUCT_Element *elements;
1131   uint32_t i;
1132   uint16_t msize;
1133   struct GNUNET_SET_Element set_elem;
1134   struct GNUNET_SCALARPRODUCT_Element *elem;
1135
1136   s = GNUNET_SERVER_client_get_user_context (client,
1137                                              struct BobServiceSession);
1138   if (NULL == s)
1139   {
1140     /* session needs to already exist */
1141     GNUNET_break (0);
1142     GNUNET_SERVER_receive_done (client,
1143                                 GNUNET_SYSERR);
1144     return;
1145   }
1146   msize = ntohs (message->size);
1147   if (msize < sizeof (struct ComputationMultipartMessage))
1148   {
1149     GNUNET_break (0);
1150     GNUNET_SERVER_receive_done (client,
1151                                 GNUNET_SYSERR);
1152     return;
1153   }
1154   msg = (const struct ComputationMultipartMessage *) message;
1155   contained_count = ntohl (msg->element_count_contained);
1156
1157   if ( (msize != (sizeof (struct ComputationMultipartMessage) +
1158                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
1159        (0 == contained_count) ||
1160        (UINT16_MAX < contained_count) ||
1161        (s->total == s->transferred_element_count) ||
1162        (s->total < s->transferred_element_count + contained_count) )
1163   {
1164     GNUNET_break_op (0);
1165     GNUNET_SERVER_receive_done (client,
1166                                 GNUNET_SYSERR);
1167     return;
1168   }
1169   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1170   for (i = 0; i < contained_count; i++)
1171   {
1172     if (0 == GNUNET_ntohll (elements[i].value))
1173       continue;
1174     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1175     memcpy (elem,
1176             &elements[i],
1177             sizeof (struct GNUNET_SCALARPRODUCT_Element));
1178     if (GNUNET_SYSERR ==
1179         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1180                                            &elem->key,
1181                                            elem,
1182                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1183     {
1184       GNUNET_break (0);
1185       GNUNET_free (elem);
1186       continue;
1187     }
1188     set_elem.data = &elem->key;
1189     set_elem.size = sizeof (elem->key);
1190     set_elem.element_type = 0;
1191     GNUNET_SET_add_element (s->intersection_set,
1192                             &set_elem,
1193                             NULL, NULL);
1194   }
1195   s->transferred_element_count += contained_count;
1196   GNUNET_SERVER_receive_done (client,
1197                               GNUNET_OK);
1198   if (s->total != s->transferred_element_count)
1199   {
1200     /* more to come */
1201     return;
1202   }
1203   if (NULL == s->cadet)
1204   {
1205     /* no Alice waiting for this request, wait for Alice */
1206     return;
1207   }
1208   start_intersection (s);
1209 }
1210
1211
1212 /**
1213  * Handler for Bob's a client request message.  Bob is in the response
1214  * role, keep the values + session and waiting for a matching session
1215  * or process a waiting request from Alice.
1216  *
1217  * @param cls closure
1218  * @param client identification of the client
1219  * @param message the actual message
1220  */
1221 static void
1222 GSS_handle_bob_client_message (void *cls,
1223                                struct GNUNET_SERVER_Client *client,
1224                                const struct GNUNET_MessageHeader *message)
1225 {
1226   const struct BobComputationMessage *msg;
1227   struct BobServiceSession *s;
1228   struct CadetIncomingSession *in;
1229   uint32_t contained_count;
1230   uint32_t total_count;
1231   const struct GNUNET_SCALARPRODUCT_Element *elements;
1232   uint32_t i;
1233   struct GNUNET_SET_Element set_elem;
1234   struct GNUNET_SCALARPRODUCT_Element *elem;
1235   uint16_t msize;
1236
1237   s = GNUNET_SERVER_client_get_user_context (client,
1238                                              struct BobServiceSession);
1239   if (NULL != s)
1240   {
1241     /* only one concurrent session per client connection allowed,
1242        simplifies logic a lot... */
1243     GNUNET_break (0);
1244     GNUNET_SERVER_receive_done (client,
1245                                 GNUNET_SYSERR);
1246     return;
1247   }
1248   msize = ntohs (message->size);
1249   if (msize < sizeof (struct BobComputationMessage))
1250   {
1251     GNUNET_break (0);
1252     GNUNET_SERVER_receive_done (client,
1253                                 GNUNET_SYSERR);
1254     return;
1255   }
1256   msg = (const struct BobComputationMessage *) message;
1257   total_count = ntohl (msg->element_count_total);
1258   contained_count = ntohl (msg->element_count_contained);
1259   if ( (0 == total_count) ||
1260        (0 == contained_count) ||
1261        (UINT16_MAX < contained_count) ||
1262        (msize != (sizeof (struct BobComputationMessage) +
1263                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) )
1264   {
1265     GNUNET_break_op (0);
1266     GNUNET_SERVER_receive_done (client,
1267                                 GNUNET_SYSERR);
1268     return;
1269   }
1270   if (NULL != find_matching_client_session (&msg->session_key))
1271   {
1272     GNUNET_break (0);
1273     GNUNET_SERVER_receive_done (client,
1274                                 GNUNET_SYSERR);
1275     return;
1276   }
1277
1278   s = GNUNET_new (struct BobServiceSession);
1279   s->active = GNUNET_YES;
1280   s->client = client;
1281   s->client_mq = GNUNET_MQ_queue_for_server_client (client);
1282   s->total = total_count;
1283   s->transferred_element_count = contained_count;
1284   s->session_id = msg->session_key;
1285   GNUNET_break (GNUNET_YES ==
1286                 GNUNET_CONTAINER_multihashmap_put (client_sessions,
1287                                                    &s->session_id,
1288                                                    s,
1289                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1290   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1291   s->intersected_elements = GNUNET_CONTAINER_multihashmap_create (s->total,
1292                                                                   GNUNET_YES);
1293   s->intersection_set = GNUNET_SET_create (cfg,
1294                                            GNUNET_SET_OPERATION_INTERSECTION);
1295   for (i = 0; i < contained_count; i++)
1296   {
1297     if (0 == GNUNET_ntohll (elements[i].value))
1298       continue;
1299     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1300     memcpy (elem,
1301             &elements[i],
1302             sizeof (struct GNUNET_SCALARPRODUCT_Element));
1303     if (GNUNET_SYSERR ==
1304         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1305                                            &elem->key,
1306                                            elem,
1307                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1308     {
1309       GNUNET_break (0);
1310       GNUNET_free (elem);
1311       continue;
1312     }
1313     set_elem.data = &elem->key;
1314     set_elem.size = sizeof (elem->key);
1315     set_elem.element_type = 0;
1316     GNUNET_SET_add_element (s->intersection_set,
1317                             &set_elem,
1318                             NULL, NULL);
1319     s->used_element_count++;
1320   }
1321   GNUNET_SERVER_client_set_user_context (client,
1322                                          s);
1323   GNUNET_SERVER_receive_done (client,
1324                               GNUNET_YES);
1325   if (s->total != s->transferred_element_count)
1326   {
1327     /* multipart msg */
1328     return;
1329   }
1330   in = find_matching_cadet_session (&s->session_id);
1331   if (NULL == in)
1332   {
1333     /* nothing yet, wait for Alice */
1334     return;
1335   }
1336   GNUNET_assert (NULL == in->s);
1337   /* pair them up */
1338   in->s = s;
1339   s->cadet = in;
1340   start_intersection (s);
1341 }
1342
1343
1344 /**
1345  * Task run during shutdown.
1346  *
1347  * @param cls unused
1348  * @param tc unused
1349  */
1350 static void
1351 shutdown_task (void *cls,
1352                const struct GNUNET_SCHEDULER_TaskContext *tc)
1353 {
1354   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1355               "Shutting down, initiating cleanup.\n");
1356   do_shutdown = GNUNET_YES;
1357   // FIXME: is there a need to shutdown active sessions?
1358   if (NULL != my_cadet)
1359   {
1360     GNUNET_CADET_disconnect (my_cadet);
1361     my_cadet = NULL;
1362   }
1363   GNUNET_CONTAINER_multihashmap_destroy (client_sessions);
1364   client_sessions = NULL;
1365   GNUNET_CONTAINER_multihashmap_destroy (cadet_sessions);
1366   cadet_sessions = NULL;
1367 }
1368
1369
1370 /**
1371  * A client disconnected.
1372  *
1373  * Remove the associated session(s), release data structures
1374  * and cancel pending outgoing transmissions to the client.
1375  *
1376  * @param cls closure, NULL
1377  * @param client identification of the client
1378  */
1379 static void
1380 handle_client_disconnect (void *cls,
1381                           struct GNUNET_SERVER_Client *client)
1382 {
1383   struct BobServiceSession *s;
1384
1385   if (NULL == client)
1386     return;
1387   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1388               "Client disconnected from us.\n",
1389               client);
1390   s = GNUNET_SERVER_client_get_user_context (client,
1391                                              struct BobServiceSession);
1392   if (NULL == s)
1393     return;
1394   s->client = NULL;
1395   destroy_service_session (s);
1396 }
1397
1398
1399 /**
1400  * Initialization of the program and message handlers
1401  *
1402  * @param cls closure
1403  * @param server the initialized server
1404  * @param c configuration to use
1405  */
1406 static void
1407 run (void *cls,
1408      struct GNUNET_SERVER_Handle *server,
1409      const struct GNUNET_CONFIGURATION_Handle *c)
1410 {
1411   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1412     { &GSS_handle_bob_client_message, NULL,
1413       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
1414       0},
1415     { &GSS_handle_bob_client_message_multipart, NULL,
1416       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART_BOB,
1417       0},
1418     { NULL, NULL, 0, 0}
1419   };
1420   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1421     { &handle_alices_computation_request,
1422       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION,
1423       sizeof (struct ServiceRequestMessage) },
1424     { &handle_alices_cryptodata_message,
1425       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA,
1426       0},
1427     { NULL, 0, 0}
1428   };
1429   static const uint32_t ports[] = {
1430     GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
1431     0
1432   };
1433
1434   cfg = c;
1435   /*
1436     offset has to be sufficiently small to allow computation of:
1437     m1+m2 mod n == (S + a) + (S + b) mod n,
1438     if we have more complex operations, this factor needs to be lowered */
1439   my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1440   gcry_mpi_set_bit (my_offset,
1441                     GNUNET_CRYPTO_PAILLIER_BITS / 3);
1442
1443   GNUNET_CRYPTO_paillier_create (&my_pubkey,
1444                                  &my_privkey);
1445   GNUNET_SERVER_add_handlers (server,
1446                               server_handlers);
1447   GNUNET_SERVER_disconnect_notify (server,
1448                                    &handle_client_disconnect,
1449                                    NULL);
1450   client_sessions = GNUNET_CONTAINER_multihashmap_create (128,
1451                                                           GNUNET_YES);
1452   cadet_sessions = GNUNET_CONTAINER_multihashmap_create (128,
1453                                                          GNUNET_YES);
1454   my_cadet = GNUNET_CADET_connect (cfg, NULL,
1455                                    &cb_channel_incoming,
1456                                    &cb_channel_destruction,
1457                                    cadet_handlers,
1458                                    ports);
1459   if (NULL == my_cadet)
1460   {
1461     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1462                 _("Connect to CADET failed\n"));
1463     GNUNET_SCHEDULER_shutdown ();
1464     return;
1465   }
1466   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1467                                 &shutdown_task,
1468                                 NULL);
1469 }
1470
1471
1472 /**
1473  * The main function for the scalarproduct service.
1474  *
1475  * @param argc number of arguments from the command line
1476  * @param argv command line arguments
1477  * @return 0 ok, 1 on error
1478  */
1479 int
1480 main (int argc,
1481       char *const *argv)
1482 {
1483   return (GNUNET_OK ==
1484           GNUNET_SERVICE_run (argc, argv,
1485                               "scalarproduct-bob",
1486                               GNUNET_SERVICE_OPTION_NONE,
1487                               &run, NULL)) ? 0 : 1;
1488 }
1489
1490 /* end of gnunet-service-scalarproduct_bob.c */