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