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