GNUnet  0.19.4
secretsharing_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
29 #include "secretsharing.h"
30 #include <gcrypt.h>
31 
32 
33 #define LOG(kind, ...) GNUNET_log_from (kind, "secretsharing-api", __VA_ARGS__)
34 
40 {
45 
50 
55 };
56 
57 
62 {
67 
72 
76  void *decrypt_cls;
77 };
78 
79 
84 static gcry_mpi_t elgamal_q;
85 
90 static gcry_mpi_t elgamal_p;
91 
96 static gcry_mpi_t elgamal_g;
97 
98 
102 static void
104 {
105  if (NULL != elgamal_q)
106  return; /* looks like crypto is already initialized */
107 
108  GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
110  NULL));
111  GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
113  NULL));
114  GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
116  NULL));
117 }
118 
119 
127 static void
129  enum GNUNET_MQ_Error error)
130 {
131  struct GNUNET_SECRETSHARING_Session *s = cls;
132 
133  s->secret_ready_cb (s->secret_ready_cls, NULL, NULL, 0, NULL);
135 }
136 
137 
145 static void
147  enum GNUNET_MQ_Error error)
148 {
149  struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls;
150 
151  dh->decrypt_cb (dh->decrypt_cls, NULL);
153 }
154 
155 
164 static int
167 {
168  /* FIXME: actually check m is well-formed here! */
169  return GNUNET_OK;
170 }
171 
172 
181 static void
184 {
185  struct GNUNET_SECRETSHARING_Session *s = cls;
186  struct GNUNET_SECRETSHARING_Share *share;
187  size_t share_size;
188 
190  "Got secret ready message of size %u\n",
191  ntohs (m->header.size));
192  share_size = ntohs (m->header.size) - sizeof(struct
194 
195  share = GNUNET_SECRETSHARING_share_read (&m[1],
196  share_size,
197  NULL);
198  GNUNET_assert (NULL != share); // FIXME: this can fail!
199  // should have been checked in #check_secret_ready!
200  // FIXME: below we never check &m[1] is valid!
201  // FIXME: do we leak 'share' here?
203  share, /* FIXME */
204  &share->public_key,
205  share->num_peers,
206  (const struct GNUNET_PeerIdentity *) &m[1]);
207 
209 }
210 
211 
218 void
220 {
221  GNUNET_MQ_destroy (s->mq);
222  s->mq = NULL;
223  GNUNET_free (s);
224 }
225 
226 
246  unsigned int num_peers,
247  const struct GNUNET_PeerIdentity *peers,
248  const struct GNUNET_HashCode *session_id,
251  unsigned int threshold,
253  void *cls)
254 {
257  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
258  GNUNET_MQ_hd_var_size (secret_ready,
261  s),
263  };
264  struct GNUNET_MQ_Envelope *ev;
266 
268  "secretsharing",
269  mq_handlers,
271  s);
272  if (NULL == s->mq)
273  {
274  /* secretsharing not configured correctly */
275  GNUNET_break (0);
276  GNUNET_free (s);
277  return NULL;
278  }
279  s->secret_ready_cb = cb;
280  s->secret_ready_cls = cls;
281  ev = GNUNET_MQ_msg_extra (msg,
282  num_peers * sizeof(struct GNUNET_PeerIdentity),
284 
285  msg->threshold = htons (threshold);
286  msg->num_peers = htons (num_peers);
287  msg->session_id = *session_id;
289  msg->deadline = GNUNET_TIME_absolute_hton (deadline);
290  GNUNET_memcpy (&msg[1], peers, num_peers * sizeof(struct
292 
293  GNUNET_MQ_send (s->mq, ev);
294 
296  "Secretsharing session created with %u peers\n",
297  num_peers);
298  return s;
299 }
300 
301 
302 static void
304  const struct
306 {
307  struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls;
308  const struct GNUNET_SECRETSHARING_Plaintext *plaintext;
309 
310  if (m->success == 0)
311  plaintext = NULL;
312  else
313  plaintext = (void *) &m->plaintext;
314  dh->decrypt_cb (dh->decrypt_cls, plaintext);
316 }
317 
318 
321  struct GNUNET_SECRETSHARING_Share *share,
322  const struct
327  void *decrypt_cb_cls)
328 {
331  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
332  GNUNET_MQ_hd_fixed_size (decrypt_done,
335  s),
337  };
338  struct GNUNET_MQ_Envelope *ev;
340  size_t share_size;
341 
342  s->decrypt_cb = decrypt_cb;
343  s->decrypt_cls = decrypt_cb_cls;
345  "secretsharing",
346  mq_handlers,
348  s);
349  if (NULL == s->mq)
350  {
351  GNUNET_free (s);
352  return NULL;
353  }
355  GNUNET_SECRETSHARING_share_write (share, NULL, 0,
356  &share_size));
357 
358  ev = GNUNET_MQ_msg_extra (msg,
359  share_size,
361 
364  &msg[1],
365  share_size,
366  NULL));
367 
369  msg->deadline = GNUNET_TIME_absolute_hton (deadline);
370  msg->ciphertext = *ciphertext;
371 
372  GNUNET_MQ_send (s->mq, ev);
373 
375  "decrypt session created\n");
376  return s;
377 }
378 
379 
380 int
383  plaintext,
384  int64_t exponent)
385 {
386  int negative;
387  gcry_mpi_t x;
388 
390 
391  GNUNET_assert (NULL != (x = gcry_mpi_new (0)));
392 
393  negative = GNUNET_NO;
394  if (exponent < 0)
395  {
396  negative = GNUNET_YES;
397  exponent = -exponent;
398  }
399 
400  gcry_mpi_set_ui (x, exponent);
401 
402  gcry_mpi_powm (x, elgamal_g, x, elgamal_p);
403 
404  if (GNUNET_YES == negative)
405  {
406  int res;
407  res = gcry_mpi_invm (x, x, elgamal_p);
408  if (0 == res)
409  return GNUNET_SYSERR;
410  }
411 
413  sizeof(struct
415  x);
416 
417  return GNUNET_OK;
418 }
419 
420 
421 int
423  GNUNET_SECRETSHARING_PublicKey *public_key,
424  const struct
427  result_ciphertext)
428 {
429  /* pubkey */
430  gcry_mpi_t h;
431  /* nonce */
432  gcry_mpi_t y;
433  /* plaintext message */
434  gcry_mpi_t m;
435  /* temp value */
436  gcry_mpi_t tmp;
437 
439 
440  GNUNET_assert (NULL != (h = gcry_mpi_new (0)));
441  GNUNET_assert (NULL != (y = gcry_mpi_new (0)));
442  GNUNET_assert (NULL != (tmp = gcry_mpi_new (0)));
443 
444  GNUNET_CRYPTO_mpi_scan_unsigned (&h, public_key, sizeof *public_key);
445  GNUNET_CRYPTO_mpi_scan_unsigned (&m, plaintext, sizeof *plaintext);
446 
447  // Randomize y such that 0 < y < elgamal_q.
448  // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
449  do
450  {
451  gcry_mpi_randomize (y, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1,
452  GCRY_WEAK_RANDOM);
453  }
454  while ((gcry_mpi_cmp_ui (y, 0) == 0) || (gcry_mpi_cmp (y, elgamal_q) >= 0));
455 
456  // tmp <- g^y
457  gcry_mpi_powm (tmp, elgamal_g, y, elgamal_p);
458  // write tmp to c1
459  GNUNET_CRYPTO_mpi_print_unsigned (&result_ciphertext->c1_bits,
461 
462  // tmp <- h^y
463  gcry_mpi_powm (tmp, h, y, elgamal_p);
464  // tmp <- tmp * m
465  gcry_mpi_mulm (tmp, tmp, m, elgamal_p);
466  // write tmp to c2
467  GNUNET_CRYPTO_mpi_print_unsigned (&result_ciphertext->c2_bits,
469 
470  return GNUNET_OK;
471 }
472 
473 
482 void
485 {
486  GNUNET_MQ_destroy (dh->mq);
487  dh->mq = NULL;
488  GNUNET_free (dh);
489 }
490 
491 
492 /* end of secretsharing_api.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int res
static struct CadetPeer * peers
Operation to get peer ids.
static struct GNUNET_TIME_Absolute deadline
Deadline for all consensuses.
static struct GNUNET_HashCode session_id
static unsigned int num_peers
static unsigned int threshold
What should the threshold for then key be?
static struct GNUNET_SECRETSHARING_Ciphertext ciphertext
static void decrypt_cb(void *cls, const struct GNUNET_SECRETSHARING_Plaintext *plaintext)
Called when a decryption has succeeded.
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
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
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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_MQ_Error
Error codes for the queue.
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_handler_end()
End-marker for the handlers array.
#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:62
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY
The cryptosystem has been established.
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT
Request the decryption of a ciphertext.
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE
The service succeeded in decrypting a ciphertext.
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE
Establish a new session.
int GNUNET_SECRETSHARING_encrypt(const struct GNUNET_SECRETSHARING_PublicKey *public_key, const struct GNUNET_SECRETSHARING_Plaintext *plaintext, struct GNUNET_SECRETSHARING_Ciphertext *result_ciphertext)
Encrypt a value.
struct GNUNET_SECRETSHARING_DecryptionHandle * GNUNET_SECRETSHARING_decrypt(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SECRETSHARING_Share *share, const struct GNUNET_SECRETSHARING_Ciphertext *ciphertext, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, GNUNET_SECRETSHARING_DecryptCallback decrypt_cb, void *decrypt_cb_cls)
Publish the given ciphertext for decryption.
struct GNUNET_SECRETSHARING_Session * GNUNET_SECRETSHARING_create_session(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, unsigned int threshold, GNUNET_SECRETSHARING_SecretReadyCallback cb, void *cls)
Create a session that will eventually establish a shared secret with the other peers.
void GNUNET_SECRETSHARING_decrypt_cancel(struct GNUNET_SECRETSHARING_DecryptionHandle *dh)
Cancel a decryption.
int GNUNET_SECRETSHARING_plaintext_generate_i(struct GNUNET_SECRETSHARING_Plaintext *plaintext, int64_t exponent)
#define GNUNET_SECRETSHARING_ELGAMAL_BITS
Number of bits for secretsharing elements.
void GNUNET_SECRETSHARING_session_destroy(struct GNUNET_SECRETSHARING_Session *s)
Destroy a secret sharing session.
#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.
struct GNUNET_SECRETSHARING_Share * GNUNET_SECRETSHARING_share_read(const void *data, size_t len, size_t *readlen)
Read a share from its binary representation.
#define GNUNET_SECRETSHARING_ELGAMAL_G_HEX
The g-parameter for ElGamal encryption, a generator of the unique size q subgroup of Z_p^*.
void(* GNUNET_SECRETSHARING_DecryptCallback)(void *cls, const struct GNUNET_SECRETSHARING_Plaintext *plaintext)
Called when a decryption has succeeded.
void(* GNUNET_SECRETSHARING_SecretReadyCallback)(void *cls, struct GNUNET_SECRETSHARING_Share *my_share, struct GNUNET_SECRETSHARING_PublicKey *public_key, unsigned int num_ready_peers, const struct GNUNET_PeerIdentity *ready_peers)
Called once the secret has been established with all peers, or the deadline is due.
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_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
messages used for the secretsharing api
static void handle_decrypt_client_error(void *cls, enum GNUNET_MQ_Error error)
Callback invoked when there is an error communicating with the service.
static void handle_session_client_error(void *cls, enum GNUNET_MQ_Error error)
Callback invoked when there is an error communicating with the service.
static gcry_mpi_t elgamal_q
The ElGamal prime field order as libgcrypt mpi.
static int check_secret_ready(void *cls, const struct GNUNET_SECRETSHARING_SecretReadyMessage *m)
Handler invoked with the final result message from secret sharing.
static void handle_decrypt_done(void *cls, const struct GNUNET_SECRETSHARING_DecryptResponseMessage *m)
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.
#define LOG(kind,...)
static void ensure_elgamal_initialized(void)
Function to initialize elgamal_q, elgamal_p and elgamal_g.
static void handle_secret_ready(void *cls, const struct GNUNET_SECRETSHARING_SecretReadyMessage *m)
Handler invoked with the final result message from secret sharing.
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
The identity of the host (wraps the signing key of the peer).
uint32_t c2_bits[1024/8/sizeof(uint32_t)]
uint32_t c1_bits[1024/8/sizeof(uint32_t)]
Handle to cancel a cooperative decryption operation.
struct GNUNET_MQ_Handle * mq
Message queue for client.
GNUNET_SECRETSHARING_DecryptCallback decrypt_cb
Called when the secret sharing is done.
void * decrypt_cls
Closure for decrypt_cb.
Plain, unencrypted message that can be encrypted with a group public key.
Public key of a group sharing a secret.
Notify the client that then threshold secret has been established.
Session that will eventually establish a shared secred between the involved peers and allow encryptio...
void * secret_ready_cls
Closure for secret_ready_cb.
struct GNUNET_MQ_Handle * mq
Message queue for client.
GNUNET_SECRETSHARING_SecretReadyCallback secret_ready_cb
Called when the secret sharing is done.
A share, with all values in in host byte order.
uint16_t num_peers
Peers that have the share.
struct GNUNET_SECRETSHARING_PublicKey public_key
Public key.
Time for absolute times used by GNUnet, in microseconds.