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