GNUnet 0.21.0
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
77};
78
79
84static gcry_mpi_t elgamal_q;
85
90static gcry_mpi_t elgamal_p;
91
96static gcry_mpi_t elgamal_g;
97
98
102static 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
127static 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
145static void
147 enum GNUNET_MQ_Error error)
148{
150
151 dh->decrypt_cb (dh->decrypt_cls, NULL);
153}
154
155
164static int
167{
168 /* FIXME: actually check m is well-formed here! */
169 return GNUNET_OK;
170}
171
172
181static 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
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
218void
220{
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,
250 struct GNUNET_TIME_Absolute deadline,
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;
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;
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
302static void
304 const struct
306{
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
325 struct GNUNET_TIME_Absolute deadline,
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
359 share_size,
361
364 &msg[1],
365 share_size,
366 NULL));
367
370 msg->ciphertext = *ciphertext;
371
372 GNUNET_MQ_send (s->mq, ev);
373
375 "decrypt session created\n");
376 return s;
377}
378
379
380int
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
421int
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
482void
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 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 struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
static char * res
Currently read line or NULL on EOF.
struct GNUNET_CONTAINER_MultiPeerMap * peers
Map from PIDs to struct CadetPeer entries.
static unsigned int num_peers
Number of peers.
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:63
#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.
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.
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_session_destroy(struct GNUNET_SECRETSHARING_Session *s)
Destroy a secret sharing session.
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_P_HEX
The q-parameter for ElGamal encryption, a 1024-bit safe prime.
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.
#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^*.
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)]
struct GNUNET_TIME_AbsoluteNBO deadline
Deadline for the establishment of the crypto system.
Definition: secretsharing.h:67
struct GNUNET_HashCode session_id
Session ID, will be used for consensus.
Definition: secretsharing.h:57
uint16_t threshold
Minimum number of cooperating peers to decrypt a value.
Definition: secretsharing.h:73
struct GNUNET_TIME_AbsoluteNBO deadline
Until when should the decryption be finished?
struct GNUNET_SECRETSHARING_Ciphertext ciphertext
Ciphertext we want to decrypt.
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.