2 This file is part of GNUnet.
3 (C) 2013 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file secretsharing/gnunet-service-secretsharing.c
23 * @brief secret sharing service
24 * @author Florian Dold
27 #include "gnunet_util_lib.h"
28 #include "gnunet_time_lib.h"
29 #include "gnunet_signatures.h"
30 #include "gnunet_consensus_service.h"
31 #include "secretsharing.h"
32 #include "secretsharing_protocol.h"
36 #define EXTRA_CHECKS 1
40 * Info about a peer in a key generation session.
45 * Peer identity of the peer.
47 struct GNUNET_PeerIdentity peer;
50 * The peer's paillier public key.
51 * Freshly generated for each keygen session.
53 gcry_mpi_t paillier_n;
56 * The peer's commitment to his presecret.
58 gcry_mpi_t presecret_commitment;
61 * The peer's preshare that we decrypted
62 * with out private key.
64 gcry_mpi_t decrypted_preshare;
67 * Multiplicative share of the public key.
69 gcry_mpi_t public_key_share;
72 * Did we successfully receive the round1 element
78 * Did we successfully receive the round2 element
86 * Information about a peer in a decrypt session.
88 struct DecryptPeerInfo
91 * Identity of the peer.
93 struct GNUNET_PeerIdentity peer;
96 * Original index in the key generation round.
97 * Necessary for computing the lagrange coefficients.
99 unsigned int original_index;
102 * Set to the partial decryption of
103 * this peer, or NULL if we did not
104 * receive a partial decryption from this
105 * peer or the zero knowledge proof failed.
107 gcry_mpi_t partial_decryption;
112 * Session to establish a threshold-shared secret.
117 * Keygen sessions are held in a linked list.
119 struct KeygenSession *next;
122 * Keygen sessions are held in a linked list.
124 struct KeygenSession *prev;
127 * Current consensus, used for both DKG rounds.
129 struct GNUNET_CONSENSUS_Handle *consensus;
132 * Client that is interested in the result
133 * of this key generation session.
135 struct GNUNET_SERVER_Client *client;
138 * Message queue for 'client'
140 struct GNUNET_MQ_Handle *client_mq;
143 * Randomly generated coefficients of the polynomial for sharing our
144 * pre-secret, where 'preshares[0]' is our pre-secret. Contains 'threshold'
145 * elements, thus represents a polynomial of degree 'threshold-1', which can
146 * be interpolated with 'threshold' data points.
148 * The pre-secret-shares 'i=1,...,num_peers' are given by evaluating this
149 * polyomial at 'i' for share i.
151 gcry_mpi_t *presecret_polynomial;
154 * Minimum number of shares required to restore the secret.
155 * Also the number of coefficients for the polynomial representing
156 * the sharing. Obviously, the polynomial then has degree threshold-1.
158 unsigned int threshold;
161 * Total number of peers.
163 unsigned int num_peers;
166 * Index of the local peer.
168 unsigned int local_peer;
171 * Information about all participating peers.
172 * Array of size 'num_peers'.
174 struct KeygenPeerInfo *info;
177 * List of all peers involved in the secret sharing session.
179 struct GNUNET_PeerIdentity *peers;
182 * Identifier for this session.
184 struct GNUNET_HashCode session_id;
187 * lambda-component of our peer's paillier private key.
189 gcry_mpi_t paillier_lambda;
192 * mu-component of our peer's paillier private key.
194 gcry_mpi_t paillier_mu;
197 * When would we like the key to be established?
199 struct GNUNET_TIME_Absolute deadline;
202 * When does the DKG start? Necessary to compute fractions of the
203 * operation's desired time interval.
205 struct GNUNET_TIME_Absolute start_time;
208 * Index of the local peer in the ordered list
209 * of peers in the session.
211 unsigned int local_peer_idx;
216 * Session to cooperatively decrypt a value.
218 struct DecryptSession
221 * Decrypt sessions are stored in a linked list.
223 struct DecryptSession *next;
226 * Decrypt sessions are stored in a linked list.
228 struct DecryptSession *prev;
231 * Handle to the consensus over partial decryptions.
233 struct GNUNET_CONSENSUS_Handle *consensus;
236 * Client connected to us.
238 struct GNUNET_SERVER_Client *client;
241 * Message queue for 'client'.
243 struct GNUNET_MQ_Handle *client_mq;
246 * When would we like the ciphertext to be
249 struct GNUNET_TIME_Absolute deadline;
252 * Ciphertext we want to decrypt.
254 struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
257 * Share of the local peer.
258 * Containts other important information, such as
259 * the list of other peers.
261 struct GNUNET_SECRETSHARING_Share *share;
264 * State information about other peers.
266 struct DecryptPeerInfo *info;
271 * Decrypt sessions are held in a linked list.
273 static struct DecryptSession *decrypt_sessions_head;
276 * Decrypt sessions are held in a linked list.
278 static struct DecryptSession *decrypt_sessions_tail;
281 * Decrypt sessions are held in a linked list.
283 static struct KeygenSession *keygen_sessions_head;
286 * Decrypt sessions are held in a linked list.
288 static struct KeygenSession *keygen_sessions_tail;
291 * The ElGamal prime field order as libgcrypt mpi.
292 * Initialized in #init_crypto_constants.
294 static gcry_mpi_t elgamal_q;
297 * Modulus of the prime field used for ElGamal.
298 * Initialized in #init_crypto_constants.
300 static gcry_mpi_t elgamal_p;
303 * Generator for prime field of order 'elgamal_q'.
304 * Initialized in #init_crypto_constants.
306 static gcry_mpi_t elgamal_g;
309 * Peer that runs this service.
311 static struct GNUNET_PeerIdentity my_peer;
314 * Peer that runs this service.
316 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_peer_private_key;
319 * Configuration of this service.
321 static const struct GNUNET_CONFIGURATION_Handle *cfg;
324 * Server for this service.
326 static struct GNUNET_SERVER_Handle *srv;
330 * Get the peer info belonging to a peer identity in a keygen session.
332 * @param ks The keygen session.
333 * @param peer The peer identity.
334 * @return The Keygen peer info, or NULL if the peer could not be found.
336 static struct KeygenPeerInfo *
337 get_keygen_peer_info (const struct KeygenSession *ks,
338 const struct GNUNET_PeerIdentity *peer)
341 for (i = 0; i < ks->num_peers; i++)
342 if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
349 * Get the peer info belonging to a peer identity in a decrypt session.
351 * @param ds The decrypt session.
352 * @param peer The peer identity.
353 * @return The decrypt peer info, or NULL if the peer could not be found.
355 static struct DecryptPeerInfo *
356 get_decrypt_peer_info (const struct DecryptSession *ds,
357 const struct GNUNET_PeerIdentity *peer)
360 for (i = 0; i < ds->share->num_peers; i++)
361 if (0 == memcmp (peer, &ds->info[i].peer, sizeof (struct GNUNET_PeerIdentity)))
368 * Interpolate between two points in time.
370 * @param start start time
371 * @param end end time
372 * @param num numerator of the scale factor
373 * @param denum denumerator of the scale factor
375 static struct GNUNET_TIME_Absolute
376 time_between (struct GNUNET_TIME_Absolute start,
377 struct GNUNET_TIME_Absolute end,
380 struct GNUNET_TIME_Absolute result;
383 GNUNET_assert (start.abs_value_us <= end.abs_value_us);
384 diff = end.abs_value_us - start.abs_value_us;
385 result.abs_value_us = start.abs_value_us + ((diff * num) / denum);
392 * Compare two peer identities. Indended to be used with qsort or bsearch.
394 * @param p1 Some peer identity.
395 * @param p2 Some peer identity.
396 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
399 peer_id_cmp (const void *p1, const void *p2)
401 return memcmp (p1, p2, sizeof (struct GNUNET_PeerIdentity));
406 * Get the index of a peer in an array of peers
408 * @param haystack Array of peers.
409 * @param n Size of @a haystack.
410 * @param needle Peer to find
411 * @return Index of @a needle in @a haystack, or -1 if peer
412 * is not in the list.
415 peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n,
416 const struct GNUNET_PeerIdentity *needle)
419 for (i = 0; i < n; i++)
420 if (0 == memcmp (&haystack[i], needle, sizeof (struct GNUNET_PeerIdentity)))
427 * Normalize the given list of peers, by including the local peer
428 * (if it is missing) and sorting the peers by their identity.
430 * @param listed Peers in the unnormalized list.
431 * @param num_listed Peers in the un-normalized list.
432 * @param[out] num_normalized Number of peers in the normalized list.
433 * @param[out] my_peer_idx Index of the local peer in the normalized list.
434 * @return Normalized list, must be free'd by the caller.
436 static struct GNUNET_PeerIdentity *
437 normalize_peers (struct GNUNET_PeerIdentity *listed,
438 unsigned int num_listed,
439 unsigned int *num_normalized,
440 unsigned int *my_peer_idx)
442 unsigned int local_peer_in_list;
443 /* number of peers in the normalized list */
445 struct GNUNET_PeerIdentity *normalized;
447 local_peer_in_list = GNUNET_YES;
449 if (peer_find (listed, num_listed, &my_peer) < 0)
451 local_peer_in_list = GNUNET_NO;
455 normalized = GNUNET_new_array (n, struct GNUNET_PeerIdentity);
457 if (GNUNET_NO == local_peer_in_list)
458 normalized[n - 1] = my_peer;
460 memcpy (normalized, listed, num_listed * sizeof (struct GNUNET_PeerIdentity));
461 qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp);
463 if (NULL != my_peer_idx)
464 *my_peer_idx = peer_find (normalized, n, &my_peer);
465 if (NULL != num_normalized)
473 * Get a the j-th lagrange coefficient for a set of indices.
475 * @param[out] coeff the lagrange coefficient
476 * @param j lagrange coefficient we want to compute
477 * @param indices indices
478 * @param num number of indices in @a indices
481 compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
482 unsigned int *indices,
490 /* temp value for l-j */
493 GNUNET_assert (0 != coeff);
495 GNUNET_assert (0 != (n = gcry_mpi_new (0)));
496 GNUNET_assert (0 != (d = gcry_mpi_new (0)));
497 GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
499 gcry_mpi_set_ui (n, 1);
500 gcry_mpi_set_ui (d, 1);
502 for (i = 0; i < num; i++)
504 unsigned int l = indices[i];
507 gcry_mpi_mul_ui (n, n, l + 1);
509 gcry_mpi_set_ui (tmp, l + 1);
510 gcry_mpi_sub_ui (tmp, tmp, j + 1);
511 gcry_mpi_mul (d, d, tmp);
514 // gcry_mpi_invm does not like negative numbers ...
515 gcry_mpi_mod (d, d, elgamal_q);
517 GNUNET_assert (gcry_mpi_cmp_ui (d, 0) > 0);
519 // now we do the actual division, with everything mod q, as we
520 // are not operating on elements from <g>, but on exponents
521 GNUNET_assert (0 != gcry_mpi_invm (d, d, elgamal_q));
523 gcry_mpi_mulm (coeff, n, d, elgamal_q);
525 gcry_mpi_release (n);
526 gcry_mpi_release (d);
527 gcry_mpi_release (tmp);
532 * Create a key pair for the paillier crypto system.
534 * Uses the simplified key generation of Jonathan Katz, Yehuda Lindell,
535 * "Introduction to Modern Cryptography: Principles and Protocols".
537 * @param n n-component of public key
538 * @param lambda lambda-component of private key
539 * @param mu mu-componenent of private key
542 paillier_create (gcry_mpi_t n, gcry_mpi_t lambda, gcry_mpi_t mu)
549 GNUNET_assert (NULL != (phi = gcry_mpi_new (PAILLIER_BITS)));
550 GNUNET_assert (NULL != (tmp = gcry_mpi_new (PAILLIER_BITS)));
554 // Generate two distinct primes.
555 // The probability that the loop body
556 // is executed more than once is very low.
559 gcry_mpi_release (p);
561 gcry_mpi_release (q);
562 // generate rsa modulus
563 GNUNET_assert (0 == gcry_prime_generate (&p, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
564 GCRY_WEAK_RANDOM, 0));
565 GNUNET_assert (0 == gcry_prime_generate (&q, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
566 GCRY_WEAK_RANDOM, 0));
567 } while (0 == gcry_mpi_cmp (p, q));
568 gcry_mpi_mul (n, p, q);
569 // compute phi(n) = (p-1)(q-1)
570 gcry_mpi_sub_ui (phi, p, 1);
571 gcry_mpi_sub_ui (tmp, q, 1);
572 gcry_mpi_mul (phi, phi, tmp);
573 gcry_mpi_set (lambda, phi);
575 GNUNET_assert (0 != gcry_mpi_invm (mu, phi, n));
577 gcry_mpi_release (p);
578 gcry_mpi_release (q);
579 gcry_mpi_release (phi);
580 gcry_mpi_release (tmp);
585 * Encrypt a value using Paillier's scheme.
587 * @param[out] c resulting ciphertext
588 * @param m plaintext to encrypt
589 * @param n n-component of public key
592 paillier_encrypt (gcry_mpi_t c, gcry_mpi_t m, gcry_mpi_t n)
598 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
599 GNUNET_assert (0 != (r = gcry_mpi_new (0)));
600 GNUNET_assert (0 != (g = gcry_mpi_new (0)));
602 gcry_mpi_add_ui (g, n, 1);
604 gcry_mpi_mul (n_square, n, n);
609 gcry_mpi_randomize (r, PAILLIER_BITS, GCRY_WEAK_RANDOM);
611 while (gcry_mpi_cmp (r, n) >= 0);
613 gcry_mpi_powm (c, g, m, n_square);
614 gcry_mpi_powm (r, r, n, n_square);
615 gcry_mpi_mulm (c, r, c, n_square);
617 gcry_mpi_release (n_square);
618 gcry_mpi_release (r);
619 gcry_mpi_release (g);
624 * Decrypt a ciphertext using Paillier's scheme.
626 * @param[out] m resulting plaintext
627 * @param c ciphertext to decrypt
628 * @param lambda lambda-component of private key
629 * @param mu mu-component of private key
630 * @param n n-component of public key
633 paillier_decrypt (gcry_mpi_t m, gcry_mpi_t c, gcry_mpi_t mu, gcry_mpi_t lambda, gcry_mpi_t n)
637 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
639 gcry_mpi_mul (n_square, n, n);
640 // m = c^lambda mod n^2
641 gcry_mpi_powm (m, c, lambda, n_square);
643 gcry_mpi_sub_ui (m, m, 1);
645 gcry_mpi_div (m, NULL, m, n, 0);
646 gcry_mpi_mulm (m, m, mu, n);
647 gcry_mpi_release (n_square);
652 decrypt_session_destroy (struct DecryptSession *ds)
654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt session\n");
656 GNUNET_CONTAINER_DLL_remove (decrypt_sessions_head, decrypt_sessions_tail, ds);
658 if (NULL != ds->client_mq)
660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt MQ\n");
661 GNUNET_MQ_destroy (ds->client_mq);
662 ds->client_mq = NULL;
665 if (NULL != ds->client)
667 GNUNET_SERVER_client_disconnect (ds->client);
676 keygen_session_destroy (struct KeygenSession *ks)
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen session\n");
680 GNUNET_CONTAINER_DLL_remove (keygen_sessions_head, keygen_sessions_tail, ks);
682 if (NULL != ks->client_mq)
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen MQ\n");
685 GNUNET_MQ_destroy (ks->client_mq);
686 ks->client_mq = NULL;
689 if (NULL != ks->client)
691 GNUNET_SERVER_client_disconnect (ks->client);
700 * Task run during shutdown.
706 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
708 while (NULL != decrypt_sessions_head)
709 decrypt_session_destroy (decrypt_sessions_head);
711 while (NULL != keygen_sessions_head)
712 keygen_session_destroy (keygen_sessions_head);
717 * Generate the random coefficients of our pre-secret polynomial
719 * @param ks the session
722 generate_presecret_polynomial (struct KeygenSession *ks)
727 GNUNET_assert (NULL == ks->presecret_polynomial);
728 ks->presecret_polynomial = GNUNET_new_array (ks->threshold, gcry_mpi_t);
729 for (i = 0; i < ks->threshold; i++)
731 v = ks->presecret_polynomial[i] = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS);
732 GNUNET_assert (NULL != v);
733 // Randomize v such that 0 < v < elgamal_q.
734 // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
737 gcry_mpi_randomize (v, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
738 } while ((gcry_mpi_cmp_ui (v, 0) == 0) || (gcry_mpi_cmp (v, elgamal_q) >= 0));
744 * Consensus element handler for round one.
745 * We should get one ephemeral key for each peer.
747 * @param cls Closure (keygen session).
748 * @param element The element from consensus, or
749 * NULL if consensus failed.
752 keygen_round1_new_element (void *cls,
753 const struct GNUNET_SET_Element *element)
755 const struct GNUNET_SECRETSHARING_KeygenCommitData *d;
756 struct KeygenSession *ks = cls;
757 struct KeygenPeerInfo *info;
761 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n");
765 /* elements have fixed size */
766 if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
768 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
769 "keygen commit data with wrong size (%u) in consensus, "
771 element->size, sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData));
775 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
778 info = get_keygen_peer_info (ks, &d->peer);
782 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
783 GNUNET_i2s (&d->peer));
787 /* Check that the right amount of data has been signed. */
788 if (d->purpose.size !=
789 htonl (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)))
791 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong signature purpose size in consensus\n");
795 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1,
796 &d->purpose, &d->signature, &d->peer.public_key))
798 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n");
801 GNUNET_CRYPTO_mpi_scan_unsigned (&info->paillier_n, &d->pubkey.n, PAILLIER_BITS / 8);
802 GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->pubkey.n, PAILLIER_BITS / 8);
803 info->round1_valid = GNUNET_YES;
808 * Evaluate the polynomial with coefficients @a coeff at @a x.
809 * The i-th element in @a coeff corresponds to the coefficient of x^i.
811 * @param[out] z result of the evaluation
812 * @param coeff array of coefficients
813 * @param num_coeff number of coefficients
814 * @param x where to evaluate the polynomial
815 * @param m what group are we operating in?
818 horner_eval (gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
822 gcry_mpi_set_ui (z, 0);
823 for (i = 0; i < num_coeff; i++)
826 gcry_mpi_mul (z, z, x);
827 gcry_mpi_addm (z, z, coeff[num_coeff - i - 1], m);
833 keygen_round2_conclude (void *cls)
835 struct KeygenSession *ks = cls;
836 struct GNUNET_SECRETSHARING_SecretReadyMessage *m;
837 struct GNUNET_MQ_Envelope *ev;
841 struct GNUNET_SECRETSHARING_Share *share;
847 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
849 GNUNET_assert (0 != (s = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
850 GNUNET_assert (0 != (h = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
852 // multiplicative identity
853 gcry_mpi_set_ui (h, 1);
855 gcry_mpi_set_ui (s, 0);
857 share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
859 share->num_peers = 0;
861 for (i = 0; i < ks->num_peers; i++)
862 if (GNUNET_YES == ks->info[i].round2_valid)
865 share->peers = GNUNET_new_array (share->num_peers, struct GNUNET_PeerIdentity);
866 share->hom_share_commitments =
867 GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement);
868 share->original_indices = GNUNET_new_array (share->num_peers, uint16_t);
870 /* maybe we're not even in the list of peers? */
871 share->my_peer = share->num_peers;
874 for (i = 0; i < ks->num_peers; i++)
876 if (GNUNET_YES == ks->info[i].round2_valid)
878 gcry_mpi_addm (s, s, ks->info[i].decrypted_preshare, elgamal_p);
879 gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p);
880 share->peers[i] = ks->info[i].peer;
881 share->original_indices[i] = j++;
882 if (0 == memcmp (&share->peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
887 GNUNET_CRYPTO_mpi_print_unsigned (&share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, s);
888 GNUNET_CRYPTO_mpi_print_unsigned (&share->public_key, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, h);
890 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers);
892 /* Write the share. If 0 peers completed the dkg, an empty
893 * share will be sent. */
895 m = GNUNET_malloc (sizeof (struct GNUNET_SECRETSHARING_SecretReadyMessage) +
896 ks->num_peers * sizeof (struct GNUNET_PeerIdentity));
898 GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size));
900 ev = GNUNET_MQ_msg_extra (m, share_size,
901 GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY);
903 GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &m[1], share_size, NULL));
905 GNUNET_MQ_send (ks->client_mq, ev);
910 * Insert round 2 element in the consensus, consisting of
911 * (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}}
912 * (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}}
913 * (3) The encrypted pre-shares Y_{i,j}
914 * (4) The zero knowledge proof for correctness of
917 * @param ks session to use
920 insert_round2_element (struct KeygenSession *ks)
922 struct GNUNET_SET_Element *element;
923 struct GNUNET_SECRETSHARING_KeygenRevealData *d;
925 unsigned char *last_pos;
932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting round2 element\n",
935 GNUNET_assert (NULL != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
936 GNUNET_assert (NULL != (idx = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
937 GNUNET_assert (NULL != (c = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
939 element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
940 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers +
941 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold +
942 PAILLIER_BITS * 2 / 8 * ks->num_peers);
944 element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
945 element->size = element_size;
946 element->data = (void *) &element[1];
948 d = (void *) element->data;
951 // start inserting vector elements
952 // after the fixed part of the element's data
953 pos = (void *) &d[1];
954 last_pos = pos + element_size;
956 // exponentiated pre-shares
957 for (i = 0; i < ks->num_peers; i++)
959 ptrdiff_t remaining = last_pos - pos;
960 GNUNET_assert (remaining > 0);
961 gcry_mpi_set_ui (idx, i + 1);
962 // evaluate the polynomial
963 horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q);
964 // take g to the result
965 gcry_mpi_powm (v, elgamal_g, v, elgamal_p);
966 GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
967 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8;
970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp preshares\n",
973 // encrypted pre-shares
974 for (i = 0; i < ks->num_peers; i++)
976 ptrdiff_t remaining = last_pos - pos;
977 GNUNET_assert (remaining > 0);
978 if (GNUNET_NO == ks->info[i].round1_valid)
980 gcry_mpi_set_ui (c, 0);
984 gcry_mpi_set_ui (idx, i + 1);
985 // evaluate the polynomial
986 horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q);
987 // encrypt the result
988 paillier_encrypt (c, v, ks->info[i].paillier_n);
990 GNUNET_CRYPTO_mpi_print_unsigned (pos, PAILLIER_BITS * 2 / 8, c);
991 pos += PAILLIER_BITS * 2 / 8;
994 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed enc preshares\n",
997 // exponentiated coefficients
998 for (i = 0; i < ks->threshold; i++)
1000 ptrdiff_t remaining = last_pos - pos;
1001 GNUNET_assert (remaining > 0);
1002 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
1003 GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
1004 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8;
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp coefficients\n",
1008 ks->local_peer_idx);
1010 d->purpose.size = htonl (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
1011 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2);
1012 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature);
1014 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1015 GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
1017 gcry_mpi_release (v);
1018 gcry_mpi_release (idx);
1023 keygen_round2_new_element (void *cls,
1024 const struct GNUNET_SET_Element *element)
1026 struct KeygenSession *ks = cls;
1027 const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
1028 struct KeygenPeerInfo *info;
1031 size_t expected_element_size;
1033 if (NULL == element)
1035 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n");
1039 expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
1040 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers +
1041 PAILLIER_BITS / 8 * 2 * ks->num_peers +
1042 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold);
1044 if (element->size != expected_element_size)
1046 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1047 "keygen round2 data with wrong size (%u) in consensus, "
1049 element->size, expected_element_size);
1053 d = (const void *) element->data;
1055 info = get_keygen_peer_info (ks, &d->peer);
1059 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n",
1060 GNUNET_i2s (&d->peer));
1064 if (GNUNET_NO == info->round1_valid)
1066 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1067 "ignoring round2 element from peer with invalid round1 element (%s)\n",
1068 GNUNET_i2s (&d->peer));
1072 if (GNUNET_YES == info->round2_valid)
1074 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1075 "ignoring duplicate round2 element (%s)\n",
1076 GNUNET_i2s (&d->peer));
1080 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
1083 pos = (void *) &d[1];
1084 // skip exponentiated pre-shares
1085 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
1086 // skip encrypted pre-shares
1087 pos += PAILLIER_BITS * 2 / 8 * ks->num_peers;
1088 // the first exponentiated coefficient is the public key share
1089 GNUNET_CRYPTO_mpi_scan_unsigned (&info->public_key_share, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1091 pos = (void *) &d[1];
1092 // skip exp. pre-shares
1093 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
1094 // skip to the encrypted value for our peer
1095 pos += PAILLIER_BITS * 2 / 8 * ks->local_peer_idx;
1097 GNUNET_CRYPTO_mpi_scan_unsigned (&c, pos, PAILLIER_BITS * 2 / 8);
1099 GNUNET_assert (0 != (info->decrypted_preshare = mpi_new (0)));
1101 paillier_decrypt (info->decrypted_preshare, c, ks->paillier_mu, ks->paillier_lambda,
1102 ks->info[ks->local_peer_idx].paillier_n);
1103 // TODO: validate zero knowledge proofs
1105 if (ntohl (d->purpose.size) !=
1106 element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose))
1108 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n");
1112 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2,
1113 &d->purpose, &d->signature, &d->peer.public_key))
1115 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n");
1119 info->round2_valid = GNUNET_YES;
1124 * Called when the first consensus round has concluded.
1125 * Will initiate the second round.
1127 * @param cls closure
1130 keygen_round1_conclude (void *cls)
1132 struct KeygenSession *ks = cls;
1134 GNUNET_CONSENSUS_destroy (ks->consensus);
1136 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id,
1137 keygen_round2_new_element, ks);
1139 insert_round2_element (ks);
1141 GNUNET_CONSENSUS_conclude (ks->consensus,
1142 /* last round, thus conclude at DKG deadline */
1144 keygen_round2_conclude,
1150 * Insert the ephemeral key and the presecret commitment
1151 * of this peer in the consensus of the given session.
1153 * @param ks session to use
1156 insert_round1_element (struct KeygenSession *ks)
1158 struct GNUNET_SET_Element *element;
1159 struct GNUNET_SECRETSHARING_KeygenCommitData *d;
1162 // big-endian representation of 'v'
1163 unsigned char v_data[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
1165 element = GNUNET_malloc (sizeof *element + sizeof *d);
1166 d = (void *) &element[1];
1168 element->size = sizeof *d;
1172 GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1174 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
1176 GNUNET_CRYPTO_mpi_print_unsigned (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
1178 GNUNET_CRYPTO_hash (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, &d->commitment);
1180 GNUNET_CRYPTO_mpi_print_unsigned (d->pubkey.n, PAILLIER_BITS / 8,
1181 ks->info[ks->local_peer_idx].paillier_n);
1183 d->purpose.size = htonl ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
1184 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
1185 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature));
1187 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1189 gcry_mpi_release (v);
1190 GNUNET_free (element);
1195 * Functions with this signature are called whenever a message is
1198 * @param cls closure
1199 * @param client identification of the client
1200 * @param message the actual message
1202 static void handle_client_keygen (void *cls,
1203 struct GNUNET_SERVER_Client *client,
1204 const struct GNUNET_MessageHeader
1207 const struct GNUNET_SECRETSHARING_CreateMessage *msg =
1208 (const struct GNUNET_SECRETSHARING_CreateMessage *) message;
1209 struct KeygenSession *ks;
1212 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n");
1214 ks = GNUNET_new (struct KeygenSession);
1216 /* FIXME: check if client already has some session */
1218 GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks);
1220 ks->client = client;
1221 ks->client_mq = GNUNET_MQ_queue_for_server_client (client);
1223 ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
1224 ks->threshold = ntohs (msg->threshold);
1225 ks->num_peers = ntohs (msg->num_peers);
1227 ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers,
1228 &ks->num_peers, &ks->local_peer_idx);
1231 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "first round of consensus with %u peers\n", ks->num_peers);
1232 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id,
1233 keygen_round1_new_element, ks);
1235 ks->info = GNUNET_new_array (ks->num_peers, struct KeygenPeerInfo);
1237 for (i = 0; i < ks->num_peers; i++)
1238 ks->info[i].peer = ks->peers[i];
1240 GNUNET_assert (0 != (ks->info[ks->local_peer_idx].paillier_n = mpi_new (0)));
1241 GNUNET_assert (0 != (ks->paillier_lambda = mpi_new (0)));
1242 GNUNET_assert (0 != (ks->paillier_mu = mpi_new (0)));
1244 paillier_create (ks->info[ks->local_peer_idx].paillier_n,
1245 ks->paillier_lambda,
1248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated paillier key pair\n", ks->local_peer_idx);
1250 generate_presecret_polynomial (ks);
1252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated presecret polynomial\n", ks->local_peer_idx);
1254 insert_round1_element (ks);
1256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Concluding for round 1\n", ks->local_peer_idx);
1258 GNUNET_CONSENSUS_conclude (ks->consensus,
1259 /* half the overall time */
1260 time_between (ks->start_time, ks->deadline, 1, 2),
1261 keygen_round1_conclude,
1264 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Waiting for round 1 elements ...\n", ks->local_peer_idx);
1271 * Called when the partial decryption consensus concludes.
1274 decrypt_conclude (void *cls)
1276 struct DecryptSession *ds = cls;
1277 struct GNUNET_SECRETSHARING_DecryptResponseMessage *msg;
1278 struct GNUNET_MQ_Envelope *ev;
1279 gcry_mpi_t lagrange;
1284 unsigned int *indices;
1289 GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
1290 GNUNET_assert (0 != (m = gcry_mpi_new (0)));
1291 GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
1292 GNUNET_assert (0 != (prod = gcry_mpi_new (0)));
1295 for (i = 0; i < ds->share->num_peers; i++)
1296 if (NULL != ds->info[i].partial_decryption)
1299 indices = GNUNET_malloc (num * sizeof (unsigned int));
1301 for (i = 0; i < ds->share->num_peers; i++)
1302 if (NULL != ds->info[i].partial_decryption)
1303 indices[j++] = ds->info[i].original_index;
1305 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: decrypt conclude, with %u peers\n",
1306 ds->share->my_peer, num);
1308 gcry_mpi_set_ui (prod, 1);
1309 for (i = 0; i < num; i++)
1312 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: index of %u: %u\n",
1313 ds->share->my_peer, i, indices[i]);
1314 compute_lagrange_coefficient (lagrange, indices[i], indices, num);
1316 gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p);
1318 // product of all exponentiated partiel decryptions ...
1319 gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1322 GNUNET_CRYPTO_mpi_scan_unsigned (&c_2, ds->ciphertext.c2_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1324 GNUNET_assert (0 != gcry_mpi_invm (prod, prod, elgamal_p));
1325 gcry_mpi_mulm (m, c_2, prod, elgamal_p);
1326 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE);
1327 GNUNET_CRYPTO_mpi_print_unsigned (&msg->plaintext, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, m);
1328 msg->success = htonl (1);
1329 GNUNET_MQ_send (ds->client_mq, ev);
1331 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sent decrypt done to client\n");
1333 // FIXME: what if not enough peers participated?
1338 * Called when a new partial decryption arrives.
1341 decrypt_new_element (void *cls,
1342 const struct GNUNET_SET_Element *element)
1344 struct DecryptSession *session = cls;
1345 const struct GNUNET_SECRETSHARING_DecryptData *d;
1346 struct DecryptPeerInfo *info;
1348 if (NULL == element)
1350 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1351 /* FIXME: destroy */
1355 if (element->size != sizeof *d)
1357 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element of wrong size in decrypt consensus\n");
1363 info = get_decrypt_peer_info (session, &d->peer);
1367 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element from invalid peer (%s)\n",
1368 GNUNET_i2s (&d->peer));
1372 if (NULL != info->partial_decryption)
1374 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n",
1375 GNUNET_i2s (&d->peer));
1379 // FIXME: check NIZP first
1381 GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption,
1382 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1386 insert_decrypt_element (struct DecryptSession *ds)
1388 struct GNUNET_SECRETSHARING_DecryptData d;
1389 struct GNUNET_SET_Element element;
1393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n",
1394 ds->share->my_peer);
1396 GNUNET_CRYPTO_mpi_scan_unsigned (&x, &ds->ciphertext.c1_bits,
1397 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1398 GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share,
1399 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1401 gcry_mpi_powm (x, x, s, elgamal_p);
1403 element.data = (void *) &d;
1404 element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
1407 /* make vagrind happy until we implement the real deal ... */
1408 memset (&d.nizk_commit1, 0, sizeof d.nizk_commit1);
1409 memset (&d.nizk_commit2, 0, sizeof d.nizk_commit2);
1410 memset (&d.nizk_response, 0, sizeof d.nizk_response);
1412 d.ciphertext = ds->ciphertext;
1414 d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose));
1415 d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
1417 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature);
1419 GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, x);
1421 GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
1422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element done!\n",
1423 ds->share->my_peer);
1428 * Functions with this signature are called whenever a message is
1431 * @param cls closure
1432 * @param client identification of the client
1433 * @param message the actual message
1435 static void handle_client_decrypt (void *cls,
1436 struct GNUNET_SERVER_Client *client,
1437 const struct GNUNET_MessageHeader
1440 const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg =
1441 (const void *) message;
1442 struct DecryptSession *ds;
1443 struct GNUNET_HashCode session_id;
1446 ds = GNUNET_new (struct DecryptSession);
1447 // FIXME: check if session already exists
1448 GNUNET_CONTAINER_DLL_insert (decrypt_sessions_head, decrypt_sessions_tail, ds);
1449 ds->client = client;
1450 ds->client_mq = GNUNET_MQ_queue_for_server_client (client);
1451 ds->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
1452 ds->ciphertext = msg->ciphertext;
1454 ds->share = GNUNET_SECRETSHARING_share_read (&msg[1], ntohs (msg->header.size) - sizeof *msg, NULL);
1455 // FIXME: probably should be break rather than assert
1456 GNUNET_assert (NULL != ds->share);
1458 // FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ...
1459 GNUNET_CRYPTO_hash (&msg->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext), &session_id);
1461 ds->consensus = GNUNET_CONSENSUS_create (cfg,
1462 ds->share->num_peers,
1465 &decrypt_new_element,
1469 ds->info = GNUNET_new_array (ds->share->num_peers, struct DecryptPeerInfo);
1470 for (i = 0; i < ds->share->num_peers; i++)
1472 ds->info[i].peer = ds->share->peers[i];
1473 ds->info[i].original_index = ds->share->original_indices[i];
1476 insert_decrypt_element (ds);
1478 GNUNET_CONSENSUS_conclude (ds->consensus, ds->deadline, decrypt_conclude, ds);
1480 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1482 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypting with %u peers\n",
1483 ds->share->num_peers);
1488 init_crypto_constants (void)
1490 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
1491 GNUNET_SECRETSHARING_ELGAMAL_Q_HEX, 0, NULL));
1492 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
1493 GNUNET_SECRETSHARING_ELGAMAL_P_HEX, 0, NULL));
1494 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
1495 GNUNET_SECRETSHARING_ELGAMAL_G_HEX, 0, NULL));
1499 static struct KeygenSession *
1500 keygen_session_get (struct GNUNET_SERVER_Client *client)
1502 struct KeygenSession *ks;
1503 for (ks = keygen_sessions_head; NULL != ks; ks = ks->next)
1504 if (ks->client == client)
1509 static struct DecryptSession *
1510 decrypt_session_get (struct GNUNET_SERVER_Client *client)
1512 struct DecryptSession *ds;
1513 for (ds = decrypt_sessions_head; NULL != ds; ds = ds->next)
1514 if (ds->client == client)
1521 * Clean up after a client has disconnected
1523 * @param cls closure, unused
1524 * @param client the client to clean up after
1527 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1529 struct KeygenSession *ks;
1530 struct DecryptSession *ds;
1532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handling client disconnect\n");
1534 ks = keygen_session_get (client);
1536 keygen_session_destroy (ks);
1538 ds = decrypt_session_get (client);
1540 decrypt_session_destroy (ds);
1545 * Process template requests.
1547 * @param cls closure
1548 * @param server the initialized server
1549 * @param c configuration to use
1552 run (void *cls, struct GNUNET_SERVER_Handle *server,
1553 const struct GNUNET_CONFIGURATION_Handle *c)
1555 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1556 {handle_client_keygen, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, 0},
1557 {handle_client_decrypt, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, 0},
1562 my_peer_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
1563 if (NULL == my_peer_private_key)
1565 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not access host private key\n");
1567 GNUNET_SCHEDULER_shutdown ();
1570 init_crypto_constants ();
1571 if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer))
1573 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n");
1575 GNUNET_SCHEDULER_shutdown ();
1578 GNUNET_SERVER_add_handlers (server, handlers);
1579 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1580 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1586 * The main function for the template service.
1588 * @param argc number of arguments from the command line
1589 * @param argv command line arguments
1590 * @return 0 ok, 1 on error
1593 main (int argc, char *const *argv)
1595 return (GNUNET_OK ==
1596 GNUNET_SERVICE_run (argc, argv, "secretsharing",
1597 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;