GNUnet  0.10.x
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 
44 
49 
54 };
55 
56 
65 
70 
74  void *decrypt_cls;
75 };
76 
77 
82 static gcry_mpi_t elgamal_q;
83 
88 static gcry_mpi_t elgamal_p;
89 
94 static gcry_mpi_t elgamal_g;
95 
96 
100 static void
102 {
103  if (NULL != elgamal_q)
104  return; /* looks like crypto is already initialized */
105 
106  GNUNET_assert(0 == gcry_mpi_scan(&elgamal_q, GCRYMPI_FMT_HEX,
108  GNUNET_assert(0 == gcry_mpi_scan(&elgamal_p, GCRYMPI_FMT_HEX,
110  GNUNET_assert(0 == gcry_mpi_scan(&elgamal_g, GCRYMPI_FMT_HEX,
112 }
113 
114 
122 static void
124  enum GNUNET_MQ_Error error)
125 {
126  struct GNUNET_SECRETSHARING_Session *s = cls;
127 
128  s->secret_ready_cb(s->secret_ready_cls, NULL, NULL, 0, NULL);
130 }
131 
132 
140 static void
142  enum GNUNET_MQ_Error error)
143 {
144  struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls;
145 
146  dh->decrypt_cb(dh->decrypt_cls, NULL);
148 }
149 
150 
159 static int
162 {
163  /* FIXME: actually check m is well-formed here! */
164  return GNUNET_OK;
165 }
166 
167 
176 static void
179 {
180  struct GNUNET_SECRETSHARING_Session *s = cls;
181  struct GNUNET_SECRETSHARING_Share *share;
182  size_t share_size;
183 
185  "Got secret ready message of size %u\n",
186  ntohs(m->header.size));
187  share_size = ntohs(m->header.size) - sizeof(struct GNUNET_SECRETSHARING_SecretReadyMessage);
188 
189  share = GNUNET_SECRETSHARING_share_read(&m[1],
190  share_size,
191  NULL);
192  GNUNET_assert(NULL != share); // FIXME: this can fail!
193  // should have been checked in #check_secret_ready!
194  // FIXME: below we never check &m[1] is valid!
195  // FIXME: do we leak 'share' here?
197  share, /* FIXME */
198  &share->public_key,
199  share->num_peers,
200  (const struct GNUNET_PeerIdentity *)&m[1]);
201 
203 }
204 
205 
212 void
214 {
215  GNUNET_MQ_destroy(s->mq);
216  s->mq = NULL;
217  GNUNET_free(s);
218 }
219 
220 
239  unsigned int num_peers,
240  const struct GNUNET_PeerIdentity *peers,
241  const struct GNUNET_HashCode *session_id,
244  unsigned int threshold,
246  void *cls)
247 {
250  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
251  GNUNET_MQ_hd_var_size(secret_ready,
254  s),
256  };
257  struct GNUNET_MQ_Envelope *ev;
259 
260  s->mq = GNUNET_CLIENT_connect(cfg,
261  "secretsharing",
262  mq_handlers,
264  s);
265  if (NULL == s->mq)
266  {
267  /* secretsharing not configured correctly */
268  GNUNET_break(0);
269  GNUNET_free(s);
270  return NULL;
271  }
272  s->secret_ready_cb = cb;
273  s->secret_ready_cls = cls;
274  ev = GNUNET_MQ_msg_extra(msg,
275  num_peers * sizeof(struct GNUNET_PeerIdentity),
277 
278  msg->threshold = htons(threshold);
279  msg->num_peers = htons(num_peers);
280  msg->session_id = *session_id;
281  msg->start = GNUNET_TIME_absolute_hton(start);
282  msg->deadline = GNUNET_TIME_absolute_hton(deadline);
283  GNUNET_memcpy(&msg[1], peers, num_peers * sizeof(struct GNUNET_PeerIdentity));
284 
285  GNUNET_MQ_send(s->mq, ev);
286 
288  "Secretsharing session created with %u peers\n",
289  num_peers);
290  return s;
291 }
292 
293 
294 static void
297 {
298  struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls;
299  const struct GNUNET_SECRETSHARING_Plaintext *plaintext;
300 
301  if (m->success == 0)
302  plaintext = NULL;
303  else
304  plaintext = (void *)&m->plaintext;
305  dh->decrypt_cb(dh->decrypt_cls, plaintext);
307 }
308 
309 
325  struct GNUNET_SECRETSHARING_Share *share,
330  void *decrypt_cb_cls)
331 {
334  struct GNUNET_MQ_MessageHandler mq_handlers[] = {
335  GNUNET_MQ_hd_fixed_size(decrypt_done,
338  s),
340  };
341  struct GNUNET_MQ_Envelope *ev;
343  size_t share_size;
344 
345  s->decrypt_cb = decrypt_cb;
346  s->decrypt_cls = decrypt_cb_cls;
347  s->mq = GNUNET_CLIENT_connect(cfg,
348  "secretsharing",
349  mq_handlers,
351  s);
352  if (NULL == s->mq)
353  {
354  GNUNET_free(s);
355  return NULL;
356  }
358  GNUNET_SECRETSHARING_share_write(share, NULL, 0,
359  &share_size));
360 
361  ev = GNUNET_MQ_msg_extra(msg,
362  share_size,
364 
367  &msg[1],
368  share_size,
369  NULL));
370 
371  msg->start = GNUNET_TIME_absolute_hton(start);
372  msg->deadline = GNUNET_TIME_absolute_hton(deadline);
373  msg->ciphertext = *ciphertext;
374 
375  GNUNET_MQ_send(s->mq, ev);
376 
378  "decrypt session created\n");
379  return s;
380 }
381 
382 
383 int
385  int64_t exponent)
386 {
387  int negative;
388  gcry_mpi_t x;
389 
391 
392  GNUNET_assert(NULL != (x = gcry_mpi_new(0)));
393 
394  negative = GNUNET_NO;
395  if (exponent < 0)
396  {
397  negative = GNUNET_YES;
398  exponent = -exponent;
399  }
400 
401  gcry_mpi_set_ui(x, exponent);
402 
403  gcry_mpi_powm(x, elgamal_g, x, elgamal_p);
404 
405  if (GNUNET_YES == negative)
406  {
407  int res;
408  res = gcry_mpi_invm(x, x, elgamal_p);
409  if (0 == res)
410  return GNUNET_SYSERR;
411  }
412 
414  sizeof(struct GNUNET_SECRETSHARING_Plaintext),
415  x);
416 
417  return GNUNET_OK;
418 }
419 
420 
434 int
436  const struct GNUNET_SECRETSHARING_Plaintext *plaintext,
437  struct GNUNET_SECRETSHARING_Ciphertext *result_ciphertext)
438 {
439  /* pubkey */
440  gcry_mpi_t h;
441  /* nonce */
442  gcry_mpi_t y;
443  /* plaintext message */
444  gcry_mpi_t m;
445  /* temp value */
446  gcry_mpi_t tmp;
447 
449 
450  GNUNET_assert(NULL != (h = gcry_mpi_new(0)));
451  GNUNET_assert(NULL != (y = gcry_mpi_new(0)));
452  GNUNET_assert(NULL != (tmp = gcry_mpi_new(0)));
453 
454  GNUNET_CRYPTO_mpi_scan_unsigned(&h, public_key, sizeof *public_key);
455  GNUNET_CRYPTO_mpi_scan_unsigned(&m, plaintext, sizeof *plaintext);
456 
457  // Randomize y such that 0 < y < elgamal_q.
458  // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
459  do
460  {
461  gcry_mpi_randomize(y, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
462  }
463  while ((gcry_mpi_cmp_ui(y, 0) == 0) || (gcry_mpi_cmp(y, elgamal_q) >= 0));
464 
465  // tmp <- g^y
466  gcry_mpi_powm(tmp, elgamal_g, y, elgamal_p);
467  // write tmp to c1
468  GNUNET_CRYPTO_mpi_print_unsigned(&result_ciphertext->c1_bits,
470 
471  // tmp <- h^y
472  gcry_mpi_powm(tmp, h, y, elgamal_p);
473  // tmp <- tmp * m
474  gcry_mpi_mulm(tmp, tmp, m, elgamal_p);
475  // write tmp to c2
476  GNUNET_CRYPTO_mpi_print_unsigned(&result_ciphertext->c2_bits,
478 
479  return GNUNET_OK;
480 }
481 
482 
491 void
493 {
494  GNUNET_MQ_destroy(dh->mq);
495  dh->mq = NULL;
496  GNUNET_free(dh);
497 }
498 
499 /* end of secretsharing_api.c */
struct GNUNET_TIME_AbsoluteNBO start
Start time for communication with the other peers.
Definition: secretsharing.h:60
static unsigned int threshold
What should the threshold for then key be?
struct GNUNET_MessageHeader * msg
Definition: 005.c: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^*...
GNUNET_SECRETSHARING_SecretReadyCallback secret_ready_cb
Called when the secret sharing is done.
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:900
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY.
static void handle_session_client_error(void *cls, enum GNUNET_MQ_Error error)
Callback invoked when there is an error communicating with the service.
struct GNUNET_SECRETSHARING_FieldElement plaintext
Decrypted plaintext.
GNUNET_MQ_Error
Error codes for the queue.
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
struct GNUNET_MQ_Handle * mq
Message queue for client.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
messages used for the secretsharing api
#define GNUNET_SECRETSHARING_ELGAMAL_Q_HEX
The q-parameter for ElGamal encryption, a 1023-bit Sophie Germain prime, q = (p-1)/2.
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:75
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT
Request the decryption of a ciphertext.
A share, with all values in in host byte order.
static struct GNUNET_HashCode session_id
#define GNUNET_NO
Definition: gnunet_common.h:78
void * secret_ready_cls
Closure for secret_ready_cb.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
GNUNET_SECRETSHARING_DecryptCallback decrypt_cb
Called when the secret sharing is done.
static void ensure_elgamal_initialized(void)
Function to initialize elgamal_q, elgamal_p and elgamal_g.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
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.
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.
Public key of a group sharing a secret.
#define GNUNET_SECRETSHARING_ELGAMAL_P_HEX
The q-parameter for ElGamal encryption, a 1024-bit safe prime.
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
void GNUNET_SECRETSHARING_session_destroy(struct GNUNET_SECRETSHARING_Session *s)
Destroy a secret sharing session.
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE
The service succeeded in decrypting a ciphertext.
#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:52
int GNUNET_SECRETSHARING_plaintext_generate_i(struct GNUNET_SECRETSHARING_Plaintext *plaintext, int64_t exponent)
static void handle_secret_ready(void *cls, const struct GNUNET_SECRETSHARING_SecretReadyMessage *m)
Handler invoked with the final result message from secret sharing.
struct GNUNET_TIME_AbsoluteNBO deadline
Deadline for the establishment of the crypto system.
Definition: secretsharing.h:65
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
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_share_write(const struct GNUNET_SECRETSHARING_Share *share, void *buf, size_t buflen, size_t *writelen)
Convert a share to its binary representation.
static struct GNUNET_SECRETSHARING_Ciphertext ciphertext
A 512-bit hashcode.
struct GNUNET_TIME_AbsoluteNBO deadline
Until when should the decryption be finished?
#define LOG(kind,...)
Message handler for a specific message type.
uint16_t threshold
Mininum number of cooperating peers to decrypt a value.
Definition: secretsharing.h:71
static int res
Session that will eventually establish a shared secred between the involved peers and allow encryptio...
uint32_t c1_bits[1024/8/sizeof(uint32_t)]
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:128
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
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.
Handle to cancel a cooperative decryption operation.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static void handle_decrypt_done(void *cls, const struct GNUNET_SECRETSHARING_DecryptResponseMessage *m)
struct GNUNET_TIME_AbsoluteNBO start
Until when should the decryption start?
static unsigned int num_peers
Handle to a message queue.
Definition: mq.c:84
The identity of the host (wraps the signing key of the peer).
uint32_t success
Zero if decryption failed, non-zero if decryption succeeded.
configuration data
Definition: configuration.c:83
static struct CadetPeer * peers
Operation to get peer ids.
Plain, unencrypted message that can be encrypted with a group public key.
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 gcry_mpi_t elgamal_p
Modulus of the prime field used for ElGamal.
uint16_t num_peers
Number of peers at the end of this message.
Definition: secretsharing.h:76
static struct GNUNET_TIME_Absolute deadline
Deadline for all consensuses.
void * decrypt_cls
Closure for decrypt_cb.
Time for absolute times used by GNUnet, in microseconds.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:821
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY
The cryptosystem has been established.
static void decrypt_cb(void *cls, const struct GNUNET_SECRETSHARING_Plaintext *plaintext)
Called when a decryption has succeeded.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:351
#define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE
Establish a new session.
struct GNUNET_MQ_Handle * mq
Message queue for client.
void(* GNUNET_SECRETSHARING_DecryptCallback)(void *cls, const struct GNUNET_SECRETSHARING_Plaintext *plaintext)
Called when a decryption has succeeded.
uint16_t num_peers
Peers that have the share.
struct GNUNET_HashCode session_id
Session ID, will be used for consensus.
Definition: secretsharing.h:55
static int check_secret_ready(void *cls, const struct GNUNET_SECRETSHARING_SecretReadyMessage *m)
Handler invoked with the final result message from secret sharing.
struct GNUNET_SECRETSHARING_PublicKey public_key
Public key.
uint32_t c2_bits[1024/8/sizeof(uint32_t)]
static gcry_mpi_t elgamal_g
Generator for prime field of order &#39;elgamal_q&#39;.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:655
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
Notify the client that then threshold secret has been established.
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.
static gcry_mpi_t elgamal_q
The ElGamal prime field order as libgcrypt mpi.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_SECRETSHARING_ELGAMAL_BITS
Number of bits for secretsharing elements.