GNUnet 0.21.1
gnunet-service-secretsharing.c File Reference

secret sharing service More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_time_lib.h"
#include "gnunet_signatures.h"
#include "gnunet_consensus_service.h"
#include "secretsharing.h"
#include "secretsharing_protocol.h"
#include <gcrypt.h>
Include dependency graph for gnunet-service-secretsharing.c:

Go to the source code of this file.

Data Structures

struct  KeygenPeerInfo
 Info about a peer in a key generation session. More...
 
struct  DecryptPeerInfo
 Information about a peer in a decrypt session. More...
 
struct  KeygenSession
 Session to establish a threshold-shared secret. More...
 
struct  DecryptSession
 Session to cooperatively decrypt a value. More...
 
struct  ClientState
 State we keep per client. More...
 

Macros

#define EXTRA_CHECKS   1
 

Functions

static struct KeygenPeerInfoget_keygen_peer_info (const struct KeygenSession *ks, const struct GNUNET_PeerIdentity *peer)
 Get the peer info belonging to a peer identity in a keygen session. More...
 
static struct DecryptPeerInfoget_decrypt_peer_info (const struct DecryptSession *ds, const struct GNUNET_PeerIdentity *peer)
 Get the peer info belonging to a peer identity in a decrypt session. More...
 
static struct GNUNET_TIME_Absolute time_between (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end, int num, int denum)
 Interpolate between two points in time. More...
 
static int peer_id_cmp (const void *p1, const void *p2)
 Compare two peer identities. More...
 
static int peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n, const struct GNUNET_PeerIdentity *needle)
 Get the index of a peer in an array of peers. More...
 
static struct GNUNET_PeerIdentitynormalize_peers (struct GNUNET_PeerIdentity *listed, unsigned int num_listed, unsigned int *num_normalized, unsigned int *my_peer_idx)
 Normalize the given list of peers, by including the local peer (if it is missing) and sorting the peers by their identity. More...
 
static void compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j, unsigned int *indices, unsigned int num)
 Get a the j-th lagrange coefficient for a set of indices. More...
 
static void decrypt_session_destroy (struct DecryptSession *ds)
 Destroy a decrypt session, removing it from the linked list of decrypt sessions. More...
 
static void keygen_info_destroy (struct KeygenPeerInfo *info)
 
static void keygen_session_destroy (struct KeygenSession *ks)
 
static void cleanup_task (void *cls)
 Task run during shutdown. More...
 
static void generate_presecret_polynomial (struct KeygenSession *ks)
 Generate the random coefficients of our pre-secret polynomial. More...
 
static void keygen_round1_new_element (void *cls, const struct GNUNET_SET_Element *element)
 Consensus element handler for round one. More...
 
static void horner_eval (gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
 Evaluate the polynomial with coefficients coeff at x. More...
 
static void keygen_round2_conclude (void *cls)
 
static void restore_fair (const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, const struct GNUNET_SECRETSHARING_FairEncryption *fe, gcry_mpi_t x, gcry_mpi_t xres)
 
static void get_fair_encryption_challenge (const struct GNUNET_SECRETSHARING_FairEncryption *fe, gcry_mpi_t *e)
 
static int verify_fair (const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, const struct GNUNET_SECRETSHARING_FairEncryption *fe)
 
static void encrypt_fair (gcry_mpi_t v, const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, struct GNUNET_SECRETSHARING_FairEncryption *fe)
 Create a fair Paillier encryption of then given ciphertext. More...
 
static void insert_round2_element (struct KeygenSession *ks)
 Insert round 2 element in the consensus, consisting of (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}} (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}} (3) The encrypted pre-shares Y_{i,j} (4) The zero knowledge proof for fairness of the encryption. More...
 
static gcry_mpi_t keygen_reveal_get_exp_coeff (struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
 
static struct GNUNET_SECRETSHARING_FairEncryptionkeygen_reveal_get_enc_preshare (struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
 
static gcry_mpi_t keygen_reveal_get_exp_preshare (struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
 
static void keygen_round2_new_element (void *cls, const struct GNUNET_SET_Element *element)
 
static void keygen_round1_conclude (void *cls)
 Called when the first consensus round has concluded. More...
 
static void insert_round1_element (struct KeygenSession *ks)
 Insert the ephemeral key and the presecret commitment of this peer in the consensus of the given session. More...
 
static int check_client_keygen (void *cls, const struct GNUNET_SECRETSHARING_CreateMessage *msg)
 Check that msg is well-formed. More...
 
static void handle_client_keygen (void *cls, const struct GNUNET_SECRETSHARING_CreateMessage *msg)
 Functions with this signature are called whenever a message is received. More...
 
static void decrypt_conclude (void *cls)
 Called when the partial decryption consensus concludes. More...
 
static char * mpi_to_str (gcry_mpi_t mpi)
 Get a string representation of an MPI. More...
 
static void decrypt_new_element (void *cls, const struct GNUNET_SET_Element *element)
 Called when a new partial decryption arrives. More...
 
static void insert_decrypt_element (struct DecryptSession *ds)
 
static int check_client_decrypt (void *cls, const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg)
 Check that msg is well-formed. More...
 
static void handle_client_decrypt (void *cls, const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg)
 Functions with this signature are called whenever a message is received. More...
 
static void init_crypto_constants (void)
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
 Initialize secretsharing service. More...
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
 Callback called when a client connects to the service. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
 Callback called when a client disconnected from the service. More...
 
 GNUNET_SERVICE_MAIN ("secretsharing", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(client_keygen, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, struct GNUNET_SECRETSHARING_CreateMessage, NULL), GNUNET_MQ_hd_var_size(client_decrypt, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, struct GNUNET_SECRETSHARING_DecryptRequestMessage, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro. More...
 

Variables

static gcry_mpi_t elgamal_q
 The ElGamal prime field order as libgcrypt mpi. More...
 
static gcry_mpi_t elgamal_p
 Modulus of the prime field used for ElGamal. More...
 
static gcry_mpi_t elgamal_g
 Generator for prime field of order 'elgamal_q'. More...
 
static struct GNUNET_PeerIdentity my_peer
 Peer that runs this service. More...
 
static struct GNUNET_CRYPTO_EddsaPrivateKeymy_peer_private_key
 Peer that runs this service. More...
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Configuration of this service. More...
 

Detailed Description

secret sharing service

Author
Florian Dold

Definition in file gnunet-service-secretsharing.c.

Macro Definition Documentation

◆ EXTRA_CHECKS

#define EXTRA_CHECKS   1

Definition at line 36 of file gnunet-service-secretsharing.c.

Function Documentation

◆ get_keygen_peer_info()

static struct KeygenPeerInfo * get_keygen_peer_info ( const struct KeygenSession ks,
const struct GNUNET_PeerIdentity peer 
)
static

Get the peer info belonging to a peer identity in a keygen session.

Parameters
ksThe keygen session.
peerThe peer identity.
Returns
The Keygen peer info, or NULL if the peer could not be found.

Definition at line 325 of file gnunet-service-secretsharing.c.

327{
328 unsigned int i;
329
330 for (i = 0; i < ks->num_peers; i++)
331 if (0 == GNUNET_memcmp (peer, &ks->info[i].peer))
332 return &ks->info[i];
333 return NULL;
334}
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
struct GNUNET_PeerIdentity peer
Peer identity of the peer.
unsigned int num_peers
Total number of peers.
struct KeygenPeerInfo * info
Information about all participating peers.

References GNUNET_memcmp, KeygenSession::info, KeygenSession::num_peers, and KeygenPeerInfo::peer.

Referenced by keygen_round1_new_element(), and keygen_round2_new_element().

Here is the caller graph for this function:

◆ get_decrypt_peer_info()

static struct DecryptPeerInfo * get_decrypt_peer_info ( const struct DecryptSession ds,
const struct GNUNET_PeerIdentity peer 
)
static

Get the peer info belonging to a peer identity in a decrypt session.

Parameters
dsThe decrypt session.
peerThe peer identity.
Returns
The decrypt peer info, or NULL if the peer could not be found.

Definition at line 345 of file gnunet-service-secretsharing.c.

347{
348 unsigned int i;
349
350 for (i = 0; i < ds->share->num_peers; i++)
351 if (0 == GNUNET_memcmp (peer, &ds->info[i].peer))
352 return &ds->info[i];
353 return NULL;
354}
static struct GNUNET_FS_DirScanner * ds
Handle to the directory scanner (for recursive insertions).

References ds, GNUNET_memcmp, and DecryptPeerInfo::peer.

Referenced by decrypt_new_element().

Here is the caller graph for this function:

◆ time_between()

static struct GNUNET_TIME_Absolute time_between ( struct GNUNET_TIME_Absolute  start,
struct GNUNET_TIME_Absolute  end,
int  num,
int  denum 
)
static

Interpolate between two points in time.

Parameters
startstart time
endend time
numnumerator of the scale factor
denumdenumerator of the scale factor

Definition at line 366 of file gnunet-service-secretsharing.c.

369{
371 uint64_t diff;
372
373 GNUNET_assert (start.abs_value_us <= end.abs_value_us);
374 diff = end.abs_value_us - start.abs_value_us;
375 result.abs_value_us = start.abs_value_us + ((diff * num) / denum);
376
377 return result;
378}
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static int result
Global testing status.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Time for absolute times used by GNUnet, in microseconds.

References end, GNUNET_assert, result, and start.

Referenced by keygen_round1_conclude().

Here is the caller graph for this function:

◆ peer_id_cmp()

static int peer_id_cmp ( const void *  p1,
const void *  p2 
)
static

Compare two peer identities.

Intended to be used with qsort or bsearch.

Parameters
p1Some peer identity.
p2Some peer identity.
Returns
1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.

Definition at line 389 of file gnunet-service-secretsharing.c.

390{
391 return memcmp (p1,
392 p2,
393 sizeof(struct GNUNET_PeerIdentity));
394}
The identity of the host (wraps the signing key of the peer).

Referenced by normalize_peers().

Here is the caller graph for this function:

◆ peer_find()

static int peer_find ( const struct GNUNET_PeerIdentity haystack,
unsigned int  n,
const struct GNUNET_PeerIdentity needle 
)
static

Get the index of a peer in an array of peers.

Parameters
haystackArray of peers.
nSize of haystack.
needlePeer to find
Returns
Index of needle in haystack, or -1 if peer is not in the list.

Definition at line 407 of file gnunet-service-secretsharing.c.

409{
410 unsigned int i;
411
412 for (i = 0; i < n; i++)
413 if (0 == GNUNET_memcmp (&haystack[i],
414 needle))
415 return i;
416 return -1;
417}

References GNUNET_memcmp.

Referenced by normalize_peers().

Here is the caller graph for this function:

◆ normalize_peers()

static struct GNUNET_PeerIdentity * normalize_peers ( struct GNUNET_PeerIdentity listed,
unsigned int  num_listed,
unsigned int *  num_normalized,
unsigned int *  my_peer_idx 
)
static

Normalize the given list of peers, by including the local peer (if it is missing) and sorting the peers by their identity.

Parameters
listedPeers in the unnormalized list.
num_listedPeers in the un-normalized list.
[out]num_normalizedNumber of peers in the normalized list.
[out]my_peer_idxIndex of the local peer in the normalized list.
Returns
Normalized list, must be free'd by the caller.

Definition at line 431 of file gnunet-service-secretsharing.c.

435{
436 unsigned int local_peer_in_list;
437 /* number of peers in the normalized list */
438 unsigned int n;
439 struct GNUNET_PeerIdentity *normalized;
440
441 local_peer_in_list = GNUNET_YES;
442 n = num_listed;
443 if (peer_find (listed, num_listed, &my_peer) < 0)
444 {
445 local_peer_in_list = GNUNET_NO;
446 n += 1;
447 }
448
449 normalized = GNUNET_new_array (n,
450 struct GNUNET_PeerIdentity);
451
452 if (GNUNET_NO == local_peer_in_list)
453 normalized[n - 1] = my_peer;
454
455 GNUNET_memcpy (normalized,
456 listed,
457 num_listed * sizeof(struct GNUNET_PeerIdentity));
458 qsort (normalized,
459 n,
460 sizeof(struct GNUNET_PeerIdentity),
461 &peer_id_cmp);
462
463 if (NULL != my_peer_idx)
464 *my_peer_idx = peer_find (normalized, n, &my_peer);
465 if (NULL != num_normalized)
466 *num_normalized = n;
467
468 return normalized;
469}
static int peer_id_cmp(const void *p1, const void *p2)
Compare two peer identities.
static int peer_find(const struct GNUNET_PeerIdentity *haystack, unsigned int n, const struct GNUNET_PeerIdentity *needle)
Get the index of a peer in an array of peers.
static struct GNUNET_PeerIdentity my_peer
Peer that runs this service.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.

References GNUNET_memcpy, GNUNET_new_array, GNUNET_NO, GNUNET_YES, my_peer, peer_find(), and peer_id_cmp().

Referenced by handle_client_keygen().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ compute_lagrange_coefficient()

static void compute_lagrange_coefficient ( gcry_mpi_t  coeff,
unsigned int  j,
unsigned int *  indices,
unsigned int  num 
)
static

Get a the j-th lagrange coefficient for a set of indices.

Parameters
[out]coeffthe lagrange coefficient
jlagrange coefficient we want to compute
indicesindices
numnumber of indices in indices

Definition at line 481 of file gnunet-service-secretsharing.c.

484{
485 unsigned int i;
486 /* numerator */
487 gcry_mpi_t n;
488 /* denominator */
489 gcry_mpi_t d;
490 /* temp value for l-j */
491 gcry_mpi_t tmp;
492
493 GNUNET_assert (0 != coeff);
494
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)));
498
499 gcry_mpi_set_ui (n, 1);
500 gcry_mpi_set_ui (d, 1);
501
502 for (i = 0; i < num; i++)
503 {
504 unsigned int l = indices[i];
505 if (l == j)
506 continue;
507 gcry_mpi_mul_ui (n, n, l + 1);
508 // d <- d * (l-j)
509 gcry_mpi_set_ui (tmp, l + 1);
510 gcry_mpi_sub_ui (tmp, tmp, j + 1);
511 gcry_mpi_mul (d, d, tmp);
512 }
513
514 // gcry_mpi_invm does not like negative numbers ...
515 gcry_mpi_mod (d, d, elgamal_q);
516
517 GNUNET_assert (gcry_mpi_cmp_ui (d, 0) > 0);
518
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));
522
523 gcry_mpi_mulm (coeff, n, d, elgamal_q);
524
525 gcry_mpi_release (n);
526 gcry_mpi_release (d);
527 gcry_mpi_release (tmp);
528}
static mp_limb_t d[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static gcry_mpi_t elgamal_q
The ElGamal prime field order as libgcrypt mpi.

References d, elgamal_q, and GNUNET_assert.

Referenced by decrypt_conclude().

Here is the caller graph for this function:

◆ decrypt_session_destroy()

static void decrypt_session_destroy ( struct DecryptSession ds)
static

Destroy a decrypt session, removing it from the linked list of decrypt sessions.

Parameters
dsdecrypt session to destroy

Definition at line 538 of file gnunet-service-secretsharing.c.

539{
541 "destroying decrypt session\n");
542 if (NULL != ds->cs)
543 {
544 ds->cs->decrypt_session = NULL;
545 ds->cs = NULL;
546 }
547 if (NULL != ds->consensus)
548 {
549 GNUNET_CONSENSUS_destroy (ds->consensus);
550 ds->consensus = NULL;
551 }
552
553 if (NULL != ds->info)
554 {
555 for (unsigned int i = 0; i < ds->share->num_peers; i++)
556 {
557 if (NULL != ds->info[i].partial_decryption)
558 {
559 gcry_mpi_release (ds->info[i].partial_decryption);
560 ds->info[i].partial_decryption = NULL;
561 }
562 }
563 GNUNET_free (ds->info);
564 ds->info = NULL;
565 }
566 if (NULL != ds->share)
567 {
569 ds->share = NULL;
570 }
571
572 GNUNET_free (ds);
573}
void GNUNET_CONSENSUS_destroy(struct GNUNET_CONSENSUS_Handle *consensus)
Destroy a consensus handle (free all state associated with it, no longer call any of the callbacks).
#define GNUNET_log(kind,...)
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_SECRETSHARING_share_destroy(struct GNUNET_SECRETSHARING_Share *share)

References ds, GNUNET_CONSENSUS_destroy(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, and GNUNET_SECRETSHARING_share_destroy().

Referenced by client_disconnect_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ keygen_info_destroy()

static void keygen_info_destroy ( struct KeygenPeerInfo info)
static

Definition at line 577 of file gnunet-service-secretsharing.c.

578{
579 if (NULL != info->sigma)
580 {
581 gcry_mpi_release (info->sigma);
582 info->sigma = NULL;
583 }
584 if (NULL != info->presecret_commitment)
585 {
586 gcry_mpi_release (info->presecret_commitment);
587 info->presecret_commitment = NULL;
588 }
589 if (NULL != info->preshare_commitment)
590 {
591 gcry_mpi_release (info->preshare_commitment);
592 info->preshare_commitment = NULL;
593 }
594}
#define info

References info.

Referenced by keygen_session_destroy().

Here is the caller graph for this function:

◆ keygen_session_destroy()

static void keygen_session_destroy ( struct KeygenSession ks)
static

Definition at line 598 of file gnunet-service-secretsharing.c.

599{
601 "destroying keygen session\n");
602
603 if (NULL != ks->cs)
604 {
605 ks->cs->keygen_session = NULL;
606 ks->cs = NULL;
607 }
608 if (NULL != ks->info)
609 {
610 for (unsigned int i = 0; i < ks->num_peers; i++)
611 keygen_info_destroy (&ks->info[i]);
612 GNUNET_free (ks->info);
613 ks->info = NULL;
614 }
615
616 if (NULL != ks->consensus)
617 {
619 ks->consensus = NULL;
620 }
621
622 if (NULL != ks->presecret_polynomial)
623 {
624 for (unsigned int i = 0; i < ks->threshold; i++)
625 {
626 GNUNET_assert (NULL != ks->presecret_polynomial[i]);
627 gcry_mpi_release (ks->presecret_polynomial[i]);
628 ks->presecret_polynomial[i] = NULL;
629 }
631 ks->presecret_polynomial = NULL;
632 }
633 if (NULL != ks->my_share)
634 {
635 gcry_mpi_release (ks->my_share);
636 ks->my_share = NULL;
637 }
638 if (NULL != ks->public_key)
639 {
640 gcry_mpi_release (ks->public_key);
641 ks->public_key = NULL;
642 }
643 if (NULL != ks->peers)
644 {
645 GNUNET_free (ks->peers);
646 ks->peers = NULL;
647 }
648 GNUNET_free (ks);
649}
static void keygen_info_destroy(struct KeygenPeerInfo *info)
struct KeygenSession * keygen_session
Keygen session of the client, if any.
struct ClientState * cs
Which client is this for?
gcry_mpi_t my_share
Share of our peer.
gcry_mpi_t public_key
Public key, will be updated when a round2 element arrives.
struct GNUNET_CONSENSUS_Handle * consensus
Current consensus, used for both DKG rounds.
gcry_mpi_t * presecret_polynomial
Randomly generated coefficients of the polynomial for sharing our pre-secret, where 'preshares[0]' is...
struct GNUNET_PeerIdentity * peers
List of all peers involved in the secret sharing session.
unsigned int threshold
Minimum number of shares required to restore the secret.

References KeygenSession::consensus, KeygenSession::cs, GNUNET_assert, GNUNET_CONSENSUS_destroy(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, KeygenSession::info, keygen_info_destroy(), ClientState::keygen_session, KeygenSession::my_share, KeygenSession::num_peers, KeygenSession::peers, KeygenSession::presecret_polynomial, KeygenSession::public_key, and KeygenSession::threshold.

Referenced by client_disconnect_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup_task()

static void cleanup_task ( void *  cls)
static

Task run during shutdown.

Parameters
clsunused

Definition at line 658 of file gnunet-service-secretsharing.c.

659{
660 /* Nothing to do! */
661}

Referenced by run().

Here is the caller graph for this function:

◆ generate_presecret_polynomial()

static void generate_presecret_polynomial ( struct KeygenSession ks)
static

Generate the random coefficients of our pre-secret polynomial.

Parameters
ksthe session

Definition at line 670 of file gnunet-service-secretsharing.c.

671{
672 int i;
673 gcry_mpi_t v;
674
677 gcry_mpi_t);
678 for (i = 0; i < ks->threshold; i++)
679 {
680 v = ks->presecret_polynomial[i] = gcry_mpi_new (
682 GNUNET_assert (NULL != v);
683 // Randomize v such that 0 < v < elgamal_q.
684 // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
685 do
686 {
687 gcry_mpi_randomize (v, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1,
688 GCRY_WEAK_RANDOM);
689 }
690 while ((gcry_mpi_cmp_ui (v, 0) == 0) || (gcry_mpi_cmp (v, elgamal_q) >= 0));
691 }
692}
#define GNUNET_SECRETSHARING_ELGAMAL_BITS
Number of bits for secretsharing elements.

References elgamal_q, GNUNET_assert, GNUNET_new_array, GNUNET_SECRETSHARING_ELGAMAL_BITS, KeygenSession::presecret_polynomial, and KeygenSession::threshold.

Referenced by handle_client_keygen().

Here is the caller graph for this function:

◆ keygen_round1_new_element()

static void keygen_round1_new_element ( void *  cls,
const struct GNUNET_SET_Element element 
)
static

Consensus element handler for round one.

We should get one ephemeral key for each peer.

Parameters
clsClosure (keygen session).
elementThe element from consensus, or NULL if consensus failed.

Definition at line 704 of file gnunet-service-secretsharing.c.

706{
708 struct KeygenSession *ks = cls;
709 struct KeygenPeerInfo *info;
710
711 if (NULL == element)
712 {
713 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n");
714 return;
715 }
716
717 /* elements have fixed size */
718 if (element->size != sizeof(struct GNUNET_SECRETSHARING_KeygenCommitData))
719 {
721 "keygen commit data with wrong size (%u) in consensus, %u expected\n",
722 (unsigned int) element->size,
723 (unsigned int) sizeof(struct
725 return;
726 }
727
728 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
729
730 d = element->data;
731 info = get_keygen_peer_info (ks, &d->peer);
732
733 if (NULL == info)
734 {
736 "keygen commit data with wrong peer identity (%s) in consensus\n",
737 GNUNET_i2s (&d->peer));
738 return;
739 }
740
741 /* Check that the right amount of data has been signed. */
742 if (d->purpose.size !=
743 htonl (element->size - offsetof (struct
745 purpose)))
746 {
748 "keygen commit data with wrong signature purpose size in consensus\n");
749 return;
750 }
751
754 &d->purpose, &d->signature,
755 &d->peer.public_key))
756 {
758 "keygen commit data with invalid signature in consensus\n");
759 return;
760 }
761 info->paillier_public_key = d->pubkey;
762 GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->commitment,
763 512 / 8);
764 info->round1_valid = GNUNET_YES;
765}
static struct KeygenPeerInfo * get_keygen_peer_info(const struct KeygenSession *ks, const struct GNUNET_PeerIdentity *peer)
Get the peer info belonging to a peer identity in a keygen session.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:690
void GNUNET_CRYPTO_mpi_scan_unsigned(gcry_mpi_t *result, const void *data, size_t size)
Convert data buffer into MPI value.
Definition: crypto_mpi.c:132
@ GNUNET_OK
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1
Signature for the first round of distributed key generation.
Consensus element data used in the first round of key generation.
uint16_t size
Number of bytes in the buffer pointed to by data.
const void * data
Actual data of the element.
Info about a peer in a key generation session.
Session to establish a threshold-shared secret.

References d, GNUNET_SET_Element::data, get_keygen_peer_info(), GNUNET_CRYPTO_eddsa_verify_(), GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_i2s(), GNUNET_log, GNUNET_OK, GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1, GNUNET_YES, info, and GNUNET_SET_Element::size.

Referenced by handle_client_keygen().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ horner_eval()

static void horner_eval ( gcry_mpi_t  z,
gcry_mpi_t *  coeff,
unsigned int  num_coeff,
gcry_mpi_t  x,
gcry_mpi_t  m 
)
static

Evaluate the polynomial with coefficients coeff at x.

The i-th element in coeff corresponds to the coefficient of x^i.

Parameters
[out]zresult of the evaluation
coeffarray of coefficients
num_coeffnumber of coefficients
xwhere to evaluate the polynomial
mwhat group are we operating in?

Definition at line 779 of file gnunet-service-secretsharing.c.

781{
782 unsigned int i;
783
784 gcry_mpi_set_ui (z, 0);
785 for (i = 0; i < num_coeff; i++)
786 {
787 // z <- zx + c
788 gcry_mpi_mul (z, z, x);
789 gcry_mpi_addm (z, z, coeff[num_coeff - i - 1], m);
790 }
791}
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104

References m.

Referenced by insert_round2_element().

Here is the caller graph for this function:

◆ keygen_round2_conclude()

static void keygen_round2_conclude ( void *  cls)
static

Definition at line 795 of file gnunet-service-secretsharing.c.

796{
797 struct KeygenSession *ks = cls;
799 struct GNUNET_MQ_Envelope *ev;
800 size_t share_size;
801 unsigned int i;
802 unsigned int j;
803 struct GNUNET_SECRETSHARING_Share *share;
804
805 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
806
808 ks->consensus = NULL;
809
810 share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
811
812 share->num_peers = 0;
813
814 for (i = 0; i < ks->num_peers; i++)
815 if (GNUNET_YES == ks->info[i].round2_valid)
816 share->num_peers++;
817
818 share->peers = GNUNET_new_array (share->num_peers,
819 struct GNUNET_PeerIdentity);
820 share->sigmas =
824 uint16_t);
825
826 /* maybe we're not even in the list of peers? */
827 share->my_peer = share->num_peers;
828
829 j = 0; /* running index of valid peers */
830 for (i = 0; i < ks->num_peers; i++)
831 {
832 if (GNUNET_YES == ks->info[i].round2_valid)
833 {
834 share->peers[j] = ks->info[i].peer;
837 ks->info[i].sigma);
838 share->original_indices[i] = j;
839 if (0 == GNUNET_memcmp (&share->peers[i], &my_peer))
840 share->my_peer = j;
841 j += 1;
842 }
843 }
844
845 if (share->my_peer == share->num_peers)
846 {
847 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: peer identity not in share\n",
848 ks->local_peer_idx);
849 }
850
853 ks->my_share);
856 ks->public_key);
857
858 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n",
859 share->num_peers);
860
861 /* Write the share. If 0 peers completed the dkg, an empty
862 * share will be sent. */
863
865 &share_size));
866
867 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "writing share of size %u\n",
868 (unsigned int) share_size);
869
870 ev = GNUNET_MQ_msg_extra (m, share_size,
872
874 share_size,
875 NULL));
876
878 share = NULL;
879
880 GNUNET_MQ_send (ks->cs->mq,
881 ev);
882}
void GNUNET_CRYPTO_mpi_print_unsigned(void *buf, size_t size, gcry_mpi_t val)
Output the given MPI value to the given buffer in network byte order.
Definition: crypto_mpi.c:79
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:304
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY
The cryptosystem has been established.
int GNUNET_SECRETSHARING_share_write(const struct GNUNET_SECRETSHARING_Share *share, void *buf, size_t buflen, size_t *writelen)
Convert a share to its binary representation.
struct GNUNET_MQ_Handle * mq
MQ to talk to client.
Notify the client that then threshold secret has been established.
A share, with all values in in host byte order.
uint16_t num_peers
Peers that have the share.
struct GNUNET_SECRETSHARING_FieldElement my_share
Share of 'my_peer'.
struct GNUNET_SECRETSHARING_PublicKey public_key
Public key.
struct GNUNET_PeerIdentity * peers
Peer identities (includes 'my_peer')
uint16_t my_peer
Index of our peer in the list.
struct GNUNET_SECRETSHARING_FieldElement * sigmas
int round2_valid
Did we successfully receive the round2 element of the peer?
gcry_mpi_t sigma
Sigma (exponentiated share) for this peer.
unsigned int local_peer_idx
Index of the local peer in the ordered list of peers in the session.

References KeygenSession::consensus, KeygenSession::cs, GNUNET_assert, GNUNET_CONSENSUS_destroy(), GNUNET_CRYPTO_mpi_print_unsigned(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_memcmp, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_new, GNUNET_new_array, GNUNET_OK, GNUNET_SECRETSHARING_ELGAMAL_BITS, GNUNET_SECRETSHARING_share_destroy(), GNUNET_SECRETSHARING_share_write(), GNUNET_YES, KeygenSession::info, KeygenSession::local_peer_idx, m, ClientState::mq, my_peer, GNUNET_SECRETSHARING_Share::my_peer, KeygenSession::my_share, GNUNET_SECRETSHARING_Share::my_share, KeygenSession::num_peers, GNUNET_SECRETSHARING_Share::num_peers, GNUNET_SECRETSHARING_Share::original_indices, KeygenPeerInfo::peer, GNUNET_SECRETSHARING_Share::peers, KeygenSession::public_key, GNUNET_SECRETSHARING_Share::public_key, KeygenPeerInfo::round2_valid, KeygenPeerInfo::sigma, and GNUNET_SECRETSHARING_Share::sigmas.

Referenced by keygen_round1_conclude().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ restore_fair()

static void restore_fair ( const struct GNUNET_CRYPTO_PaillierPublicKey ppub,
const struct GNUNET_SECRETSHARING_FairEncryption fe,
gcry_mpi_t  x,
gcry_mpi_t  xres 
)
static

Definition at line 886 of file gnunet-service-secretsharing.c.

889{
890 gcry_mpi_t a_1;
891 gcry_mpi_t a_2;
892 gcry_mpi_t b_1;
893 gcry_mpi_t b_2;
894 gcry_mpi_t big_a;
895 gcry_mpi_t big_b;
896 gcry_mpi_t big_t;
897 gcry_mpi_t n;
898 gcry_mpi_t t_1;
899 gcry_mpi_t t_2;
900 gcry_mpi_t t;
901 gcry_mpi_t r;
902 gcry_mpi_t v;
903
904
905 GNUNET_assert (NULL != (n = gcry_mpi_new (0)));
906 GNUNET_assert (NULL != (t = gcry_mpi_new (0)));
907 GNUNET_assert (NULL != (t_1 = gcry_mpi_new (0)));
908 GNUNET_assert (NULL != (t_2 = gcry_mpi_new (0)));
909 GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
910 GNUNET_assert (NULL != (big_t = gcry_mpi_new (0)));
911 GNUNET_assert (NULL != (v = gcry_mpi_new (0)));
912 GNUNET_assert (NULL != (big_a = gcry_mpi_new (0)));
913 GNUNET_assert (NULL != (big_b = gcry_mpi_new (0)));
914
915 // a = (N,0)^T
917 ppub,
918 sizeof(struct
920 GNUNET_assert (NULL != (a_2 = gcry_mpi_new (0)));
921 gcry_mpi_set_ui (a_2, 0);
922 // b = (x,1)^T
923 GNUNET_assert (NULL != (b_1 = gcry_mpi_new (0)));
924 gcry_mpi_set (b_1, x);
925 GNUNET_assert (NULL != (b_2 = gcry_mpi_new (0)));
926 gcry_mpi_set_ui (b_2, 1);
927
928 // A = a DOT a
929 gcry_mpi_mul (t, a_1, a_1);
930 gcry_mpi_mul (big_a, a_2, a_2);
931 gcry_mpi_add (big_a, big_a, t);
932
933 // B = b DOT b
934 gcry_mpi_mul (t, b_1, b_1);
935 gcry_mpi_mul (big_b, b_2, b_2);
936 gcry_mpi_add (big_b, big_b, t);
937
938 while (1)
939 {
940 // n = a DOT b
941 gcry_mpi_mul (t, a_1, b_1);
942 gcry_mpi_mul (n, a_2, b_2);
943 gcry_mpi_add (n, n, t);
944
945 // r = nearest(n/B)
946 gcry_mpi_div (r, NULL, n, big_b, 0);
947
948 // T := A - 2rn + rrB
949 gcry_mpi_mul (v, r, n);
950 gcry_mpi_mul_ui (v, v, 2);
951 gcry_mpi_sub (big_t, big_a, v);
952 gcry_mpi_mul (v, r, r);
953 gcry_mpi_mul (v, v, big_b);
954 gcry_mpi_add (big_t, big_t, v);
955
956 if (gcry_mpi_cmp (big_t, big_b) >= 0)
957 {
958 break;
959 }
960
961 // t = a - rb
962 gcry_mpi_mul (v, r, b_1);
963 gcry_mpi_sub (t_1, a_1, v);
964 gcry_mpi_mul (v, r, b_2);
965 gcry_mpi_sub (t_2, a_2, v);
966
967 // a = b
968 gcry_mpi_set (a_1, b_1);
969 gcry_mpi_set (a_2, b_2);
970 // b = t
971 gcry_mpi_set (b_1, t_1);
972 gcry_mpi_set (b_2, t_2);
973
974 gcry_mpi_set (big_a, big_b);
975 gcry_mpi_set (big_b, big_t);
976 }
977
978 gcry_mpi_set (xres, b_2);
979 gcry_mpi_invm (xres, xres, elgamal_q);
980 gcry_mpi_mulm (xres, xres, b_1, elgamal_q);
981
982 gcry_mpi_release (a_1);
983 gcry_mpi_release (a_2);
984 gcry_mpi_release (b_1);
985 gcry_mpi_release (b_2);
986 gcry_mpi_release (big_a);
987 gcry_mpi_release (big_b);
988 gcry_mpi_release (big_t);
989 gcry_mpi_release (n);
990 gcry_mpi_release (t_1);
991 gcry_mpi_release (t_2);
992 gcry_mpi_release (t);
993 gcry_mpi_release (r);
994 gcry_mpi_release (v);
995}
static struct GNUNET_SCHEDULER_Task * t
Main task.

References elgamal_q, GNUNET_assert, GNUNET_CRYPTO_mpi_scan_unsigned(), and t.

Referenced by keygen_round2_new_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_fair_encryption_challenge()

static void get_fair_encryption_challenge ( const struct GNUNET_SECRETSHARING_FairEncryption fe,
gcry_mpi_t *  e 
)
static

Definition at line 999 of file gnunet-service-secretsharing.c.

1002{
1003 struct
1004 {
1008 char t2[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8];
1009 } hash_data;
1010 struct GNUNET_HashCode e_hash;
1011
1012 memset (&hash_data,
1013 0,
1014 sizeof(hash_data));
1015 GNUNET_memcpy (&hash_data.c, &fe->c, sizeof(struct
1017 GNUNET_memcpy (&hash_data.h, &fe->h, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1018 GNUNET_memcpy (&hash_data.t1, &fe->t1, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1019 GNUNET_memcpy (&hash_data.t2, &fe->t2, GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8);
1020 GNUNET_CRYPTO_hash (&hash_data,
1021 sizeof(hash_data),
1022 &e_hash);
1023 /* This allocates "e" */
1025 &e_hash,
1026 sizeof(struct GNUNET_HashCode));
1027 gcry_mpi_mod (*e, *e, elgamal_q);
1028}
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
#define GNUNET_CRYPTO_PAILLIER_BITS
Size of paillier plain texts and public keys.
A 512-bit hashcode.
char t1[GNUNET_SECRETSHARING_ELGAMAL_BITS/8]
struct GNUNET_CRYPTO_PaillierCiphertext c
char h[GNUNET_SECRETSHARING_ELGAMAL_BITS/8]
h = g^x, where x is the fairly encrypted secret.
char t2[GNUNET_CRYPTO_PAILLIER_BITS *2/8]

References GNUNET_SECRETSHARING_FairEncryption::c, elgamal_q, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_CRYPTO_PAILLIER_BITS, GNUNET_memcpy, GNUNET_SECRETSHARING_ELGAMAL_BITS, h, GNUNET_SECRETSHARING_FairEncryption::h, GNUNET_SECRETSHARING_FairEncryption::t1, and GNUNET_SECRETSHARING_FairEncryption::t2.

Referenced by encrypt_fair(), and verify_fair().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ verify_fair()

static int verify_fair ( const struct GNUNET_CRYPTO_PaillierPublicKey ppub,
const struct GNUNET_SECRETSHARING_FairEncryption fe 
)
static

Definition at line 1032 of file gnunet-service-secretsharing.c.

1034{
1035 gcry_mpi_t n;
1036 gcry_mpi_t n_sq;
1037 gcry_mpi_t z;
1038 gcry_mpi_t t1;
1039 gcry_mpi_t t2;
1040 gcry_mpi_t e;
1041 gcry_mpi_t w;
1042 gcry_mpi_t tmp1;
1043 gcry_mpi_t tmp2;
1044 gcry_mpi_t y;
1045 gcry_mpi_t big_y;
1046 int res;
1047
1048 GNUNET_assert (NULL != (n_sq = gcry_mpi_new (0)));
1049 GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0)));
1050 GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0)));
1051
1053 &e /* this allocates e */);
1054
1056 ppub,
1057 sizeof(struct
1060 / 8);
1069 * 2 / 8);
1070 gcry_mpi_mul (n_sq, n, n);
1071
1072 // tmp1 = g^z
1073 gcry_mpi_powm (tmp1, elgamal_g, z, elgamal_p);
1074 // tmp2 = y^{-e}
1075 gcry_mpi_powm (tmp1, y, e, elgamal_p);
1076 gcry_mpi_invm (tmp1, tmp1, elgamal_p);
1077 // tmp1 = tmp1 * tmp2
1078 gcry_mpi_mulm (tmp1, tmp1, tmp2, elgamal_p);
1079
1080 if (0 == gcry_mpi_cmp (t1, tmp1))
1081 {
1082 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "fair encryption invalid (t1)\n");
1083 res = GNUNET_NO;
1084 goto cleanup;
1085 }
1086
1087 gcry_mpi_powm (big_y, big_y, e, n_sq);
1088 gcry_mpi_invm (big_y, big_y, n_sq);
1089
1090 gcry_mpi_add_ui (tmp1, n, 1);
1091 gcry_mpi_powm (tmp1, tmp1, z, n_sq);
1092
1093 gcry_mpi_powm (tmp2, w, n, n_sq);
1094
1095 gcry_mpi_mulm (tmp1, tmp1, tmp2, n_sq);
1096 gcry_mpi_mulm (tmp1, tmp1, big_y, n_sq);
1097
1098
1099 if (0 == gcry_mpi_cmp (t2, tmp1))
1100 {
1101 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "fair encryption invalid (t2)\n");
1102 res = GNUNET_NO;
1103 goto cleanup;
1104 }
1105
1106 res = GNUNET_YES;
1107
1108cleanup:
1109
1110 gcry_mpi_release (n);
1111 gcry_mpi_release (n_sq);
1112 gcry_mpi_release (z);
1113 gcry_mpi_release (t1);
1114 gcry_mpi_release (t2);
1115 gcry_mpi_release (e);
1116 gcry_mpi_release (w);
1117 gcry_mpi_release (tmp1);
1118 gcry_mpi_release (tmp2);
1119 gcry_mpi_release (y);
1120 gcry_mpi_release (big_y);
1121 return res;
1122}
static void cleanup(void *cls)
Disconnect and shutdown.
Definition: gnunet-did.c:131
static char * res
Currently read line or NULL on EOF.
static gcry_mpi_t elgamal_g
Generator for prime field of order 'elgamal_q'.
static gcry_mpi_t elgamal_p
Modulus of the prime field used for ElGamal.
static void get_fair_encryption_challenge(const struct GNUNET_SECRETSHARING_FairEncryption *fe, gcry_mpi_t *e)
@ GNUNET_ERROR_TYPE_ERROR
unsigned char bits[2048 *2/8]
The bits of the ciphertext.
char z[GNUNET_SECRETSHARING_ELGAMAL_BITS/8]
char w[GNUNET_CRYPTO_PAILLIER_BITS/8]

References GNUNET_CRYPTO_PaillierCiphertext::bits, GNUNET_SECRETSHARING_FairEncryption::c, cleanup(), elgamal_g, elgamal_p, get_fair_encryption_challenge(), GNUNET_assert, GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_CRYPTO_PAILLIER_BITS, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NO, GNUNET_SECRETSHARING_ELGAMAL_BITS, GNUNET_YES, GNUNET_SECRETSHARING_FairEncryption::h, res, GNUNET_SECRETSHARING_FairEncryption::t1, GNUNET_SECRETSHARING_FairEncryption::t2, GNUNET_SECRETSHARING_FairEncryption::w, and GNUNET_SECRETSHARING_FairEncryption::z.

Referenced by keygen_round2_new_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ encrypt_fair()

static void encrypt_fair ( gcry_mpi_t  v,
const struct GNUNET_CRYPTO_PaillierPublicKey ppub,
struct GNUNET_SECRETSHARING_FairEncryption fe 
)
static

Create a fair Paillier encryption of then given ciphertext.

Parameters
vthe ciphertext
[out]fethe fair encryption

Definition at line 1132 of file gnunet-service-secretsharing.c.

1135{
1136 gcry_mpi_t r;
1137 gcry_mpi_t s;
1138 gcry_mpi_t t1;
1139 gcry_mpi_t t2;
1140 gcry_mpi_t z;
1141 gcry_mpi_t w;
1142 gcry_mpi_t n;
1143 gcry_mpi_t e;
1144 gcry_mpi_t n_sq;
1145 gcry_mpi_t u;
1146 gcry_mpi_t Y;
1147 gcry_mpi_t G;
1148 gcry_mpi_t h;
1149
1150 GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
1151 GNUNET_assert (NULL != (s = gcry_mpi_new (0)));
1152 GNUNET_assert (NULL != (t1 = gcry_mpi_new (0)));
1153 GNUNET_assert (NULL != (t2 = gcry_mpi_new (0)));
1154 GNUNET_assert (NULL != (z = gcry_mpi_new (0)));
1155 GNUNET_assert (NULL != (w = gcry_mpi_new (0)));
1156 GNUNET_assert (NULL != (n_sq = gcry_mpi_new (0)));
1157 GNUNET_assert (NULL != (u = gcry_mpi_new (0)));
1158 GNUNET_assert (NULL != (Y = gcry_mpi_new (0)));
1159 GNUNET_assert (NULL != (G = gcry_mpi_new (0)));
1160 GNUNET_assert (NULL != (h = gcry_mpi_new (0)));
1161
1163 ppub,
1164 sizeof(struct
1166 gcry_mpi_mul (n_sq, n, n);
1167 gcry_mpi_add_ui (G, n, 1);
1168
1169 do
1170 {
1171 gcry_mpi_randomize (u, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM);
1172 }
1173 while (gcry_mpi_cmp (u, n) >= 0);
1174
1175 gcry_mpi_powm (t1, G, v, n_sq);
1176 gcry_mpi_powm (t2, u, n, n_sq);
1177 gcry_mpi_mulm (Y, t1, t2, n_sq);
1178
1180 sizeof fe->c.bits,
1181 Y);
1182
1183
1184 gcry_mpi_randomize (r, 2048, GCRY_WEAK_RANDOM);
1185 do
1186 {
1187 gcry_mpi_randomize (s, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM);
1188 }
1189 while (gcry_mpi_cmp (s, n) >= 0);
1190
1191 // compute t1
1192 gcry_mpi_mulm (t1, elgamal_g, r, elgamal_p);
1193 // compute t2 (use z and w as temp)
1194 gcry_mpi_powm (z, G, r, n_sq);
1195 gcry_mpi_powm (w, s, n, n_sq);
1196 gcry_mpi_mulm (t2, z, w, n_sq);
1197
1198
1199 gcry_mpi_powm (h, elgamal_g, v, elgamal_p);
1200
1203 h);
1204
1207 t1);
1208
1211 t2);
1212
1214 &e /* This allocates "e" */);
1215
1216 // compute z
1217 gcry_mpi_mul (z, e, v);
1218 gcry_mpi_addm (z, z, r, elgamal_q);
1219 // compute w
1220 gcry_mpi_powm (w, u, e, n);
1221 gcry_mpi_mulm (w, w, s, n);
1222
1225 z);
1226
1229 w);
1230
1231 gcry_mpi_release (n);
1232 gcry_mpi_release (r);
1233 gcry_mpi_release (s);
1234 gcry_mpi_release (t1);
1235 gcry_mpi_release (t2);
1236 gcry_mpi_release (z);
1237 gcry_mpi_release (w);
1238 gcry_mpi_release (e);
1239 gcry_mpi_release (n_sq);
1240 gcry_mpi_release (u);
1241 gcry_mpi_release (Y);
1242 gcry_mpi_release (G);
1243 gcry_mpi_release (h);
1244}
static mp_limb_t u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]

References GNUNET_CRYPTO_PaillierCiphertext::bits, GNUNET_SECRETSHARING_FairEncryption::c, elgamal_g, elgamal_p, elgamal_q, get_fair_encryption_challenge(), GNUNET_assert, GNUNET_CRYPTO_mpi_print_unsigned(), GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_CRYPTO_PAILLIER_BITS, GNUNET_SECRETSHARING_ELGAMAL_BITS, h, GNUNET_SECRETSHARING_FairEncryption::h, GNUNET_SECRETSHARING_FairEncryption::t1, GNUNET_SECRETSHARING_FairEncryption::t2, u, GNUNET_SECRETSHARING_FairEncryption::w, and GNUNET_SECRETSHARING_FairEncryption::z.

Referenced by insert_round2_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ insert_round2_element()

static void insert_round2_element ( struct KeygenSession ks)
static

Insert round 2 element in the consensus, consisting of (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}} (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}} (3) The encrypted pre-shares Y_{i,j} (4) The zero knowledge proof for fairness of the encryption.

Parameters
kssession to use

Definition at line 1258 of file gnunet-service-secretsharing.c.

1259{
1260 struct GNUNET_SET_Element *element;
1262 unsigned char *pos;
1263 unsigned char *last_pos;
1264 size_t element_size;
1265 unsigned int i;
1266 gcry_mpi_t idx;
1267 gcry_mpi_t v;
1268
1269 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting round2 element\n",
1270 ks->local_peer_idx);
1271
1272 GNUNET_assert (NULL != (v = gcry_mpi_new (
1274 GNUNET_assert (NULL != (idx = gcry_mpi_new (
1276
1277 element_size = (sizeof(struct GNUNET_SECRETSHARING_KeygenRevealData)
1279 * ks->num_peers
1281
1282 element = GNUNET_malloc (sizeof(struct GNUNET_SET_Element) + element_size);
1283 element->size = element_size;
1284 element->data = (void *) &element[1];
1285
1286 d = (void *) element->data;
1287 d->peer = my_peer;
1288
1289 // start inserting vector elements
1290 // after the fixed part of the element's data
1291 pos = (void *) &d[1];
1292 last_pos = pos + element_size;
1293
1294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp preshares\n",
1295 ks->local_peer_idx);
1296
1297 // encrypted pre-shares
1298 // and fair encryption proof
1299 {
1300 for (i = 0; i < ks->num_peers; i++)
1301 {
1302 ptrdiff_t remaining = last_pos - pos;
1303 struct GNUNET_SECRETSHARING_FairEncryption *fe = (void *) pos;
1304
1305 GNUNET_assert (remaining > 0);
1306 memset (fe, 0, sizeof *fe);
1307 if (GNUNET_YES == ks->info[i].round1_valid)
1308 {
1309 gcry_mpi_set_ui (idx, i + 1);
1310 // evaluate the polynomial
1311 horner_eval (v, ks->presecret_polynomial, ks->threshold, idx,
1312 elgamal_q);
1313 // encrypt the result
1314 encrypt_fair (v, &ks->info[i].paillier_public_key, fe);
1315 }
1316 pos += sizeof *fe;
1317 }
1318 }
1319
1320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed enc preshares\n",
1321 ks->local_peer_idx);
1322
1323 // exponentiated coefficients
1324 for (i = 0; i < ks->threshold; i++)
1325 {
1326 ptrdiff_t remaining = last_pos - pos;
1327 GNUNET_assert (remaining > 0);
1328 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
1330 / 8, v);
1332 }
1333
1334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp coefficients\n",
1335 ks->local_peer_idx);
1336
1337
1338 d->purpose.size = htonl (element_size - offsetof (struct
1340 purpose));
1341 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2);
1344 &d->purpose,
1345 &d->signature));
1346
1347 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1348 GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */
1349
1350 gcry_mpi_release (v);
1351 gcry_mpi_release (idx);
1352}
static void horner_eval(gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m)
Evaluate the polynomial with coefficients coeff at x.
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_peer_private_key
Peer that runs this service.
static void encrypt_fair(gcry_mpi_t v, const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, struct GNUNET_SECRETSHARING_FairEncryption *fe)
Create a fair Paillier encryption of then given ciphertext.
void GNUNET_CONSENSUS_insert(struct GNUNET_CONSENSUS_Handle *consensus, const struct GNUNET_SET_Element *element, GNUNET_CONSENSUS_InsertDoneCallback idc, void *idc_cls)
Insert an element in the set being reconsiled.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:607
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2
Signature for the second round of distributed key generation.
Element stored in a set.
int round1_valid
Did we successfully receive the round1 element of the peer?
struct GNUNET_CRYPTO_PaillierPublicKey paillier_public_key
The peer's paillier public key.

References KeygenSession::consensus, d, GNUNET_SET_Element::data, elgamal_g, elgamal_p, elgamal_q, encrypt_fair(), GNUNET_assert, GNUNET_CONSENSUS_insert(), GNUNET_CRYPTO_eddsa_sign_(), GNUNET_CRYPTO_mpi_print_unsigned(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_OK, GNUNET_SECRETSHARING_ELGAMAL_BITS, GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2, GNUNET_YES, horner_eval(), KeygenSession::info, KeygenSession::local_peer_idx, my_peer, my_peer_private_key, KeygenSession::num_peers, KeygenPeerInfo::paillier_public_key, KeygenSession::presecret_polynomial, KeygenPeerInfo::round1_valid, GNUNET_SET_Element::size, and KeygenSession::threshold.

Referenced by keygen_round1_conclude().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ keygen_reveal_get_exp_coeff()

static gcry_mpi_t keygen_reveal_get_exp_coeff ( struct KeygenSession ks,
const struct GNUNET_SECRETSHARING_KeygenRevealData d,
unsigned int  idx 
)
static

Definition at line 1356 of file gnunet-service-secretsharing.c.

1360{
1361 unsigned char *pos;
1362 gcry_mpi_t exp_coeff;
1363
1364 GNUNET_assert (idx < ks->threshold);
1365
1366 pos = (void *) &d[1];
1367 // skip encrypted pre-shares
1368 pos += sizeof(struct GNUNET_SECRETSHARING_FairEncryption) * ks->num_peers;
1369 // skip exp. coeffs we are not interested in
1370 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * idx;
1371 // the first exponentiated coefficient is the public key share
1372 GNUNET_CRYPTO_mpi_scan_unsigned (&exp_coeff, pos,
1374 return exp_coeff;
1375}

References d, GNUNET_assert, GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_SECRETSHARING_ELGAMAL_BITS, and KeygenSession::num_peers.

Referenced by keygen_round2_new_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ keygen_reveal_get_enc_preshare()

static struct GNUNET_SECRETSHARING_FairEncryption * keygen_reveal_get_enc_preshare ( struct KeygenSession ks,
const struct GNUNET_SECRETSHARING_KeygenRevealData d,
unsigned int  idx 
)
static

Definition at line 1379 of file gnunet-service-secretsharing.c.

1383{
1384 unsigned char *pos;
1385
1386 GNUNET_assert (idx < ks->num_peers);
1387
1388 pos = (void *) &d[1];
1389 // skip encrypted pre-shares we're not interested in
1390 pos += sizeof(struct GNUNET_SECRETSHARING_FairEncryption) * idx;
1391 return (struct GNUNET_SECRETSHARING_FairEncryption *) pos;
1392}
static unsigned int num_peers
Number of peers.

References d, GNUNET_assert, and num_peers.

Referenced by keygen_reveal_get_exp_preshare(), and keygen_round2_new_element().

Here is the caller graph for this function:

◆ keygen_reveal_get_exp_preshare()

static gcry_mpi_t keygen_reveal_get_exp_preshare ( struct KeygenSession ks,
const struct GNUNET_SECRETSHARING_KeygenRevealData d,
unsigned int  idx 
)
static

Definition at line 1396 of file gnunet-service-secretsharing.c.

1400{
1401 gcry_mpi_t exp_preshare;
1403
1404 GNUNET_assert (idx < ks->num_peers);
1405 fe = keygen_reveal_get_enc_preshare (ks, d, idx);
1406 GNUNET_CRYPTO_mpi_scan_unsigned (&exp_preshare, fe->h,
1408 return exp_preshare;
1409}
static struct GNUNET_SECRETSHARING_FairEncryption * keygen_reveal_get_enc_preshare(struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)

References d, GNUNET_assert, GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_SECRETSHARING_ELGAMAL_BITS, GNUNET_SECRETSHARING_FairEncryption::h, keygen_reveal_get_enc_preshare(), and num_peers.

Referenced by keygen_round2_new_element().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ keygen_round2_new_element()

static void keygen_round2_new_element ( void *  cls,
const struct GNUNET_SET_Element element 
)
static

Definition at line 1413 of file gnunet-service-secretsharing.c.

1415{
1416 struct KeygenSession *ks = cls;
1418 struct KeygenPeerInfo *info;
1419 size_t expected_element_size;
1420 unsigned int j;
1421 int cmp_result;
1422 gcry_mpi_t tmp;
1423 gcry_mpi_t public_key_share;
1424 gcry_mpi_t preshare;
1425
1426 if (NULL == element)
1427 {
1428 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n");
1429 return;
1430 }
1431
1432 expected_element_size = (sizeof(struct GNUNET_SECRETSHARING_KeygenRevealData)
1433 + sizeof(struct
1435 * ks->num_peers
1437 * ks->threshold);
1438
1439 if (element->size != expected_element_size)
1440 {
1442 "keygen round2 data with wrong size (%u) in consensus, %u expected\n",
1443 (unsigned int) element->size,
1444 (unsigned int) expected_element_size);
1445 return;
1446 }
1447
1448 d = (const void *) element->data;
1449
1450 info = get_keygen_peer_info (ks, &d->peer);
1451
1452 if (NULL == info)
1453 {
1455 "keygen commit data with wrong peer identity (%s) in consensus\n",
1456 GNUNET_i2s (&d->peer));
1457 return;
1458 }
1459
1460 if (GNUNET_NO == info->round1_valid)
1461 {
1463 "ignoring round2 element from peer with invalid round1 element (%s)\n",
1464 GNUNET_i2s (&d->peer));
1465 return;
1466 }
1467
1468 if (GNUNET_YES == info->round2_valid)
1469 {
1471 "ignoring duplicate round2 element (%s)\n",
1472 GNUNET_i2s (&d->peer));
1473 return;
1474 }
1475
1476 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n");
1477
1478 if (ntohl (d->purpose.size) !=
1479 element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData,
1480 purpose))
1481 {
1483 "keygen reveal data with wrong signature purpose size in consensus\n");
1484 return;
1485 }
1486
1489 &d->purpose, &d->signature,
1490 &d->peer.public_key))
1491 {
1493 "keygen reveal data with invalid signature in consensus\n");
1494 return;
1495 }
1496
1497 public_key_share = keygen_reveal_get_exp_coeff (ks, d, 0);
1498 info->preshare_commitment = keygen_reveal_get_exp_preshare (ks, d,
1499 ks->local_peer_idx);
1500
1501 if (NULL == ks->public_key)
1502 {
1503 GNUNET_assert (NULL != (ks->public_key = gcry_mpi_new (0)));
1504 gcry_mpi_set_ui (ks->public_key, 1);
1505 }
1506 gcry_mpi_mulm (ks->public_key, ks->public_key, public_key_share, elgamal_p);
1507
1508 gcry_mpi_release (public_key_share);
1509 public_key_share = NULL;
1510
1511 {
1514 GNUNET_assert (NULL != (preshare = gcry_mpi_new (0)));
1516 &ks->info[ks->local_peer_idx].
1517 paillier_public_key,
1518 &fe->c,
1519 preshare);
1520
1521 // FIXME: not doing the restoration is less expensive
1523 fe,
1524 preshare,
1525 preshare);
1526 }
1527
1528 GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
1529 gcry_mpi_powm (tmp, elgamal_g, preshare, elgamal_p);
1530
1531 cmp_result = gcry_mpi_cmp (tmp, info->preshare_commitment);
1532 gcry_mpi_release (tmp);
1533 tmp = NULL;
1534 if (0 != cmp_result)
1535 {
1537 "P%u: Got invalid presecret from P%u\n",
1538 (unsigned int) ks->local_peer_idx, (unsigned int) (info
1539 - ks->info));
1540 return;
1541 }
1542
1543 if (NULL == ks->my_share)
1544 {
1545 GNUNET_assert (NULL != (ks->my_share = gcry_mpi_new (0)));
1546 }
1547 gcry_mpi_addm (ks->my_share, ks->my_share, preshare, elgamal_q);
1548
1549 for (j = 0; j < ks->num_peers; j++)
1550 {
1551 gcry_mpi_t presigma;
1552 if (NULL == ks->info[j].sigma)
1553 {
1554 GNUNET_assert (NULL != (ks->info[j].sigma = gcry_mpi_new (0)));
1555 gcry_mpi_set_ui (ks->info[j].sigma, 1);
1556 }
1557 presigma = keygen_reveal_get_exp_preshare (ks, d, j);
1558 gcry_mpi_mulm (ks->info[j].sigma, ks->info[j].sigma, presigma, elgamal_p);
1559 gcry_mpi_release (presigma);
1560 }
1561
1562 gcry_mpi_t prod;
1563 GNUNET_assert (NULL != (prod = gcry_mpi_new (0)));
1564 gcry_mpi_t j_to_k;
1565 GNUNET_assert (NULL != (j_to_k = gcry_mpi_new (0)));
1566 // validate that the polynomial sharing matches the additive sharing
1567 for (j = 0; j < ks->num_peers; j++)
1568 {
1569 unsigned int k;
1570 int cmp_result;
1571 gcry_mpi_t exp_preshare;
1572 gcry_mpi_set_ui (prod, 1);
1573 for (k = 0; k < ks->threshold; k++)
1574 {
1575 // Using pow(double,double) is a bit sketchy.
1576 // We count players from 1, but shares from 0.
1577 gcry_mpi_t tmp;
1578 gcry_mpi_set_ui (j_to_k, (unsigned int) pow (j + 1, k));
1579 tmp = keygen_reveal_get_exp_coeff (ks, d, k);
1580 gcry_mpi_powm (tmp, tmp, j_to_k, elgamal_p);
1581 gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1582 gcry_mpi_release (tmp);
1583 }
1584 exp_preshare = keygen_reveal_get_exp_preshare (ks, d, j);
1585 gcry_mpi_mod (exp_preshare, exp_preshare, elgamal_p);
1586 cmp_result = gcry_mpi_cmp (prod, exp_preshare);
1587 gcry_mpi_release (exp_preshare);
1588 exp_preshare = NULL;
1589 if (0 != cmp_result)
1590 {
1592 "P%u: reveal data from P%u incorrect\n",
1593 ks->local_peer_idx, j);
1594 /* no need for further verification, round2 stays invalid ... */
1595 return;
1596 }
1597 }
1598
1599 // TODO: verify proof of fair encryption (once implemented)
1600 for (j = 0; j < ks->num_peers; j++)
1601 {
1604 if (GNUNET_YES != verify_fair (&ks->info[j].paillier_public_key, fe))
1605 {
1607 "P%u: reveal data from P%u incorrect (fair encryption)\n",
1608 ks->local_peer_idx, j);
1609 return;
1610 }
1611 }
1612
1613 info->round2_valid = GNUNET_YES;
1614
1615 gcry_mpi_release (preshare);
1616 gcry_mpi_release (prod);
1617 gcry_mpi_release (j_to_k);
1618}
static void restore_fair(const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, const struct GNUNET_SECRETSHARING_FairEncryption *fe, gcry_mpi_t x, gcry_mpi_t xres)
static gcry_mpi_t keygen_reveal_get_exp_coeff(struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
static gcry_mpi_t keygen_reveal_get_exp_preshare(struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx)
static int verify_fair(const struct GNUNET_CRYPTO_PaillierPublicKey *ppub, const struct GNUNET_SECRETSHARING_FairEncryption *fe)
void GNUNET_CRYPTO_paillier_decrypt(const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key, const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext, gcry_mpi_t m)
Decrypt a paillier ciphertext with a private key.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
struct GNUNET_CRYPTO_PaillierPrivateKey paillier_private_key
Paillier private key of our peer.

References GNUNET_SECRETSHARING_FairEncryption::c, d, GNUNET_SET_Element::data, elgamal_g, elgamal_p, elgamal_q, get_keygen_peer_info(), GNUNET_assert, GNUNET_CRYPTO_eddsa_verify_(), GNUNET_CRYPTO_paillier_decrypt(), GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SECRETSHARING_ELGAMAL_BITS, GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2, GNUNET_YES, info, KeygenSession::info, keygen_reveal_get_enc_preshare(), keygen_reveal_get_exp_coeff(), keygen_reveal_get_exp_preshare(), KeygenSession::local_peer_idx, KeygenSession::my_share, KeygenSession::num_peers, KeygenSession::paillier_private_key, KeygenPeerInfo::paillier_public_key, KeygenSession::public_key, GNUNET_SECRETSHARING_KeygenRevealData::purpose, restore_fair(), KeygenPeerInfo::sigma, GNUNET_SET_Element::size, KeygenSession::threshold, and verify_fair().

Referenced by keygen_round1_conclude().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ keygen_round1_conclude()

static void keygen_round1_conclude ( void *  cls)
static

Called when the first consensus round has concluded.

Will initiate the second round.

Parameters
clsclosure

Definition at line 1628 of file gnunet-service-secretsharing.c.

1629{
1630 struct KeygenSession *ks = cls;
1631
1633
1635 &ks->session_id,
1637 ks->deadline, 1, 2),
1638 ks->deadline,
1640
1642
1645 ks);
1646}
static void keygen_round2_new_element(void *cls, const struct GNUNET_SET_Element *element)
static void insert_round2_element(struct KeygenSession *ks)
Insert round 2 element in the consensus, consisting of (1) The exponentiated pre-share polynomial coe...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration of this service.
static struct GNUNET_TIME_Absolute time_between(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end, int num, int denum)
Interpolate between two points in time.
static void keygen_round2_conclude(void *cls)
struct GNUNET_CONSENSUS_Handle * GNUNET_CONSENSUS_create(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, const struct GNUNET_PeerIdentity *peers, const struct GNUNET_HashCode *session_id, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, GNUNET_CONSENSUS_ElementCallback new_element_cb, void *new_element_cls)
Create a consensus session.
void GNUNET_CONSENSUS_conclude(struct GNUNET_CONSENSUS_Handle *consensus, GNUNET_CONSENSUS_ConcludeCallback conclude, void *conclude_cls)
We are done with inserting new elements into the consensus; try to conclude the consensus within a gi...
struct GNUNET_TIME_Absolute deadline
When would we like the key to be established?
struct GNUNET_TIME_Absolute start_time
When does the DKG start? Necessary to compute fractions of the operation's desired time interval.
struct GNUNET_HashCode session_id
Identifier for this session.

References cfg, KeygenSession::consensus, KeygenSession::deadline, GNUNET_CONSENSUS_conclude(), GNUNET_CONSENSUS_create(), GNUNET_CONSENSUS_destroy(), insert_round2_element(), keygen_round2_conclude(), keygen_round2_new_element(), KeygenSession::num_peers, KeygenSession::peers, KeygenSession::session_id, KeygenSession::start_time, and time_between().

Referenced by handle_client_keygen().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ insert_round1_element()

static void insert_round1_element ( struct KeygenSession ks)
static

Insert the ephemeral key and the presecret commitment of this peer in the consensus of the given session.

Parameters
kssession to use

Definition at line 1656 of file gnunet-service-secretsharing.c.

1657{
1658 struct GNUNET_SET_Element *element;
1660 // g^a_{i,0}
1661 gcry_mpi_t v;
1662 // big-endian representation of 'v'
1663 unsigned char v_data[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
1664
1665 element = GNUNET_malloc (sizeof *element + sizeof *d);
1666 d = (void *) &element[1];
1667 element->data = d;
1668 element->size = sizeof *d;
1669
1670 d->peer = my_peer;
1671
1672 GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1673
1674 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
1675
1677 / 8, v);
1678
1680 &d->commitment);
1681
1682 d->pubkey = ks->info[ks->local_peer_idx].paillier_public_key;
1683
1684 d->purpose.size = htonl ((sizeof *d) - offsetof (struct
1686 purpose));
1687 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
1690 &d->purpose,
1691 &d->signature));
1692
1693 GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL);
1694
1695 gcry_mpi_release (v);
1696 GNUNET_free (element);
1697}
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Signature purpose for signing the keygen commit data.

References KeygenSession::consensus, d, GNUNET_SET_Element::data, elgamal_g, elgamal_p, GNUNET_assert, GNUNET_CONSENSUS_insert(), GNUNET_CRYPTO_eddsa_sign_(), GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_mpi_print_unsigned(), GNUNET_free, GNUNET_malloc, GNUNET_OK, GNUNET_SECRETSHARING_ELGAMAL_BITS, GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1, KeygenSession::info, KeygenSession::local_peer_idx, my_peer, my_peer_private_key, KeygenPeerInfo::paillier_public_key, KeygenSession::presecret_polynomial, GNUNET_SECRETSHARING_KeygenCommitData::purpose, and GNUNET_SET_Element::size.

Referenced by handle_client_keygen().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_client_keygen()

static int check_client_keygen ( void *  cls,
const struct GNUNET_SECRETSHARING_CreateMessage msg 
)
static

Check that msg is well-formed.

Parameters
clsidentification of the client
msgthe actual message
Returns
GNUNET_OK if msg is well-formed

Definition at line 1708 of file gnunet-service-secretsharing.c.

1710{
1711 unsigned int num_peers = ntohs (msg->num_peers);
1712
1713 if (ntohs (msg->header.size) - sizeof(*msg) !=
1714 num_peers * sizeof(struct GNUNET_PeerIdentity))
1715 {
1716 GNUNET_break (0);
1717 return GNUNET_SYSERR;
1718 }
1719 return GNUNET_OK;
1720}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, msg, num_peers, and GNUNET_MessageHeader::size.

◆ handle_client_keygen()

static void handle_client_keygen ( void *  cls,
const struct GNUNET_SECRETSHARING_CreateMessage msg 
)
static

Functions with this signature are called whenever a message is received.

Parameters
clsidentification of the client
msgthe actual message

Definition at line 1731 of file gnunet-service-secretsharing.c.

1733{
1734 struct ClientState *cs = cls;
1735 struct KeygenSession *ks;
1736
1738 "client requested key generation\n");
1739 if (NULL != cs->keygen_session)
1740 {
1741 GNUNET_break (0);
1743 return;
1744 }
1745 ks = GNUNET_new (struct KeygenSession);
1746 ks->cs = cs;
1747 cs->keygen_session = ks;
1748 ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
1749 ks->threshold = ntohs (msg->threshold);
1750 ks->num_peers = ntohs (msg->num_peers);
1751
1752 ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1],
1753 ks->num_peers,
1754 &ks->num_peers,
1755 &ks->local_peer_idx);
1756
1757
1759 "first round of consensus with %u peers\n",
1760 ks->num_peers);
1762 ks->num_peers,
1763 ks->peers,
1764 &msg->session_id,
1766 msg->start),
1768 msg->deadline),
1770 ks);
1771
1772 ks->info = GNUNET_new_array (ks->num_peers,
1773 struct KeygenPeerInfo);
1774
1775 for (unsigned int i = 0; i < ks->num_peers; i++)
1776 ks->info[i].peer = ks->peers[i];
1777
1781
1783 "P%u: Generated paillier key pair\n",
1784 ks->local_peer_idx);
1787 "P%u: Generated presecret polynomial\n",
1788 ks->local_peer_idx);
1791 "P%u: Concluding for round 1\n",
1792 ks->local_peer_idx);
1795 ks);
1798 "P%u: Waiting for round 1 elements ...\n",
1799 ks->local_peer_idx);
1800}
static void keygen_round1_conclude(void *cls)
Called when the first consensus round has concluded.
static struct GNUNET_PeerIdentity * normalize_peers(struct GNUNET_PeerIdentity *listed, unsigned int num_listed, unsigned int *num_normalized, unsigned int *my_peer_idx)
Normalize the given list of peers, by including the local peer (if it is missing) and sorting the pee...
static void generate_presecret_polynomial(struct KeygenSession *ks)
Generate the random coefficients of our pre-secret polynomial.
static void insert_round1_element(struct KeygenSession *ks)
Insert the ephemeral key and the presecret commitment of this peer in the consensus of the given sess...
static void keygen_round1_new_element(void *cls, const struct GNUNET_SET_Element *element)
Consensus element handler for round one.
void GNUNET_CRYPTO_paillier_create(struct GNUNET_CRYPTO_PaillierPublicKey *public_key, struct GNUNET_CRYPTO_PaillierPrivateKey *private_key)
Create a freshly generated paillier public key.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2489
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2408
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
State we keep per client.
struct GNUNET_SERVICE_Client * client
Client this is about.

References cfg, ClientState::client, KeygenSession::consensus, KeygenSession::cs, KeygenSession::deadline, generate_presecret_polynomial(), GNUNET_break, GNUNET_CONSENSUS_conclude(), GNUNET_CONSENSUS_create(), GNUNET_CRYPTO_paillier_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_new, GNUNET_new_array, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_TIME_absolute_ntoh(), KeygenSession::info, insert_round1_element(), keygen_round1_conclude(), keygen_round1_new_element(), ClientState::keygen_session, KeygenSession::local_peer_idx, msg, normalize_peers(), KeygenSession::num_peers, KeygenSession::paillier_private_key, KeygenPeerInfo::paillier_public_key, KeygenPeerInfo::peer, KeygenSession::peers, and KeygenSession::threshold.

Here is the call graph for this function:

◆ decrypt_conclude()

static void decrypt_conclude ( void *  cls)
static

Called when the partial decryption consensus concludes.

Definition at line 1807 of file gnunet-service-secretsharing.c.

1808{
1809 struct DecryptSession *ds = cls;
1811 struct GNUNET_MQ_Envelope *ev;
1812 gcry_mpi_t lagrange;
1813 gcry_mpi_t m;
1814 gcry_mpi_t tmp;
1815 gcry_mpi_t c_2;
1816 gcry_mpi_t prod;
1817 unsigned int *indices;
1818 unsigned int num;
1819 unsigned int i;
1820 unsigned int j;
1821
1822 GNUNET_CONSENSUS_destroy (ds->consensus);
1823 ds->consensus = NULL;
1824
1825 GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
1826 GNUNET_assert (0 != (m = gcry_mpi_new (0)));
1827 GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
1828 GNUNET_assert (0 != (prod = gcry_mpi_new (0)));
1829
1830 num = 0;
1831 for (i = 0; i < ds->share->num_peers; i++)
1832 if (NULL != ds->info[i].partial_decryption)
1833 num++;
1834
1835 indices = GNUNET_new_array (num,
1836 unsigned int);
1837 j = 0;
1838 for (i = 0; i < ds->share->num_peers; i++)
1839 if (NULL != ds->info[i].partial_decryption)
1840 indices[j++] = ds->info[i].original_index;
1841
1843 "P%u: decrypt conclude, with %u peers\n",
1844 ds->share->my_peer,
1845 num);
1846
1847 gcry_mpi_set_ui (prod, 1);
1848 for (i = 0; i < num; i++)
1849 {
1851 "P%u: index of %u: %u\n",
1852 ds->share->my_peer, i, indices[i]);
1853 compute_lagrange_coefficient (lagrange, indices[i], indices, num);
1854 // w_i^{\lambda_i}
1855 gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange,
1856 elgamal_p);
1857
1858 // product of all exponentiated partiel decryptions ...
1859 gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1860 }
1861
1862 GNUNET_CRYPTO_mpi_scan_unsigned (&c_2, ds->ciphertext.c2_bits,
1864
1865 GNUNET_assert (0 != gcry_mpi_invm (prod, prod, elgamal_p));
1866 gcry_mpi_mulm (m, c_2, prod, elgamal_p);
1867 ev = GNUNET_MQ_msg (msg,
1871 msg->success = htonl (1);
1872 GNUNET_MQ_send (ds->cs->mq,
1873 ev);
1874
1875 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sent decrypt done to client\n");
1876
1877 GNUNET_free (indices);
1878
1879 gcry_mpi_release (lagrange);
1880 gcry_mpi_release (m);
1881 gcry_mpi_release (tmp);
1882 gcry_mpi_release (prod);
1883 gcry_mpi_release (c_2);
1884
1885 // FIXME: what if not enough peers participated?
1886}
static void compute_lagrange_coefficient(gcry_mpi_t coeff, unsigned int j, unsigned int *indices, unsigned int num)
Get a the j-th lagrange coefficient for a set of indices.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE
The service succeeded in decrypting a ciphertext.
Session to cooperatively decrypt a value.

References compute_lagrange_coefficient(), ds, elgamal_p, GNUNET_assert, GNUNET_CONSENSUS_destroy(), GNUNET_CRYPTO_mpi_print_unsigned(), GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_new_array, GNUNET_SECRETSHARING_ELGAMAL_BITS, m, and msg.

Referenced by handle_client_decrypt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mpi_to_str()

static char * mpi_to_str ( gcry_mpi_t  mpi)
static

Get a string representation of an MPI.

The caller must free the returned string.

Parameters
mpimpi to convert to a string
Returns
string representation of mpi, must be free'd by the caller

Definition at line 1897 of file gnunet-service-secretsharing.c.

1898{
1899 unsigned char *buf;
1900
1901 GNUNET_assert (0 == gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, mpi));
1902 return (char *) buf;
1903}

References GNUNET_assert.

Referenced by decrypt_new_element(), and insert_decrypt_element().

Here is the caller graph for this function:

◆ decrypt_new_element()

static void decrypt_new_element ( void *  cls,
const struct GNUNET_SET_Element element 
)
static

Called when a new partial decryption arrives.

Definition at line 1910 of file gnunet-service-secretsharing.c.

1912{
1913 struct DecryptSession *session = cls;
1914 const struct GNUNET_SECRETSHARING_DecryptData *d;
1915 struct DecryptPeerInfo *info;
1916 struct GNUNET_HashCode challenge_hash;
1917
1918 /* nizk response */
1919 gcry_mpi_t r;
1920 /* nizk challenge */
1921 gcry_mpi_t challenge;
1922 /* nizk commit1, g^\beta */
1923 gcry_mpi_t commit1;
1924 /* nizk commit2, c_1^\beta */
1925 gcry_mpi_t commit2;
1926 /* homomorphic commitment to the peer's share,
1927 * public key share */
1928 gcry_mpi_t sigma;
1929 /* partial decryption we received */
1930 gcry_mpi_t w;
1931 /* ciphertext component #1 */
1932 gcry_mpi_t c1;
1933 /* temporary variable (for comparison) #1 */
1934 gcry_mpi_t tmp1;
1935 /* temporary variable (for comparison) #2 */
1936 gcry_mpi_t tmp2;
1937
1938 if (NULL == element)
1939 {
1940 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n");
1941 /* FIXME: destroy */
1942 return;
1943 }
1944
1945 if (element->size != sizeof *d)
1946 {
1948 "element of wrong size in decrypt consensus\n");
1949 return;
1950 }
1951
1952 d = element->data;
1953
1954 info = get_decrypt_peer_info (session, &d->peer);
1955
1956 if (NULL == info)
1957 {
1959 "decrypt element from invalid peer (%s)\n",
1960 GNUNET_i2s (&d->peer));
1961 return;
1962 }
1963
1964 if (NULL != info->partial_decryption)
1965 {
1966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n");
1967 return;
1968 }
1969
1970 if (0 != GNUNET_memcmp (&d->ciphertext, &session->ciphertext))
1971 {
1973 "P%u: got decrypt element with non-matching ciphertext from P%u\n",
1974 (unsigned int) session->share->my_peer, (unsigned int) (info
1975 -
1976 session
1977 ->info));
1978
1979 return;
1980 }
1981
1982
1984 ciphertext) + (char *) d,
1985 offsetof (struct GNUNET_SECRETSHARING_DecryptData,
1986 nizk_response)
1987 - offsetof (struct GNUNET_SECRETSHARING_DecryptData,
1988 ciphertext),
1989 &challenge_hash);
1990
1991 GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
1992 sizeof(struct GNUNET_HashCode));
1993
1995 - session->
1996 info],
1997 sizeof(struct
1999
2001 sizeof(struct
2003
2004 GNUNET_CRYPTO_mpi_scan_unsigned (&commit1, &d->nizk_commit1,
2005 sizeof(struct
2007
2008 GNUNET_CRYPTO_mpi_scan_unsigned (&commit2, &d->nizk_commit2,
2009 sizeof(struct
2011
2012 GNUNET_CRYPTO_mpi_scan_unsigned (&r, &d->nizk_response,
2013 sizeof(struct
2015
2016 GNUNET_CRYPTO_mpi_scan_unsigned (&w, &d->partial_decryption,
2017 sizeof(struct
2019
2020 GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0)));
2021 GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0)));
2022
2023 // tmp1 = g^r
2024 gcry_mpi_powm (tmp1, elgamal_g, r, elgamal_p);
2025
2026 // tmp2 = g^\beta * \sigma^challenge
2027 gcry_mpi_powm (tmp2, sigma, challenge, elgamal_p);
2028 gcry_mpi_mulm (tmp2, tmp2, commit1, elgamal_p);
2029
2030 if (0 != gcry_mpi_cmp (tmp1, tmp2))
2031 {
2032 char *tmp1_str;
2033 char *tmp2_str;
2034
2035 tmp1_str = mpi_to_str (tmp1);
2036 tmp2_str = mpi_to_str (tmp2);
2038 "P%u: Received invalid partial decryption from P%u (eqn 1), expected %s got %s\n",
2039 session->share->my_peer,
2040 (unsigned int) (info - session->info),
2041 tmp1_str,
2042 tmp2_str);
2043 GNUNET_free (tmp1_str);
2044 GNUNET_free (tmp2_str);
2045 goto cleanup;
2046 }
2047
2048
2049 gcry_mpi_powm (tmp1, c1, r, elgamal_p);
2050
2051 gcry_mpi_powm (tmp2, w, challenge, elgamal_p);
2052 gcry_mpi_mulm (tmp2, tmp2, commit2, elgamal_p);
2053
2054
2055 if (0 != gcry_mpi_cmp (tmp1, tmp2))
2056 {
2058 "P%u: Received invalid partial decryption from P%u (eqn 2)\n",
2059 session->share->my_peer,
2060 (unsigned int) (info - session->info));
2061 goto cleanup;
2062 }
2063
2064
2065 GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption,
2066 &d->partial_decryption,
2068cleanup:
2069 gcry_mpi_release (tmp1);
2070 gcry_mpi_release (tmp2);
2071 gcry_mpi_release (sigma);
2072 gcry_mpi_release (commit1);
2073 gcry_mpi_release (commit2);
2074 gcry_mpi_release (r);
2075 gcry_mpi_release (w);
2076 gcry_mpi_release (challenge);
2077 gcry_mpi_release (c1);
2078}
static struct DecryptPeerInfo * get_decrypt_peer_info(const struct DecryptSession *ds, const struct GNUNET_PeerIdentity *peer)
Get the peer info belonging to a peer identity in a decrypt session.
static char * mpi_to_str(gcry_mpi_t mpi)
Get a string representation of an MPI.
Information about a peer in a decrypt session.
struct DecryptPeerInfo * info
State information about other peers.
struct GNUNET_SECRETSHARING_Share * share
Share of the local peer.
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.
uint32_t c1_bits[1024/8/sizeof(uint32_t)]
Data of then element put in consensus for decrypting a value.

References GNUNET_SECRETSHARING_Ciphertext::c1_bits, DecryptSession::ciphertext, cleanup(), d, GNUNET_SET_Element::data, elgamal_g, elgamal_p, get_decrypt_peer_info(), GNUNET_assert, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_memcmp, GNUNET_SECRETSHARING_ELGAMAL_BITS, info, DecryptSession::info, mpi_to_str(), GNUNET_SECRETSHARING_Share::my_peer, DecryptSession::share, GNUNET_SECRETSHARING_Share::sigmas, and GNUNET_SET_Element::size.

Referenced by handle_client_decrypt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ insert_decrypt_element()

static void insert_decrypt_element ( struct DecryptSession ds)
static

Definition at line 2082 of file gnunet-service-secretsharing.c.

2083{
2085 struct GNUNET_SET_Element element;
2086 /* our share */
2087 gcry_mpi_t s;
2088 /* partial decryption with our share */
2089 gcry_mpi_t w;
2090 /* first component of the elgamal ciphertext */
2091 gcry_mpi_t c1;
2092 /* nonce for dlog zkp */
2093 gcry_mpi_t beta;
2094 gcry_mpi_t tmp;
2095 gcry_mpi_t challenge;
2096 gcry_mpi_t sigma;
2097 struct GNUNET_HashCode challenge_hash;
2098
2099 /* make vagrind happy until we implement the real deal ... */
2100 memset (&d, 0, sizeof d);
2101
2102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n",
2103 ds->share->my_peer);
2104
2105 GNUNET_assert (ds->share->my_peer < ds->share->num_peers);
2106
2107 GNUNET_CRYPTO_mpi_scan_unsigned (&c1, &ds->ciphertext.c1_bits,
2109 GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share,
2112 &ds->share->sigmas[ds->share->my_peer],
2114
2115 GNUNET_assert (NULL != (w = gcry_mpi_new (0)));
2116 GNUNET_assert (NULL != (beta = gcry_mpi_new (0)));
2117 GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
2118
2119 // FIXME: unnecessary, remove once crypto works
2120 gcry_mpi_powm (tmp, elgamal_g, s, elgamal_p);
2121 if (0 != gcry_mpi_cmp (tmp, sigma))
2122 {
2123 char *sigma_str = mpi_to_str (sigma);
2124 char *tmp_str = mpi_to_str (tmp);
2125 char *s_str = mpi_to_str (s);
2127 "Share of P%u is invalid, ref sigma %s, "
2128 "computed sigma %s, s %s\n",
2129 ds->share->my_peer,
2130 sigma_str, tmp_str, s_str);
2131 GNUNET_free (sigma_str);
2132 GNUNET_free (tmp_str);
2133 GNUNET_free (s_str);
2134 }
2135
2136 gcry_mpi_powm (w, c1, s, elgamal_p);
2137
2138 element.data = (void *) &d;
2139 element.size = sizeof(struct GNUNET_SECRETSHARING_DecryptData);
2140 element.element_type = 0;
2141
2142 d.ciphertext = ds->ciphertext;
2143 d.peer = my_peer;
2144 GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption,
2146
2147 // create the zero knowledge proof
2148 // randomly choose beta such that 0 < beta < q
2149 do
2150 {
2151 gcry_mpi_randomize (beta, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1,
2152 GCRY_WEAK_RANDOM);
2153 }
2154 while ((gcry_mpi_cmp_ui (beta, 0) == 0) || (gcry_mpi_cmp (beta, elgamal_q) >=
2155 0));
2156 // tmp = g^beta
2157 gcry_mpi_powm (tmp, elgamal_g, beta, elgamal_p);
2158 GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit1,
2160 // tmp = (c_1)^beta
2161 gcry_mpi_powm (tmp, c1, beta, elgamal_p);
2162 GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit2,
2164
2165 // the challenge is the hash of everything up to the response
2167 ciphertext) + (char *) &d,
2168 offsetof (struct GNUNET_SECRETSHARING_DecryptData,
2170 - offsetof (struct GNUNET_SECRETSHARING_DecryptData,
2171 ciphertext),
2172 &challenge_hash);
2173
2174 GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash,
2175 sizeof(struct GNUNET_HashCode));
2176
2177 // compute the response in tmp,
2178 // tmp = (c * s + beta) mod q
2179 gcry_mpi_mulm (tmp, challenge, s, elgamal_q);
2180 gcry_mpi_addm (tmp, tmp, beta, elgamal_q);
2181
2182 GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_response,
2184
2185 d.purpose.size = htonl (element.size - offsetof (struct
2187 purpose));
2188 d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
2189
2192 &d.purpose,
2193 &d.signature));
2194
2195 GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
2197 "P%u: Inserting decrypt element done!\n",
2198 ds->share->my_peer);
2199
2200 gcry_mpi_release (s);
2201 gcry_mpi_release (w);
2202 gcry_mpi_release (c1);
2203 gcry_mpi_release (beta);
2204 gcry_mpi_release (tmp);
2205 gcry_mpi_release (challenge);
2206 gcry_mpi_release (sigma);
2207}
static float beta
Percentage of total peer number in the view to send random PULLs to.
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION
Signature for the cooperative decryption.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.
struct GNUNET_SECRETSHARING_FieldElement nizk_response
Response to the challenge computed from the protocol transcript.

References beta, GNUNET_SECRETSHARING_DecryptData::ciphertext, d, GNUNET_SET_Element::data, ds, GNUNET_SET_Element::element_type, elgamal_g, elgamal_p, elgamal_q, GNUNET_assert, GNUNET_CONSENSUS_insert(), GNUNET_CRYPTO_eddsa_sign_(), GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_mpi_print_unsigned(), GNUNET_CRYPTO_mpi_scan_unsigned(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_SECRETSHARING_ELGAMAL_BITS, GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION, mpi_to_str(), my_peer, my_peer_private_key, GNUNET_SECRETSHARING_DecryptData::nizk_response, GNUNET_SECRETSHARING_DecryptData::purpose, and GNUNET_SET_Element::size.

Referenced by handle_client_decrypt().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_client_decrypt()

static int check_client_decrypt ( void *  cls,
const struct GNUNET_SECRETSHARING_DecryptRequestMessage msg 
)
static

Check that msg is well-formed.

Parameters
clsidentification of the client
msgthe actual message
Returns
GNUNET_OK (check deferred a bit)

Definition at line 2218 of file gnunet-service-secretsharing.c.

2221{
2222 /* we check later, it's complicated */
2223 return GNUNET_OK;
2224}

References GNUNET_OK.

◆ handle_client_decrypt()

static void handle_client_decrypt ( void *  cls,
const struct GNUNET_SECRETSHARING_DecryptRequestMessage msg 
)
static

Functions with this signature are called whenever a message is received.

Parameters
clsidentification of the client
msgthe actual message

Definition at line 2235 of file gnunet-service-secretsharing.c.

2238{
2239 struct ClientState *cs = cls;
2240 struct DecryptSession *ds;
2241 struct GNUNET_HashCode session_id;
2242
2243 if (NULL != cs->decrypt_session)
2244 {
2245 GNUNET_break (0);
2247 return;
2248 }
2249 ds = GNUNET_new (struct DecryptSession);
2250 cs->decrypt_session = ds;
2251 ds->cs = cs;
2252 ds->start = GNUNET_TIME_absolute_ntoh (msg->start);
2253 ds->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline);
2254 ds->ciphertext = msg->ciphertext;
2255
2257 ntohs (msg->header.size)
2258 - sizeof(*msg),
2259 NULL);
2260 if (NULL == ds->share)
2261 {
2262 GNUNET_break (0);
2264 return;
2265 }
2266
2267 /* FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ... */
2268 GNUNET_CRYPTO_hash (&msg->ciphertext,
2269 sizeof(struct GNUNET_SECRETSHARING_Ciphertext),
2270 &session_id);
2271 ds->consensus = GNUNET_CONSENSUS_create (cfg,
2272 ds->share->num_peers,
2273 ds->share->peers,
2274 &session_id,
2275 ds->start,
2276 ds->deadline,
2278 ds);
2279
2280
2281 ds->info = GNUNET_new_array (ds->share->num_peers,
2282 struct DecryptPeerInfo);
2283 for (unsigned int i = 0; i < ds->share->num_peers; i++)
2284 {
2285 ds->info[i].peer = ds->share->peers[i];
2286 ds->info[i].original_index = ds->share->original_indices[i];
2287 }
2289 GNUNET_CONSENSUS_conclude (ds->consensus,
2291 ds);
2294 "decrypting with %u peers\n",
2295 ds->share->num_peers);
2296}
static void insert_decrypt_element(struct DecryptSession *ds)
static void decrypt_conclude(void *cls)
Called when the partial decryption consensus concludes.
static void decrypt_new_element(void *cls, const struct GNUNET_SET_Element *element)
Called when a new partial decryption arrives.
struct GNUNET_SECRETSHARING_Share * GNUNET_SECRETSHARING_share_read(const void *data, size_t len, size_t *readlen)
Read a share from its binary representation.
struct DecryptSession * decrypt_session
Decrypt session of the client, if any.

References cfg, ClientState::client, decrypt_conclude(), decrypt_new_element(), ClientState::decrypt_session, ds, GNUNET_break, GNUNET_CONSENSUS_conclude(), GNUNET_CONSENSUS_create(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_new, GNUNET_new_array, GNUNET_SECRETSHARING_share_read(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_TIME_absolute_ntoh(), insert_decrypt_element(), msg, and GNUNET_MessageHeader::size.

Here is the call graph for this function:

◆ init_crypto_constants()

static void init_crypto_constants ( void  )
static

Definition at line 2300 of file gnunet-service-secretsharing.c.

2301{
2302 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
2304 NULL));
2305 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
2307 NULL));
2308 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
2310 NULL));
2311}
#define GNUNET_SECRETSHARING_ELGAMAL_P_HEX
The q-parameter for ElGamal encryption, a 1024-bit safe prime.
#define GNUNET_SECRETSHARING_ELGAMAL_Q_HEX
The q-parameter for ElGamal encryption, a 1023-bit Sophie Germain prime, q = (p-1)/2.
#define GNUNET_SECRETSHARING_ELGAMAL_G_HEX
The g-parameter for ElGamal encryption, a generator of the unique size q subgroup of Z_p^*.

References elgamal_g, elgamal_p, elgamal_q, GNUNET_assert, GNUNET_SECRETSHARING_ELGAMAL_G_HEX, GNUNET_SECRETSHARING_ELGAMAL_P_HEX, and GNUNET_SECRETSHARING_ELGAMAL_Q_HEX.

Referenced by run().

Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle service 
)
static

Initialize secretsharing service.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

Definition at line 2322 of file gnunet-service-secretsharing.c.

2325{
2326 cfg = c;
2328 if (NULL == my_peer_private_key)
2329 {
2331 "could not access host private key\n");
2332 GNUNET_break (0);
2334 return;
2335 }
2337 if (GNUNET_OK !=
2339 &my_peer))
2340 {
2342 "could not retrieve host identity\n");
2343 GNUNET_break (0);
2345 return;
2346 }
2348 NULL);
2349}
static void cleanup_task(void *cls)
Task run during shutdown.
static void init_crypto_constants(void)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host's peer.
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer's key from the file specified in the configuration.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1340

References cfg, cleanup_task(), GNUNET_break, GNUNET_CRYPTO_eddsa_key_create_from_configuration(), GNUNET_CRYPTO_get_peer_identity(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_OK, GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), init_crypto_constants(), my_peer, and my_peer_private_key.

Here is the call graph for this function:

◆ client_connect_cb()

static void * client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
struct GNUNET_MQ_Handle mq 
)
static

Callback called when a client connects to the service.

Parameters
clsclosure for the service
cthe new client that connected to the service
mqthe message queue used to send messages to the client
Returns
c

Definition at line 2361 of file gnunet-service-secretsharing.c.

2364{
2365 struct ClientState *cs = GNUNET_new (struct ClientState);;
2366
2367 cs->client = c;
2368 cs->mq = mq;
2369 return cs;
2370}
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5

References ClientState::client, GNUNET_new, mq, and ClientState::mq.

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
void *  internal_cls 
)
static

Callback called when a client disconnected from the service.

Parameters
clsclosure for the service
cthe client that disconnected
internal_clsshould be equal to c

Definition at line 2381 of file gnunet-service-secretsharing.c.

2384{
2385 struct ClientState *cs = internal_cls;
2386
2387 if (NULL != cs->keygen_session)
2389
2390 if (NULL != cs->decrypt_session)
2392 GNUNET_free (cs);
2393}
static void keygen_session_destroy(struct KeygenSession *ks)
static void decrypt_session_destroy(struct DecryptSession *ds)
Destroy a decrypt session, removing it from the linked list of decrypt sessions.

References ClientState::decrypt_session, decrypt_session_destroy(), GNUNET_free, ClientState::keygen_session, and keygen_session_destroy().

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( "secretsharing"  ,
GNUNET_SERVICE_OPTION_NONE  ,
run,
client_connect_cb,
client_disconnect_cb,
NULL  ,
GNUNET_MQ_hd_var_size(client_keygen, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, struct GNUNET_SECRETSHARING_CreateMessage, NULL)  ,
GNUNET_MQ_hd_var_size(client_decrypt, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, struct GNUNET_SECRETSHARING_DecryptRequestMessage, NULL)  ,
GNUNET_MQ_handler_end()   
)

Define "main" method using service macro.

Variable Documentation

◆ elgamal_q

◆ elgamal_p

◆ elgamal_g

gcry_mpi_t elgamal_g
static

◆ my_peer

◆ my_peer_private_key

struct GNUNET_CRYPTO_EddsaPrivateKey* my_peer_private_key
static

Peer that runs this service.

Definition at line 309 of file gnunet-service-secretsharing.c.

Referenced by insert_decrypt_element(), insert_round1_element(), insert_round2_element(), and run().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Configuration of this service.

Definition at line 314 of file gnunet-service-secretsharing.c.

Referenced by handle_client_decrypt(), handle_client_keygen(), keygen_round1_conclude(), and run().