-simplify further, too much checking...
[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->contained_element_count = htonl (s->cadet_transmitted_element_count);
599
600   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
601               "Sending %u/%u crypto values to Alice\n",
602               (unsigned int) s->cadet_transmitted_element_count,
603               (unsigned int) s->used_element_count);
604
605   payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
606   memcpy (&payload[0],
607           &s->s,
608           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
609   memcpy (&payload[1],
610           &s->s_prime,
611           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
612
613   payload = &payload[2];
614   // convert k[][]
615   for (i = 0; i < s->cadet_transmitted_element_count; i++)
616   {
617     //k[i][p] and k[i][q]
618     memcpy (&payload[i * 2],
619             &s->r[i],
620             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
621     memcpy (&payload[i * 2 + 1],
622             &s->r_prime[i],
623             sizeof (struct GNUNET_CRYPTO_PaillierCiphertext));
624   }
625   if (s->cadet_transmitted_element_count == s->used_element_count)
626     GNUNET_MQ_notify_sent (e,
627                            &bob_cadet_done_cb,
628                            s);
629   GNUNET_MQ_send (s->cadet->cadet_mq,
630                   e);
631   transmit_bobs_cryptodata_message_multipart (s);
632 }
633
634
635 /**
636  * Computes the square sum over a vector of a given length.
637  *
638  * @param vector the vector to compute over
639  * @param length the length of the vector
640  * @return an MPI value containing the calculated sum, never NULL
641  * TODO: code duplication with Alice!
642  */
643 static gcry_mpi_t
644 compute_square_sum (const gcry_mpi_t *vector,
645                     uint32_t length)
646 {
647   gcry_mpi_t elem;
648   gcry_mpi_t sum;
649   uint32_t i;
650
651   GNUNET_assert (NULL != (sum = gcry_mpi_new (0)));
652   GNUNET_assert (NULL != (elem = gcry_mpi_new (0)));
653   for (i = 0; i < length; i++)
654   {
655     gcry_mpi_mul (elem, vector[i], vector[i]);
656     gcry_mpi_add (sum, sum, elem);
657   }
658   gcry_mpi_release (elem);
659   return sum;
660 }
661
662
663 /**
664  * Compute the values
665  *  (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)})$
666  *  (2)[]: $E_A(a_{pi'(i)}) otimes E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$
667  *      S: $S := E_A(sum (r_i + b_i)^2)$
668  *     S': $S' := E_A(sum r_i^2)$
669  *
670  * @param request the requesting session + bob's requesting peer
671  */
672 static void
673 compute_service_response (struct BobServiceSession *session)
674 {
675   uint32_t i;
676   unsigned int *p;
677   unsigned int *q;
678   uint32_t count;
679   gcry_mpi_t *rand;
680   gcry_mpi_t tmp;
681   const struct MpiElement *b;
682   struct GNUNET_CRYPTO_PaillierCiphertext *a;
683   struct GNUNET_CRYPTO_PaillierCiphertext *r;
684   struct GNUNET_CRYPTO_PaillierCiphertext *r_prime;
685
686   count = session->used_element_count;
687   a = session->e_a;
688   b = session->sorted_elements;
689   q = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
690                                     count);
691   p = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
692                                     count);
693   rand = GNUNET_malloc (sizeof (gcry_mpi_t) * count);
694   for (i = 0; i < count; i++)
695     GNUNET_assert (NULL != (rand[i] = gcry_mpi_new (0)));
696   r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
697   r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count);
698
699   for (i = 0; i < count; i++)
700   {
701     int32_t svalue;
702
703     svalue = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
704                                                  UINT32_MAX);
705     // long to gcry_mpi_t
706     if (svalue < 0)
707       gcry_mpi_sub_ui (rand[i],
708                        rand[i],
709                        - svalue);
710     else
711       rand[i] = gcry_mpi_set_ui (rand[i], svalue);
712   }
713
714   tmp = gcry_mpi_new (0);
715   // encrypt the element
716   // for the sake of readability I decided to have dedicated permutation
717   // vectors, which get rid of all the lookups in p/q.
718   // however, ap/aq are not absolutely necessary but are just abstraction
719   // Calculate Kp = E(S + a_pi) (+) E(S - r_pi - b_pi)
720   for (i = 0; i < count; i++)
721   {
722     // E(S - r_pi - b_pi)
723     gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
724     gcry_mpi_sub (tmp, tmp, b[p[i]].value);
725     GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
726                                     tmp,
727                                     2,
728                                     &r[i]);
729
730     // E(S - r_pi - b_pi) * E(S + a_pi) ==  E(2*S + a - r - b)
731     GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
732                                     &r[i],
733                                     &a[p[i]],
734                                     &r[i]);
735   }
736
737   // Calculate Kq = E(S + a_qi) (+) E(S - r_qi)
738   for (i = 0; i < count; i++)
739   {
740     // E(S - r_qi)
741     gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
742     GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
743                                                         tmp,
744                                                         2,
745                                                         &r_prime[i]));
746
747     // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
748     GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (&session->cadet->remote_pubkey,
749                                                         &r_prime[i],
750                                                         &a[q[i]],
751                                                         &r_prime[i]));
752   }
753
754   // Calculate S' =  E(SUM( r_i^2 ))
755   tmp = compute_square_sum (rand, count);
756   GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
757                                   tmp,
758                                   1,
759                                   &session->s_prime);
760
761   // Calculate S = E(SUM( (r_i + b_i)^2 ))
762   for (i = 0; i < count; i++)
763     gcry_mpi_add (rand[i], rand[i], b[i].value);
764   tmp = compute_square_sum (rand, count);
765   GNUNET_CRYPTO_paillier_encrypt (&session->cadet->remote_pubkey,
766                                   tmp,
767                                   1,
768                                   &session->s);
769
770   session->r = r;
771   session->r_prime = r_prime;
772
773   // release rand, b and a
774   for (i = 0; i < count; i++)
775     gcry_mpi_release (rand[i]);
776   gcry_mpi_release (tmp);
777   GNUNET_free (session->e_a);
778   session->e_a = NULL;
779   GNUNET_free (p);
780   GNUNET_free (q);
781   GNUNET_free (rand);
782
783   // copy the r[], r_prime[], S and Stick into a new message, prepare_service_response frees these
784 }
785
786
787 /**
788  * Iterator to copy over messages from the hash map
789  * into an array for sorting.
790  *
791  * @param cls the `struct BobServiceSession *`
792  * @param key the key (unused)
793  * @param value the `struct GNUNET_SCALARPRODUCT_Element *`
794  * TODO: code duplication with Alice!
795  */
796 static int
797 copy_element_cb (void *cls,
798                  const struct GNUNET_HashCode *key,
799                  void *value)
800 {
801   struct BobServiceSession *s = cls;
802   struct GNUNET_SCALARPRODUCT_Element *e = value;
803   gcry_mpi_t mval;
804   int64_t val;
805
806   mval = gcry_mpi_new (0);
807   val = (int64_t) GNUNET_ntohll (e->value);
808   if (0 > val)
809     gcry_mpi_sub_ui (mval, mval, -val);
810   else
811     gcry_mpi_add_ui (mval, mval, val);
812   s->sorted_elements [s->used_element_count].value = mval;
813   s->sorted_elements [s->used_element_count].key = &e->key;
814   s->used_element_count++;
815   return GNUNET_OK;
816 }
817
818
819 /**
820  * Compare two `struct MpiValue`s by key for sorting.
821  *
822  * @param a pointer to first `struct MpiValue *`
823  * @param b pointer to first `struct MpiValue *`
824  * @return -1 for a < b, 0 for a=b, 1 for a > b.
825  * TODO: code duplication with Alice!
826  */
827 static int
828 element_cmp (const void *a,
829              const void *b)
830 {
831   const struct MpiElement *ma = a;
832   const struct MpiElement *mb = b;
833
834   return GNUNET_CRYPTO_hash_cmp (ma->key,
835                                  mb->key);
836 }
837
838
839 /**
840  * Intersection operation and receiving data via CADET from
841  * Alice are both done, compute and transmit our reply via
842  * CADET.
843  *
844  * @param s session to transmit reply for.
845  */
846 static void
847 transmit_cryptographic_reply (struct BobServiceSession *s)
848 {
849   /* TODO: code duplication with Alice! */
850   LOG (GNUNET_ERROR_TYPE_DEBUG,
851        "Received everything, building reply for Alice\n");
852   s->sorted_elements
853     = GNUNET_malloc (GNUNET_CONTAINER_multihashmap_size (s->intersected_elements) *
854                      sizeof (struct MpiElement));
855   s->used_element_count = 0;
856   GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
857                                          &copy_element_cb,
858                                          s);
859   qsort (s->sorted_elements,
860          s->used_element_count,
861          sizeof (struct MpiElement),
862          &element_cmp);
863   compute_service_response (s);
864   transmit_bobs_cryptodata_message (s);
865 }
866
867
868 /**
869  * Handle a multipart-chunk of a request from another service to
870  * calculate a scalarproduct with us.
871  *
872  * @param cls closure (set from #GNUNET_CADET_connect)
873  * @param channel connection to the other end
874  * @param channel_ctx place to store local state associated with the @a channel
875  * @param message the actual message
876  * @return #GNUNET_OK to keep the connection open,
877  *         #GNUNET_SYSERR to close it (signal serious error)
878  */
879 static int
880 handle_alices_cryptodata_message (void *cls,
881                                   struct GNUNET_CADET_Channel *channel,
882                                   void **channel_ctx,
883                                   const struct GNUNET_MessageHeader *message)
884 {
885   struct CadetIncomingSession *in = *channel_ctx;
886   struct BobServiceSession *s;
887   const struct AliceCryptodataMessage *msg;
888   const struct GNUNET_CRYPTO_PaillierCiphertext *payload;
889   uint32_t contained_elements;
890   size_t msg_length;
891   uint16_t msize;
892   unsigned int max;
893
894   if (NULL == in)
895   {
896     GNUNET_break_op (0);
897     return GNUNET_SYSERR;
898   }
899   s = in->s;
900   if (NULL == s)
901   {
902     GNUNET_break_op (0);
903     return GNUNET_SYSERR;
904   }
905   msize = ntohs (message->size);
906   if (msize <= sizeof (struct AliceCryptodataMessage))
907   {
908     GNUNET_break_op (0);
909     return GNUNET_SYSERR;
910   }
911   msg = (const struct AliceCryptodataMessage *) message;
912   contained_elements = ntohl (msg->contained_element_count);
913   /* Our intersection may still be ongoing, but this is nevertheless
914      an upper bound on the required array size */
915   max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
916   msg_length = sizeof (struct AliceCryptodataMessage)
917     + contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext);
918   if ( (msize != msg_length) ||
919        (0 == contained_elements) ||
920        (contained_elements > UINT16_MAX) ||
921        (max < contained_elements + s->cadet_received_element_count) )
922   {
923     GNUNET_break_op (0);
924     return GNUNET_SYSERR;
925   }
926   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
927               "Received %u crypto values from Alice\n",
928               (unsigned int) contained_elements);
929
930   payload = (const struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1];
931   if (NULL == s->e_a)
932     s->e_a = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) *
933                             max);
934   memcpy (&s->e_a[s->cadet_received_element_count],
935           payload,
936           sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements);
937   s->cadet_received_element_count += contained_elements;
938
939   if ( (s->cadet_received_element_count == max) &&
940        (NULL == s->intersection_op) )
941   {
942     /* intersection has finished also on our side, and
943        we got the full set, so we can proceed with the
944        CADET response(s) */
945     transmit_cryptographic_reply (s);
946   }
947   return GNUNET_OK;
948 }
949
950
951 /**
952  * Callback for set operation results. Called for each element
953  * that needs to be removed from the result set.
954  *
955  * @param cls closure with the `struct BobServiceSession`
956  * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
957  * @param status what has happened with the set intersection?
958  */
959 static void
960 cb_intersection_element_removed (void *cls,
961                                  const struct GNUNET_SET_Element *element,
962                                  enum GNUNET_SET_Status status)
963 {
964   struct BobServiceSession *s = cls;
965   struct GNUNET_SCALARPRODUCT_Element *se;
966
967   switch (status)
968   {
969   case GNUNET_SET_STATUS_OK:
970     /* this element has been removed from the set */
971     se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
972                                             element->data);
973     GNUNET_assert (NULL != se);
974     LOG (GNUNET_ERROR_TYPE_DEBUG,
975          "Removed element with key %s and value %lld\n",
976          GNUNET_h2s (&se->key),
977          (long long) GNUNET_ntohll (se->value));
978     GNUNET_assert (GNUNET_YES ==
979                    GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
980                                                          element->data,
981                                                          se));
982     GNUNET_free (se);
983     return;
984   case GNUNET_SET_STATUS_DONE:
985     s->intersection_op = NULL;
986     s->intersection_set = NULL;
987     LOG (GNUNET_ERROR_TYPE_DEBUG,
988          "Finished intersection, %d items remain\n",
989          GNUNET_CONTAINER_multihashmap_size (s->intersected_elements));
990     if (s->client_received_element_count ==
991         GNUNET_CONTAINER_multihashmap_size (s->intersected_elements))
992     {
993       /* CADET transmission from Alice is also already done,
994          start with our own reply */
995       transmit_cryptographic_reply (s);
996     }
997     return;
998   case GNUNET_SET_STATUS_HALF_DONE:
999     /* unexpected for intersection */
1000     GNUNET_break (0);
1001     return;
1002   case GNUNET_SET_STATUS_FAILURE:
1003     /* unhandled status code */
1004     LOG (GNUNET_ERROR_TYPE_DEBUG,
1005          "Set intersection failed!\n");
1006     s->intersection_op = NULL;
1007     s->intersection_set = NULL;
1008     s->active = GNUNET_SYSERR;
1009     prepare_client_end_notification (s);
1010     return;
1011   default:
1012     GNUNET_break (0);
1013     return;
1014   }
1015 }
1016
1017
1018 /**
1019  * We've paired up a client session with an incoming CADET request.
1020  * Initiate set intersection work.
1021  *
1022  * @param s client session to start intersection for
1023  */
1024 static void
1025 start_intersection (struct BobServiceSession *s)
1026 {
1027   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1028               "Got session with key %s and %u elements, starting intersection.\n",
1029               GNUNET_h2s (&s->session_id),
1030               (unsigned int) s->total);
1031
1032   s->intersection_op
1033     = GNUNET_SET_prepare (&s->cadet->peer,
1034                           &s->session_id,
1035                           NULL,
1036                           GNUNET_SET_RESULT_REMOVED,
1037                           &cb_intersection_element_removed,
1038                           s);
1039   GNUNET_SET_commit (s->intersection_op,
1040                      s->intersection_set);
1041 }
1042
1043
1044 /**
1045  * Handle a request from Alice to calculate a scalarproduct with us (Bob).
1046  *
1047  * @param cls closure (set from #GNUNET_CADET_connect)
1048  * @param channel connection to the other end
1049  * @param channel_ctx place to store the `struct CadetIncomingSession *`
1050  * @param message the actual message
1051  * @return #GNUNET_OK to keep the connection open,
1052  *         #GNUNET_SYSERR to close it (signal serious error)
1053  */
1054 static int
1055 handle_alices_computation_request (void *cls,
1056                                    struct GNUNET_CADET_Channel *channel,
1057                                    void **channel_ctx,
1058                                    const struct GNUNET_MessageHeader *message)
1059 {
1060   struct CadetIncomingSession *in = *channel_ctx;
1061   struct BobServiceSession *s;
1062   const struct ServiceRequestMessage *msg;
1063
1064   if (ntohs (message->size) != sizeof (struct ServiceRequestMessage))
1065   {
1066     GNUNET_break_op (0);
1067     return GNUNET_SYSERR;
1068   }
1069   msg = (const struct ServiceRequestMessage *) message;
1070   if (GNUNET_YES == in->in_map)
1071   {
1072     GNUNET_break_op (0);
1073     return GNUNET_SYSERR;
1074   }
1075   if (NULL != find_matching_cadet_session (&msg->session_id))
1076   {
1077     /* not unique, got one like this already */
1078     GNUNET_break_op (0);
1079     return GNUNET_SYSERR;
1080   }
1081   in->session_id = msg->session_id;
1082   in->remote_pubkey = msg->public_key;
1083   GNUNET_assert (GNUNET_YES ==
1084                  GNUNET_CONTAINER_multihashmap_put (cadet_sessions,
1085                                                     &in->session_id,
1086                                                     in,
1087                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1088   s = find_matching_client_session (&in->session_id);
1089   if (NULL == s)
1090   {
1091     /* no client waiting for this request, wait for client */
1092     return GNUNET_OK;
1093   }
1094   GNUNET_assert (NULL == s->cadet);
1095   /* pair them up */
1096   in->s = s;
1097   s->cadet = in;
1098   if (s->client_received_element_count == s->total)
1099     start_intersection (s);
1100   return GNUNET_OK;
1101 }
1102
1103
1104 /**
1105  * Function called for inbound channels on Bob's end.  Does some
1106  * preliminary initialization, more happens after we get Alice's first
1107  * message.
1108  *
1109  * @param cls closure
1110  * @param channel new handle to the channel
1111  * @param initiator peer that started the channel
1112  * @param port unused
1113  * @param options unused
1114  * @return session associated with the channel
1115  */
1116 static void *
1117 cb_channel_incoming (void *cls,
1118                      struct GNUNET_CADET_Channel *channel,
1119                      const struct GNUNET_PeerIdentity *initiator,
1120                      uint32_t port,
1121                      enum GNUNET_CADET_ChannelOption options)
1122 {
1123   struct CadetIncomingSession *in;
1124
1125   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1126               "New incoming channel from peer %s.\n",
1127               GNUNET_i2s (initiator));
1128   in = GNUNET_new (struct CadetIncomingSession);
1129   in->peer = *initiator;
1130   in->channel = channel;
1131   return in;
1132 }
1133
1134
1135 /**
1136  * We're receiving additional set data. Add it to our
1137  * set and if we are done, initiate the transaction.
1138  *
1139  * @param cls closure
1140  * @param client identification of the client
1141  * @param message the actual message
1142  */
1143 static void
1144 GSS_handle_bob_client_message_multipart (void *cls,
1145                                          struct GNUNET_SERVER_Client *client,
1146                                          const struct GNUNET_MessageHeader *message)
1147 {
1148   const struct ComputationBobCryptodataMultipartMessage * msg;
1149   struct BobServiceSession *s;
1150   uint32_t contained_count;
1151   const struct GNUNET_SCALARPRODUCT_Element *elements;
1152   uint32_t i;
1153   uint16_t msize;
1154   struct GNUNET_SET_Element set_elem;
1155   struct GNUNET_SCALARPRODUCT_Element *elem;
1156
1157   s = GNUNET_SERVER_client_get_user_context (client,
1158                                              struct BobServiceSession);
1159   if (NULL == s)
1160   {
1161     /* session needs to already exist */
1162     GNUNET_break (0);
1163     GNUNET_SERVER_receive_done (client,
1164                                 GNUNET_SYSERR);
1165     return;
1166   }
1167   msize = ntohs (message->size);
1168   if (msize < sizeof (struct ComputationBobCryptodataMultipartMessage))
1169   {
1170     GNUNET_break (0);
1171     GNUNET_SERVER_receive_done (client,
1172                                 GNUNET_SYSERR);
1173     return;
1174   }
1175   msg = (const struct ComputationBobCryptodataMultipartMessage *) message;
1176   contained_count = ntohl (msg->element_count_contained);
1177
1178   if ( (msize != (sizeof (struct ComputationBobCryptodataMultipartMessage) +
1179                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) ||
1180        (0 == contained_count) ||
1181        (UINT16_MAX < contained_count) ||
1182        (s->total == s->client_received_element_count) ||
1183        (s->total < s->client_received_element_count + contained_count) )
1184   {
1185     GNUNET_break_op (0);
1186     GNUNET_SERVER_receive_done (client,
1187                                 GNUNET_SYSERR);
1188     return;
1189   }
1190   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1191   for (i = 0; i < contained_count; i++)
1192   {
1193     if (0 == GNUNET_ntohll (elements[i].value))
1194       continue;
1195     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1196     memcpy (elem,
1197             &elements[i],
1198             sizeof (struct GNUNET_SCALARPRODUCT_Element));
1199     if (GNUNET_SYSERR ==
1200         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1201                                            &elem->key,
1202                                            elem,
1203                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1204     {
1205       GNUNET_break (0);
1206       GNUNET_free (elem);
1207       continue;
1208     }
1209     set_elem.data = &elem->key;
1210     set_elem.size = sizeof (elem->key);
1211     set_elem.element_type = 0;
1212     GNUNET_SET_add_element (s->intersection_set,
1213                             &set_elem,
1214                             NULL, NULL);
1215   }
1216   s->client_received_element_count += contained_count;
1217   GNUNET_SERVER_receive_done (client,
1218                               GNUNET_OK);
1219   if (s->total != s->client_received_element_count)
1220   {
1221     /* more to come */
1222     return;
1223   }
1224   if (NULL == s->cadet)
1225   {
1226     /* no Alice waiting for this request, wait for Alice */
1227     return;
1228   }
1229   start_intersection (s);
1230 }
1231
1232
1233 /**
1234  * Handler for Bob's a client request message.  Bob is in the response
1235  * role, keep the values + session and waiting for a matching session
1236  * or process a waiting request from Alice.
1237  *
1238  * @param cls closure
1239  * @param client identification of the client
1240  * @param message the actual message
1241  */
1242 static void
1243 GSS_handle_bob_client_message (void *cls,
1244                                struct GNUNET_SERVER_Client *client,
1245                                const struct GNUNET_MessageHeader *message)
1246 {
1247   const struct BobComputationMessage *msg;
1248   struct BobServiceSession *s;
1249   struct CadetIncomingSession *in;
1250   uint32_t contained_count;
1251   uint32_t total_count;
1252   const struct GNUNET_SCALARPRODUCT_Element *elements;
1253   uint32_t i;
1254   struct GNUNET_SET_Element set_elem;
1255   struct GNUNET_SCALARPRODUCT_Element *elem;
1256   uint16_t msize;
1257
1258   s = GNUNET_SERVER_client_get_user_context (client,
1259                                              struct BobServiceSession);
1260   if (NULL != s)
1261   {
1262     /* only one concurrent session per client connection allowed,
1263        simplifies logic a lot... */
1264     GNUNET_break (0);
1265     GNUNET_SERVER_receive_done (client,
1266                                 GNUNET_SYSERR);
1267     return;
1268   }
1269   msize = ntohs (message->size);
1270   if (msize < sizeof (struct BobComputationMessage))
1271   {
1272     GNUNET_break (0);
1273     GNUNET_SERVER_receive_done (client,
1274                                 GNUNET_SYSERR);
1275     return;
1276   }
1277   msg = (const struct BobComputationMessage *) message;
1278   total_count = ntohl (msg->element_count_total);
1279   contained_count = ntohl (msg->element_count_contained);
1280   if ( (0 == total_count) ||
1281        (0 == contained_count) ||
1282        (UINT16_MAX < contained_count) ||
1283        (msize != (sizeof (struct BobComputationMessage) +
1284                   contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) )
1285   {
1286     GNUNET_break_op (0);
1287     GNUNET_SERVER_receive_done (client,
1288                                 GNUNET_SYSERR);
1289     return;
1290   }
1291   if (NULL != find_matching_client_session (&msg->session_key))
1292   {
1293     GNUNET_break (0);
1294     GNUNET_SERVER_receive_done (client,
1295                                 GNUNET_SYSERR);
1296     return;
1297   }
1298
1299   s = GNUNET_new (struct BobServiceSession);
1300   s->active = GNUNET_YES;
1301   s->client = client;
1302   s->client_mq = GNUNET_MQ_queue_for_server_client (client);
1303   s->total = total_count;
1304   s->client_received_element_count = contained_count;
1305   s->session_id = msg->session_key;
1306   GNUNET_break (GNUNET_YES ==
1307                 GNUNET_CONTAINER_multihashmap_put (client_sessions,
1308                                                    &s->session_id,
1309                                                    s,
1310                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1311   elements = (const struct GNUNET_SCALARPRODUCT_Element *) &msg[1];
1312   s->intersected_elements = GNUNET_CONTAINER_multihashmap_create (s->total,
1313                                                                   GNUNET_YES);
1314   s->intersection_set = GNUNET_SET_create (cfg,
1315                                            GNUNET_SET_OPERATION_INTERSECTION);
1316   for (i = 0; i < contained_count; i++)
1317   {
1318     if (0 == GNUNET_ntohll (elements[i].value))
1319       continue;
1320     elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element);
1321     memcpy (elem,
1322             &elements[i],
1323             sizeof (struct GNUNET_SCALARPRODUCT_Element));
1324     if (GNUNET_SYSERR ==
1325         GNUNET_CONTAINER_multihashmap_put (s->intersected_elements,
1326                                            &elem->key,
1327                                            elem,
1328                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1329     {
1330       GNUNET_break (0);
1331       GNUNET_free (elem);
1332       continue;
1333     }
1334     set_elem.data = &elem->key;
1335     set_elem.size = sizeof (elem->key);
1336     set_elem.element_type = 0;
1337     GNUNET_SET_add_element (s->intersection_set,
1338                             &set_elem,
1339                             NULL, NULL);
1340     s->used_element_count++;
1341   }
1342   GNUNET_SERVER_client_set_user_context (client,
1343                                          s);
1344   GNUNET_SERVER_receive_done (client,
1345                               GNUNET_YES);
1346   if (s->total != s->client_received_element_count)
1347   {
1348     /* multipart msg */
1349     return;
1350   }
1351   in = find_matching_cadet_session (&s->session_id);
1352   if (NULL == in)
1353   {
1354     /* nothing yet, wait for Alice */
1355     return;
1356   }
1357   GNUNET_assert (NULL == in->s);
1358   /* pair them up */
1359   in->s = s;
1360   s->cadet = in;
1361   start_intersection (s);
1362 }
1363
1364
1365 /**
1366  * Task run during shutdown.
1367  *
1368  * @param cls unused
1369  * @param tc unused
1370  */
1371 static void
1372 shutdown_task (void *cls,
1373                const struct GNUNET_SCHEDULER_TaskContext *tc)
1374 {
1375   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1376               "Shutting down, initiating cleanup.\n");
1377   // FIXME: do we have to cut our connections to CADET first?
1378   if (NULL != my_cadet)
1379   {
1380     GNUNET_CADET_disconnect (my_cadet);
1381     my_cadet = NULL;
1382   }
1383   GNUNET_CONTAINER_multihashmap_destroy (client_sessions);
1384   client_sessions = NULL;
1385   GNUNET_CONTAINER_multihashmap_destroy (cadet_sessions);
1386   cadet_sessions = NULL;
1387 }
1388
1389
1390 /**
1391  * A client disconnected.
1392  *
1393  * Remove the associated session(s), release data structures
1394  * and cancel pending outgoing transmissions to the client.
1395  *
1396  * @param cls closure, NULL
1397  * @param client identification of the client
1398  */
1399 static void
1400 handle_client_disconnect (void *cls,
1401                           struct GNUNET_SERVER_Client *client)
1402 {
1403   struct BobServiceSession *s;
1404
1405   if (NULL == client)
1406     return;
1407   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1408               "Client disconnected from us.\n",
1409               client);
1410   s = GNUNET_SERVER_client_get_user_context (client,
1411                                              struct BobServiceSession);
1412   if (NULL == s)
1413     return;
1414   s->client = NULL;
1415   destroy_service_session (s);
1416 }
1417
1418
1419 /**
1420  * Initialization of the program and message handlers
1421  *
1422  * @param cls closure
1423  * @param server the initialized server
1424  * @param c configuration to use
1425  */
1426 static void
1427 run (void *cls,
1428      struct GNUNET_SERVER_Handle *server,
1429      const struct GNUNET_CONFIGURATION_Handle *c)
1430 {
1431   static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
1432     { &GSS_handle_bob_client_message, NULL,
1433       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB,
1434       0},
1435     { &GSS_handle_bob_client_message_multipart, NULL,
1436       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART_BOB,
1437       0},
1438     { NULL, NULL, 0, 0}
1439   };
1440   static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
1441     { &handle_alices_computation_request,
1442       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION,
1443       sizeof (struct ServiceRequestMessage) },
1444     { &handle_alices_cryptodata_message,
1445       GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA,
1446       0},
1447     { NULL, 0, 0}
1448   };
1449   static const uint32_t ports[] = {
1450     GNUNET_APPLICATION_TYPE_SCALARPRODUCT,
1451     0
1452   };
1453
1454   cfg = c;
1455   /*
1456     offset has to be sufficiently small to allow computation of:
1457     m1+m2 mod n == (S + a) + (S + b) mod n,
1458     if we have more complex operations, this factor needs to be lowered */
1459   my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3);
1460   gcry_mpi_set_bit (my_offset,
1461                     GNUNET_CRYPTO_PAILLIER_BITS / 3);
1462
1463   GNUNET_CRYPTO_paillier_create (&my_pubkey,
1464                                  &my_privkey);
1465   GNUNET_SERVER_add_handlers (server,
1466                               server_handlers);
1467   GNUNET_SERVER_disconnect_notify (server,
1468                                    &handle_client_disconnect,
1469                                    NULL);
1470   client_sessions = GNUNET_CONTAINER_multihashmap_create (128,
1471                                                           GNUNET_YES);
1472   cadet_sessions = GNUNET_CONTAINER_multihashmap_create (128,
1473                                                          GNUNET_YES);
1474   my_cadet = GNUNET_CADET_connect (cfg, NULL,
1475                                    &cb_channel_incoming,
1476                                    &cb_channel_destruction,
1477                                    cadet_handlers,
1478                                    ports);
1479   if (NULL == my_cadet)
1480   {
1481     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1482                 _("Connect to CADET failed\n"));
1483     GNUNET_SCHEDULER_shutdown ();
1484     return;
1485   }
1486   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1487                                 &shutdown_task,
1488                                 NULL);
1489 }
1490
1491
1492 /**
1493  * The main function for the scalarproduct service.
1494  *
1495  * @param argc number of arguments from the command line
1496  * @param argv command line arguments
1497  * @return 0 ok, 1 on error
1498  */
1499 int
1500 main (int argc,
1501       char *const *argv)
1502 {
1503   return (GNUNET_OK ==
1504           GNUNET_SERVICE_run (argc, argv,
1505                               "scalarproduct-bob",
1506                               GNUNET_SERVICE_OPTION_NONE,
1507                               &run, NULL)) ? 0 : 1;
1508 }
1509
1510 /* end of gnunet-service-scalarproduct_bob.c */