diff options
Diffstat (limited to 'src/secretsharing/secretsharing_api.c')
-rw-r--r-- | src/secretsharing/secretsharing_api.c | 181 |
1 files changed, 177 insertions, 4 deletions
diff --git a/src/secretsharing/secretsharing_api.c b/src/secretsharing/secretsharing_api.c index d2b53acc7..1489a5c45 100644 --- a/src/secretsharing/secretsharing_api.c +++ b/src/secretsharing/secretsharing_api.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "gnunet_util_lib.h" | 27 | #include "gnunet_util_lib.h" |
28 | #include "gnunet_secretsharing_service.h" | 28 | #include "gnunet_secretsharing_service.h" |
29 | #include "secretsharing.h" | 29 | #include "secretsharing.h" |
30 | #include <gcrypt.h> | ||
30 | 31 | ||
31 | 32 | ||
32 | #define LOG(kind,...) GNUNET_log_from (kind, "secretsharing-api",__VA_ARGS__) | 33 | #define LOG(kind,...) GNUNET_log_from (kind, "secretsharing-api",__VA_ARGS__) |
@@ -83,6 +84,40 @@ struct GNUNET_SECRETSHARING_DecryptionHandle | |||
83 | }; | 84 | }; |
84 | 85 | ||
85 | 86 | ||
87 | /** | ||
88 | * The ElGamal prime field order as libgcrypt mpi. | ||
89 | * Initialized in #init_crypto_constants. | ||
90 | */ | ||
91 | static gcry_mpi_t elgamal_q; | ||
92 | |||
93 | /** | ||
94 | * Modulus of the prime field used for ElGamal. | ||
95 | * Initialized in #init_crypto_constants. | ||
96 | */ | ||
97 | static gcry_mpi_t elgamal_p; | ||
98 | |||
99 | /** | ||
100 | * Generator for prime field of order 'elgamal_q'. | ||
101 | * Initialized in #init_crypto_constants. | ||
102 | */ | ||
103 | static gcry_mpi_t elgamal_g; | ||
104 | |||
105 | |||
106 | static void | ||
107 | ensure_elgamal_initialized (void) | ||
108 | { | ||
109 | if (NULL != elgamal_q) | ||
110 | return; /* looks like crypto is already initialized */ | ||
111 | |||
112 | GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX, | ||
113 | GNUNET_SECRETSHARING_ELGAMAL_Q_HEX, 0, NULL)); | ||
114 | GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX, | ||
115 | GNUNET_SECRETSHARING_ELGAMAL_P_HEX, 0, NULL)); | ||
116 | GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX, | ||
117 | GNUNET_SECRETSHARING_ELGAMAL_G_HEX, 0, NULL)); | ||
118 | } | ||
119 | |||
120 | |||
86 | static void | 121 | static void |
87 | handle_session_client_error (void *cls, enum GNUNET_MQ_Error error) | 122 | handle_session_client_error (void *cls, enum GNUNET_MQ_Error error) |
88 | { | 123 | { |
@@ -95,9 +130,12 @@ handle_session_client_error (void *cls, enum GNUNET_MQ_Error error) | |||
95 | static void | 130 | static void |
96 | handle_decrypt_client_error (void *cls, enum GNUNET_MQ_Error error) | 131 | handle_decrypt_client_error (void *cls, enum GNUNET_MQ_Error error) |
97 | { | 132 | { |
98 | GNUNET_assert (0); | 133 | struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls; |
134 | |||
135 | dh->decrypt_cb (dh->decrypt_cls, NULL); | ||
99 | } | 136 | } |
100 | 137 | ||
138 | |||
101 | static void | 139 | static void |
102 | handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg) | 140 | handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg) |
103 | { | 141 | { |
@@ -116,6 +154,18 @@ handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg) | |||
116 | share->num_peers, | 154 | share->num_peers, |
117 | (struct GNUNET_PeerIdentity *) &m[1]); | 155 | (struct GNUNET_PeerIdentity *) &m[1]); |
118 | 156 | ||
157 | GNUNET_SECRETSHARING_session_destroy (session); | ||
158 | } | ||
159 | |||
160 | |||
161 | void | ||
162 | GNUNET_SECRETSHARING_session_destroy (struct GNUNET_SECRETSHARING_Session *session) | ||
163 | { | ||
164 | GNUNET_MQ_destroy (session->mq); | ||
165 | session->mq = NULL; | ||
166 | GNUNET_CLIENT_disconnect (session->client); | ||
167 | session->client = NULL; | ||
168 | GNUNET_free (session); | ||
119 | } | 169 | } |
120 | 170 | ||
121 | 171 | ||
@@ -169,7 +219,20 @@ GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *c | |||
169 | static void | 219 | static void |
170 | handle_decrypt_done (void *cls, const struct GNUNET_MessageHeader *msg) | 220 | handle_decrypt_done (void *cls, const struct GNUNET_MessageHeader *msg) |
171 | { | 221 | { |
172 | GNUNET_assert (0); | 222 | struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls; |
223 | const struct GNUNET_SECRETSHARING_DecryptResponseMessage *m = | ||
224 | (const void *) msg; | ||
225 | |||
226 | const struct GNUNET_SECRETSHARING_Plaintext *plaintext; | ||
227 | |||
228 | if (m->success == 0) | ||
229 | plaintext = NULL; | ||
230 | else | ||
231 | plaintext = (void *) &m->plaintext; | ||
232 | |||
233 | dh->decrypt_cb (dh->decrypt_cls, plaintext); | ||
234 | |||
235 | GNUNET_SECRETSHARING_decrypt_cancel (dh); | ||
173 | } | 236 | } |
174 | 237 | ||
175 | 238 | ||
@@ -187,9 +250,9 @@ handle_decrypt_done (void *cls, const struct GNUNET_MessageHeader *msg) | |||
187 | * @return handle to cancel the operation | 250 | * @return handle to cancel the operation |
188 | */ | 251 | */ |
189 | struct GNUNET_SECRETSHARING_DecryptionHandle * | 252 | struct GNUNET_SECRETSHARING_DecryptionHandle * |
190 | GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg, | 253 | GNUNET_SECRETSHARING_decrypt (const struct GNUNET_CONFIGURATION_Handle *cfg, |
191 | struct GNUNET_SECRETSHARING_Share *share, | 254 | struct GNUNET_SECRETSHARING_Share *share, |
192 | struct GNUNET_SECRETSHARING_Ciphertext *ciphertext, | 255 | const struct GNUNET_SECRETSHARING_Ciphertext *ciphertext, |
193 | struct GNUNET_TIME_Absolute deadline, | 256 | struct GNUNET_TIME_Absolute deadline, |
194 | GNUNET_SECRETSHARING_DecryptCallback decrypt_cb, | 257 | GNUNET_SECRETSHARING_DecryptCallback decrypt_cb, |
195 | void *decrypt_cb_cls) | 258 | void *decrypt_cb_cls) |
@@ -223,6 +286,7 @@ GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
223 | GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &msg[1], share_size, NULL)); | 286 | GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &msg[1], share_size, NULL)); |
224 | 287 | ||
225 | msg->deadline = GNUNET_TIME_absolute_hton (deadline); | 288 | msg->deadline = GNUNET_TIME_absolute_hton (deadline); |
289 | msg->ciphertext = *ciphertext; | ||
226 | 290 | ||
227 | GNUNET_MQ_send (s->mq, ev); | 291 | GNUNET_MQ_send (s->mq, ev); |
228 | 292 | ||
@@ -231,3 +295,112 @@ GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg, | |||
231 | } | 295 | } |
232 | 296 | ||
233 | 297 | ||
298 | int | ||
299 | GNUNET_SECRETSHARING_plaintext_generate_i (struct GNUNET_SECRETSHARING_Plaintext *plaintext, | ||
300 | int64_t exponent) | ||
301 | { | ||
302 | int negative; | ||
303 | gcry_mpi_t x; | ||
304 | |||
305 | ensure_elgamal_initialized (); | ||
306 | |||
307 | GNUNET_assert (NULL != (x = gcry_mpi_new (0))); | ||
308 | |||
309 | negative = GNUNET_NO; | ||
310 | if (exponent < 0) | ||
311 | { | ||
312 | negative = GNUNET_YES; | ||
313 | exponent = -exponent; | ||
314 | } | ||
315 | |||
316 | gcry_mpi_set_ui (x, exponent); | ||
317 | |||
318 | gcry_mpi_powm (x, elgamal_g, x, elgamal_p); | ||
319 | |||
320 | if (GNUNET_YES == negative) | ||
321 | { | ||
322 | int res; | ||
323 | res = gcry_mpi_invm (x, x, elgamal_p); | ||
324 | if (0 == res) | ||
325 | return GNUNET_SYSERR; | ||
326 | } | ||
327 | |||
328 | GNUNET_CRYPTO_mpi_print_unsigned (plaintext, sizeof (struct GNUNET_SECRETSHARING_Plaintext), x); | ||
329 | |||
330 | return GNUNET_OK; | ||
331 | } | ||
332 | |||
333 | |||
334 | /** | ||
335 | * Encrypt a value. This operation is executed locally, no communication is | ||
336 | * necessary. | ||
337 | * | ||
338 | * This is a helper function, encryption can be done soley with a session's public key | ||
339 | * and the crypto system parameters. | ||
340 | * | ||
341 | * @param public_key public key to use for decryption | ||
342 | * @param message message to encrypt | ||
343 | * @param message_size number of bytes in @a message | ||
344 | * @param result_ciphertext pointer to store the resulting ciphertext | ||
345 | * @return #GNUNET_YES on succes, #GNUNET_SYSERR if the message is invalid (invalid range) | ||
346 | */ | ||
347 | int | ||
348 | GNUNET_SECRETSHARING_encrypt (const struct GNUNET_SECRETSHARING_PublicKey *public_key, | ||
349 | const struct GNUNET_SECRETSHARING_Plaintext *plaintext, | ||
350 | struct GNUNET_SECRETSHARING_Ciphertext *result_ciphertext) | ||
351 | { | ||
352 | /* pubkey */ | ||
353 | gcry_mpi_t h; | ||
354 | /* nonce */ | ||
355 | gcry_mpi_t y; | ||
356 | /* plaintext message */ | ||
357 | gcry_mpi_t m; | ||
358 | /* temp value */ | ||
359 | gcry_mpi_t tmp; | ||
360 | |||
361 | ensure_elgamal_initialized (); | ||
362 | |||
363 | GNUNET_assert (NULL != (h = gcry_mpi_new (0))); | ||
364 | GNUNET_assert (NULL != (y = gcry_mpi_new (0))); | ||
365 | GNUNET_assert (NULL != (tmp = gcry_mpi_new (0))); | ||
366 | |||
367 | GNUNET_CRYPTO_mpi_scan_unsigned (&h, public_key, sizeof *public_key); | ||
368 | GNUNET_CRYPTO_mpi_scan_unsigned (&m, plaintext, sizeof *plaintext); | ||
369 | |||
370 | // Randomize y such that 0 < y < elgamal_q. | ||
371 | // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1. | ||
372 | do | ||
373 | { | ||
374 | gcry_mpi_randomize (y, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM); | ||
375 | } while ((gcry_mpi_cmp_ui (y, 0) == 0) || (gcry_mpi_cmp (y, elgamal_q) >= 0)); | ||
376 | |||
377 | // tmp <- g^y | ||
378 | gcry_mpi_powm (tmp, elgamal_g, y, elgamal_p); | ||
379 | // write tmp to c1 | ||
380 | GNUNET_CRYPTO_mpi_print_unsigned (&result_ciphertext->c1_bits, | ||
381 | GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp); | ||
382 | |||
383 | // tmp <- h^y | ||
384 | gcry_mpi_powm (tmp, h, y, elgamal_p); | ||
385 | // tmp <- tmp * m | ||
386 | gcry_mpi_mulm (tmp, tmp, m, elgamal_p); | ||
387 | // write tmp to c2 | ||
388 | GNUNET_CRYPTO_mpi_print_unsigned (&result_ciphertext->c2_bits, | ||
389 | GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp); | ||
390 | |||
391 | return GNUNET_OK; | ||
392 | } | ||
393 | |||
394 | |||
395 | void | ||
396 | GNUNET_SECRETSHARING_decrypt_cancel (struct GNUNET_SECRETSHARING_DecryptionHandle *h) | ||
397 | { | ||
398 | GNUNET_MQ_destroy (h->mq); | ||
399 | h->mq = NULL; | ||
400 | GNUNET_CLIENT_disconnect (h->client); | ||
401 | h->client = NULL; | ||
402 | GNUNET_free (h); | ||
403 | } | ||
404 | |||
405 | |||
406 | |||