GNUnet  0.20.0
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.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.

References GNUNET_memcmp, KeygenSession::info, KeygenSession::num_peers, KeygenPeerInfo::peer, and 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 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 345 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.

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 struct LoggingHandle * l
static gcry_mpi_t elgamal_q
The ElGamal prime field order as libgcrypt mpi.

References elgamal_q, GNUNET_assert, and l.

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 
675  GNUNET_assert (NULL == ks->presecret_polynomial);
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 }
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1
Signature for the first round of distributed key generation.
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
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Consensus element data used in the first round of key generation.
struct GNUNET_PeerIdentity peer
Peer that inserts this element.
struct GNUNET_HashCode commitment
Commitment of 'peer' to its presecret.
struct GNUNET_CRYPTO_PaillierPublicKey pubkey
Ephemeral paillier public key used by 'peer' for this session.
struct GNUNET_CRYPTO_EddsaSignature signature
Signature over the rest of the message.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Signature purpose for signing the keygen commit data.
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 GNUNET_SECRETSHARING_KeygenCommitData::commitment, 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, GNUNET_SECRETSHARING_KeygenCommitData::peer, GNUNET_SECRETSHARING_KeygenCommitData::pubkey, GNUNET_PeerIdentity::public_key, GNUNET_SECRETSHARING_KeygenCommitData::purpose, GNUNET_SECRETSHARING_KeygenCommitData::signature, GNUNET_CRYPTO_EccSignaturePurpose::size, 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 =
821  GNUNET_new_array (share->num_peers,
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  {
1007  char t1[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
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
static struct Experiment * e
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, e, 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);
1066  GNUNET_CRYPTO_mpi_scan_unsigned (&big_y, fe->c.bits,
1067  GNUNET_CRYPTO_PAILLIER_BITS * 2 / 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 
1108 cleanup:
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 int res
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
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(), e, 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 }

References GNUNET_CRYPTO_PaillierCiphertext::bits, GNUNET_SECRETSHARING_FairEncryption::c, e, 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, 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 
1278  + sizeof(struct GNUNET_SECRETSHARING_FairEncryption)
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));
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 }
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2
Signature for the second round of distributed key generation.
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.
static unsigned int element_size
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.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
struct GNUNET_CRYPTO_EddsaSignature signature
Signature over rest of the message.
struct GNUNET_PeerIdentity peer
Peer that inserts this element.
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, GNUNET_SET_Element::data, element_size, 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, GNUNET_SECRETSHARING_KeygenRevealData::peer, KeygenSession::presecret_polynomial, GNUNET_CRYPTO_EccSignaturePurpose::purpose, GNUNET_SECRETSHARING_KeygenRevealData::purpose, KeygenPeerInfo::round1_valid, GNUNET_SECRETSHARING_KeygenRevealData::signature, GNUNET_CRYPTO_EccSignaturePurpose::size, 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 }
static unsigned int threshold
What should the threshold for then key be?

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

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

References 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 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;
1417  const struct GNUNET_SECRETSHARING_KeygenRevealData *d;
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  {
1603  keygen_reveal_get_enc_preshare (ks, d, j);
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_PaillierPrivateKey paillier_private_key
Paillier private key of our peer.

References GNUNET_SECRETSHARING_FairEncryption::c, 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, GNUNET_SECRETSHARING_KeygenRevealData::peer, GNUNET_PeerIdentity::public_key, KeygenSession::public_key, GNUNET_SECRETSHARING_KeygenRevealData::purpose, restore_fair(), KeygenPeerInfo::sigma, GNUNET_SECRETSHARING_KeygenRevealData::signature, GNUNET_CRYPTO_EccSignaturePurpose::size, 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,
1636  time_between (ks->start_time,
1637  ks->deadline, 1, 2),
1638  ks->deadline,
1640 
1641  insert_round2_element (ks);
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 
1683 
1684  d->purpose.size = htonl ((sizeof *d) - offsetof (struct
1686  purpose));
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 }

References GNUNET_SECRETSHARING_KeygenCommitData::commitment, KeygenSession::consensus, 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, GNUNET_SECRETSHARING_KeygenCommitData::peer, KeygenSession::presecret_polynomial, GNUNET_SECRETSHARING_KeygenCommitData::pubkey, GNUNET_CRYPTO_EccSignaturePurpose::purpose, GNUNET_SECRETSHARING_KeygenCommitData::purpose, GNUNET_SECRETSHARING_KeygenCommitData::signature, GNUNET_CRYPTO_EccSignaturePurpose::size, 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 
1780  &ks->paillier_private_key);
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);
1789  insert_round1_element (ks);
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 void generate_presecret_polynomial(struct KeygenSession *ks)
Generate the random coefficients of our pre-secret polynomial.
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 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:2330
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2249
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 }
static char buf[2048]

References buf, and 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 
1994  GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &session->share->sigmas[info
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,
2068 cleanup:
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 GNUNET_SECRETSHARING_Ciphertext ciphertext
static char * mpi_to_str(gcry_mpi_t mpi)
Get a string representation of an MPI.
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.
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.
struct GNUNET_PeerIdentity peer
Peer that inserts this element.
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.

References GNUNET_SECRETSHARING_Ciphertext::c1_bits, ciphertext, DecryptSession::ciphertext, GNUNET_SECRETSHARING_DecryptData::ciphertext, cleanup(), 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, GNUNET_SECRETSHARING_DecryptData::nizk_commit1, GNUNET_SECRETSHARING_DecryptData::nizk_commit2, GNUNET_SECRETSHARING_DecryptData::nizk_response, GNUNET_SECRETSHARING_DecryptData::partial_decryption, GNUNET_SECRETSHARING_DecryptData::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,
2169  nizk_response)
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 }
#define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION
Signature for the cooperative decryption.
static float beta
Percentage of total peer number in the view to send random PULLs to.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
struct GNUNET_SECRETSHARING_FieldElement nizk_response
Response to the challenge computed from the protocol transcript.

References beta, ciphertext, GNUNET_SECRETSHARING_DecryptData::ciphertext, 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_commit1, GNUNET_SECRETSHARING_DecryptData::nizk_commit2, GNUNET_SECRETSHARING_DecryptData::nizk_response, GNUNET_SECRETSHARING_DecryptData::partial_decryption, GNUNET_SECRETSHARING_DecryptData::peer, GNUNET_CRYPTO_EccSignaturePurpose::purpose, GNUNET_SECRETSHARING_DecryptData::purpose, GNUNET_SECRETSHARING_DecryptData::signature, GNUNET_CRYPTO_EccSignaturePurpose::size, 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 
2256  ds->share = GNUNET_SECRETSHARING_share_read (&msg[1],
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 struct GNUNET_HashCode session_id
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, session_id, 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)
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.
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.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
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:1334

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().