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