aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2014-01-20 19:08:47 +0000
committerFlorian Dold <florian.dold@gmail.com>2014-01-20 19:08:47 +0000
commit29517cf1e5cb2e2a92c97f458ba4d3fe6716b1ee (patch)
tree1cd922f43818800d7279f16f8b9496a6016338f0 /src
parent95b657e52e52523cc7080406221896ed31327052 (diff)
downloadgnunet-29517cf1e5cb2e2a92c97f458ba4d3fe6716b1ee.tar.gz
gnunet-29517cf1e5cb2e2a92c97f458ba4d3fe6716b1ee.zip
- make mpi scan/print public
- secretsharing key generation and decryption fixed
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_crypto_lib.h30
-rw-r--r--src/include/gnunet_secretsharing_service.h102
-rwxr-xr-xsrc/secretsharing/gnunet-secretsharing-profiler.c265
-rw-r--r--src/secretsharing/gnunet-service-secretsharing.c506
-rw-r--r--src/secretsharing/secretsharing.h6
-rw-r--r--src/secretsharing/secretsharing_api.c181
-rw-r--r--src/secretsharing/secretsharing_common.c3
-rw-r--r--src/secretsharing/test_secretsharing.conf2
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/crypto_ecc.c100
-rw-r--r--src/util/crypto_mpi.c132
11 files changed, 1001 insertions, 327 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index a82b2fdd6..a5ee98092 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -55,6 +55,7 @@ struct GNUNET_PeerIdentity;
55 55
56#include "gnunet_common.h" 56#include "gnunet_common.h"
57#include "gnunet_scheduler_lib.h" 57#include "gnunet_scheduler_lib.h"
58#include <gcrypt.h>
58 59
59 60
60/** 61/**
@@ -1232,6 +1233,35 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey
1232 struct GNUNET_CRYPTO_EcdsaPublicKey *result); 1233 struct GNUNET_CRYPTO_EcdsaPublicKey *result);
1233 1234
1234 1235
1236/**
1237 * Output the given MPI value to the given buffer in network
1238 * byte order. The MPI @a val may not be negative.
1239 *
1240 * @param buf where to output to
1241 * @param size number of bytes in @a buf
1242 * @param val value to write to @a buf
1243 */
1244void
1245GNUNET_CRYPTO_mpi_print_unsigned (void *buf,
1246 size_t size,
1247 gcry_mpi_t val);
1248
1249
1250/**
1251 * Convert data buffer into MPI value.
1252 * The buffer is interpreted as network
1253 * byte order, unsigned integer.
1254 *
1255 * @param result where to store MPI value (allocated)
1256 * @param data raw data (GCRYMPI_FMT_USG)
1257 * @param size number of bytes in @a data
1258 */
1259void
1260GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result,
1261 const void *data,
1262 size_t size);
1263
1264
1235#if 0 /* keep Emacsens' auto-indent happy */ 1265#if 0 /* keep Emacsens' auto-indent happy */
1236{ 1266{
1237#endif 1267#endif
diff --git a/src/include/gnunet_secretsharing_service.h b/src/include/gnunet_secretsharing_service.h
index 8569e15ea..1524c79fe 100644
--- a/src/include/gnunet_secretsharing_service.h
+++ b/src/include/gnunet_secretsharing_service.h
@@ -43,13 +43,53 @@ extern "C"
43 43
44 44
45/** 45/**
46 * Number of bits for secretsharing keys. 46 * Number of bits for secretsharing elements.
47 * Must be smaller than the Pallier key size used internally 47 * Must be smaller than the Pallier key size used internally
48 * by the secretsharing service. 48 * by the secretsharing service.
49 * When changing this value, other internal parameters must also 49 * When changing this value, other internal parameters must also
50 * be adjusted. 50 * be adjusted.
51 */ 51 */
52#define GNUNET_SECRETSHARING_KEY_BITS 1024 52#define GNUNET_SECRETSHARING_ELGAMAL_BITS 1024
53
54
55/**
56 * The q-parameter for ElGamal encryption, a 1024-bit safe prime.
57 */
58#define GNUNET_SECRETSHARING_ELGAMAL_P_HEX \
59 "0x08a347d3d69e8b2dd7d1b12a08dfbccbebf4ca" \
60 "6f4269a0814e158a34312964d946b3ef22882317" \
61 "2bcf30fc08f772774cb404f9bc002a6f66b09a79" \
62 "d810d67c4f8cb3bedc6060e3c8ef874b1b64df71" \
63 "6c7d2b002da880e269438d5a776e6b5f253c8df5" \
64 "6a16b1c7ce58def07c03db48238aadfc52a354a2" \
65 "7ed285b0c1675cad3f3"
66
67/**
68 * The q-parameter for ElGamal encryption,
69 * a 1023-bit Sophie Germain prime, q = (p-1)/2
70 */
71#define GNUNET_SECRETSHARING_ELGAMAL_Q_HEX \
72 "0x0451a3e9eb4f4596ebe8d895046fde65f5fa65" \
73 "37a134d040a70ac51a1894b26ca359f79144118b" \
74 "95e7987e047bb93ba65a027cde001537b3584d3c" \
75 "ec086b3e27c659df6e303071e477c3a58db26fb8" \
76 "b63e958016d4407134a1c6ad3bb735af929e46fa" \
77 "b50b58e3e72c6f783e01eda411c556fe2951aa51" \
78 "3f6942d860b3ae569f9"
79
80/**
81 * The g-parameter for ElGamal encryption,
82 * a generator of the unique size q subgroup of Z_p^*
83 */
84#define GNUNET_SECRETSHARING_ELGAMAL_G_HEX \
85 "0x05c00c36d2e822950087ef09d8252994adc4e4" \
86 "8fe3ec70269f035b46063aff0c99b633fd64df43" \
87 "02442e1914c829a41505a275438871f365e91c12" \
88 "3d5303ef9e90f4b8cb89bf86cc9b513e74a72634" \
89 "9cfd9f953674fab5d511e1c078fc72d72b34086f" \
90 "c82b4b951989eb85325cb203ff98df76bc366bba" \
91 "1d7024c3650f60d0da"
92
53 93
54 94
55/** 95/**
@@ -77,7 +117,7 @@ struct GNUNET_SECRETSHARING_DecryptionHandle;
77 */ 117 */
78struct GNUNET_SECRETSHARING_PublicKey 118struct GNUNET_SECRETSHARING_PublicKey
79{ 119{
80 uint32_t bits[GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)]; 120 uint32_t bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)];
81}; 121};
82 122
83 123
@@ -86,21 +126,23 @@ struct GNUNET_SECRETSHARING_PublicKey
86 */ 126 */
87struct GNUNET_SECRETSHARING_Ciphertext 127struct GNUNET_SECRETSHARING_Ciphertext
88{ 128{
89 uint32_t c1_bits[GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)]; 129 uint32_t c1_bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)];
90 uint32_t c2_bits[GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)]; 130 uint32_t c2_bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)];
91}; 131};
92 132
93 133
94/** 134/**
95 * Plain, unencrypted message that can be encrypted with 135 * Plain, unencrypted message that can be encrypted with
96 * a group public key. 136 * a group public key.
137 * Note that we are not operating in GF(2^n), thus not every
138 * bit pattern is a valid plain text.
97 */ 139 */
98struct GNUNET_SECRETSHARING_Message 140struct GNUNET_SECRETSHARING_Plaintext
99{ 141{
100 /** 142 /**
101 * Value of the message. 143 * Value of the message.
102 */ 144 */
103 uint32_t bits[GNUNET_SECRETSHARING_KEY_BITS / 8 / sizeof (uint32_t)]; 145 uint32_t bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)];
104}; 146};
105 147
106 148
@@ -113,6 +155,8 @@ struct GNUNET_SECRETSHARING_Message
113 * 155 *
114 * If the secret sharing failed, num_ready_peers is 0 and my_share and public_key is NULL. 156 * If the secret sharing failed, num_ready_peers is 0 and my_share and public_key is NULL.
115 * 157 *
158 * After this callback has been called, the secretsharing session will be invalid.
159 *
116 * @param cls closure 160 * @param cls closure
117 * @param my_share the share of this peer 161 * @param my_share the share of this peer
118 * @param public_key public key of the session 162 * @param public_key public key of the session
@@ -121,10 +165,10 @@ struct GNUNET_SECRETSHARING_Message
121 * the shared secret 165 * the shared secret
122 */ 166 */
123typedef void (*GNUNET_SECRETSHARING_SecretReadyCallback) (void *cls, 167typedef void (*GNUNET_SECRETSHARING_SecretReadyCallback) (void *cls,
124 const struct GNUNET_SECRETSHARING_Share *my_share, 168 struct GNUNET_SECRETSHARING_Share *my_share,
125 const struct GNUNET_SECRETSHARING_PublicKey *public_key, 169 struct GNUNET_SECRETSHARING_PublicKey *public_key,
126 unsigned int num_ready_peers, 170 unsigned int num_ready_peers,
127 const struct GNUNET_PeerIdentity *ready_peers); 171 struct GNUNET_PeerIdentity *ready_peers);
128 172
129 173
130/** 174/**
@@ -135,8 +179,7 @@ typedef void (*GNUNET_SECRETSHARING_SecretReadyCallback) (void *cls,
135 * @param data_size number of bytes in @a data 179 * @param data_size number of bytes in @a data
136 */ 180 */
137typedef void (*GNUNET_SECRETSHARING_DecryptCallback) (void *cls, 181typedef void (*GNUNET_SECRETSHARING_DecryptCallback) (void *cls,
138 const void *data, 182 const struct GNUNET_SECRETSHARING_Plaintext *plaintext);
139 size_t data_size);
140 183
141 184
142/** 185/**
@@ -165,21 +208,13 @@ GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *c
165 208
166 209
167/** 210/**
168 * Destroy a secret share.
169 *
170 * @param share secret share to destroy
171 */
172void
173GNUNET_SECRETSHARING_share_destroy (const struct GNUNET_SECRETSHARING_Share *share);
174
175
176/**
177 * Destroy a secret sharing session. 211 * Destroy a secret sharing session.
212 * The secret ready callback will not be called.
178 * 213 *
179 * @param session session to destroy 214 * @param session session to destroy
180 */ 215 */
181void 216void
182GNUNET_SECRETSHARING_destroy_session (struct GNUNET_SECRETSHARING_Session *session); 217GNUNET_SECRETSHARING_session_destroy (struct GNUNET_SECRETSHARING_Session *session);
183 218
184 219
185/** 220/**
@@ -196,9 +231,8 @@ GNUNET_SECRETSHARING_destroy_session (struct GNUNET_SECRETSHARING_Session *sessi
196 * @return #GNUNET_YES on succes, #GNUNET_SYSERR if the message is invalid (invalid range) 231 * @return #GNUNET_YES on succes, #GNUNET_SYSERR if the message is invalid (invalid range)
197 */ 232 */
198int 233int
199GNUNET_SECRETSHARING_encrypt (struct GNUNET_SECRETSHARING_PublicKey *public_key, 234GNUNET_SECRETSHARING_encrypt (const struct GNUNET_SECRETSHARING_PublicKey *public_key,
200 const void *message, 235 const struct GNUNET_SECRETSHARING_Plaintext *plaintext,
201 size_t message_size,
202 struct GNUNET_SECRETSHARING_Ciphertext *result_ciphertext); 236 struct GNUNET_SECRETSHARING_Ciphertext *result_ciphertext);
203 237
204 238
@@ -218,9 +252,9 @@ GNUNET_SECRETSHARING_encrypt (struct GNUNET_SECRETSHARING_PublicKey *public_key,
218 * @return handle to cancel the operation 252 * @return handle to cancel the operation
219 */ 253 */
220struct GNUNET_SECRETSHARING_DecryptionHandle * 254struct GNUNET_SECRETSHARING_DecryptionHandle *
221GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg, 255GNUNET_SECRETSHARING_decrypt (const struct GNUNET_CONFIGURATION_Handle *cfg,
222 struct GNUNET_SECRETSHARING_Share *share, 256 struct GNUNET_SECRETSHARING_Share *share,
223 struct GNUNET_SECRETSHARING_Ciphertext *ciphertext, 257 const struct GNUNET_SECRETSHARING_Ciphertext *ciphertext,
224 struct GNUNET_TIME_Absolute deadline, 258 struct GNUNET_TIME_Absolute deadline,
225 GNUNET_SECRETSHARING_DecryptCallback decrypt_cb, 259 GNUNET_SECRETSHARING_DecryptCallback decrypt_cb,
226 void *decrypt_cb_cls); 260 void *decrypt_cb_cls);
@@ -267,6 +301,20 @@ GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share
267 void *buf, size_t buflen, size_t *writelen); 301 void *buf, size_t buflen, size_t *writelen);
268 302
269 303
304void
305GNUNET_SECRETSHARING_share_destroy (struct GNUNET_SECRETSHARING_Share *share);
306
307
308int
309GNUNET_SECRETSHARING_plaintext_generate (struct GNUNET_SECRETSHARING_Plaintext *plaintext,
310 gcry_mpi_t exponent);
311
312int
313GNUNET_SECRETSHARING_plaintext_generate_i (struct GNUNET_SECRETSHARING_Plaintext *plaintext,
314 int64_t exponent);
315
316
317
270 318
271#if 0 /* keep Emacsens' auto-indent happy */ 319#if 0 /* keep Emacsens' auto-indent happy */
272{ 320{
diff --git a/src/secretsharing/gnunet-secretsharing-profiler.c b/src/secretsharing/gnunet-secretsharing-profiler.c
index 01eb49a2d..b718e8a27 100755
--- a/src/secretsharing/gnunet-secretsharing-profiler.c
+++ b/src/secretsharing/gnunet-secretsharing-profiler.c
@@ -28,17 +28,48 @@
28#include "gnunet_secretsharing_service.h" 28#include "gnunet_secretsharing_service.h"
29#include "gnunet_testbed_service.h" 29#include "gnunet_testbed_service.h"
30 30
31/**
32 * How many peers should participate in the key generation?
33 */
31static unsigned int num_peers = 3; 34static unsigned int num_peers = 3;
32 35
36/**
37 * What should the threshold for then key be?
38 */
33static unsigned int threshold = 2; 39static unsigned int threshold = 2;
34 40
41/**
42 * Should we try to decrypt a value after the key generation?
43 */
44static unsigned int decrypt = GNUNET_NO;
45
46/**
47 * When would we like to see the operation finished?
48 */
35static struct GNUNET_TIME_Relative timeout; 49static struct GNUNET_TIME_Relative timeout;
36 50
51/**
52 * Handles for secretsharing sessions.
53 */
37static struct GNUNET_SECRETSHARING_Session **session_handles; 54static struct GNUNET_SECRETSHARING_Session **session_handles;
38 55
56static struct GNUNET_SECRETSHARING_DecryptionHandle **decrypt_handles;
57
58/**
59 * Shares we got from the distributed key generation.
60 */
61static struct GNUNET_SECRETSHARING_Share **shares;
62
63static struct GNUNET_SECRETSHARING_PublicKey common_pubkey;
64
65/**
66 * ???
67 */
39static struct GNUNET_TESTBED_Operation **testbed_operations; 68static struct GNUNET_TESTBED_Operation **testbed_operations;
40 69
41static unsigned int num_connected_handles; 70static unsigned int num_connected_sessions;
71
72static unsigned int num_connected_decrypt;
42 73
43static struct GNUNET_TESTBED_Peer **peers; 74static struct GNUNET_TESTBED_Peer **peers;
44 75
@@ -46,10 +77,18 @@ static struct GNUNET_PeerIdentity *peer_ids;
46 77
47static unsigned int num_retrieved_peer_ids; 78static unsigned int num_retrieved_peer_ids;
48 79
80static unsigned int num_generated;
81
82static unsigned int num_decrypted;
83
49static struct GNUNET_HashCode session_id; 84static struct GNUNET_HashCode session_id;
50 85
51static int verbose; 86static int verbose;
52 87
88struct GNUNET_SECRETSHARING_Plaintext reference_plaintext;
89
90struct GNUNET_SECRETSHARING_Ciphertext ciphertext;
91
53 92
54/** 93/**
55 * Signature of the event handler function called by the 94 * Signature of the event handler function called by the
@@ -76,10 +115,47 @@ controller_cb (void *cls,
76 * operation has executed successfully. 115 * operation has executed successfully.
77 */ 116 */
78static void 117static void
79connect_complete (void *cls, 118session_connect_complete (void *cls,
80 struct GNUNET_TESTBED_Operation *op, 119 struct GNUNET_TESTBED_Operation *op,
81 void *ca_result, 120 void *ca_result,
82 const char *emsg) 121 const char *emsg)
122{
123
124 if (NULL != emsg)
125 {
126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127 "testbed connect emsg: %s\n",
128 emsg);
129 GNUNET_assert (0);
130 }
131
132 num_connected_sessions++;
133
134 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
135 "dkg: session connect complete\n");
136
137 if (num_connected_sessions == num_peers)
138 {
139 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
140 "dkg: all peers connected\n");
141 }
142}
143
144
145/**
146 * Callback to be called when a service connect operation is completed
147 *
148 * @param cls the callback closure from functions generating an operation
149 * @param op the operation that has been finished
150 * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter()
151 * @param emsg error message in case the operation has failed; will be NULL if
152 * operation has executed successfully.
153 */
154static void
155decrypt_connect_complete (void *cls,
156 struct GNUNET_TESTBED_Operation *op,
157 void *ca_result,
158 const char *emsg)
83{ 159{
84 160
85 if (NULL != emsg) 161 if (NULL != emsg)
@@ -90,35 +166,164 @@ connect_complete (void *cls,
90 GNUNET_assert (0); 166 GNUNET_assert (0);
91 } 167 }
92 168
93 num_connected_handles++; 169 num_connected_decrypt++;
94 170
95 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 171 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
96 "connect complete\n"); 172 "decrypt: session connect complete\n");
97 173
98 if (num_connected_handles == num_peers) 174 if (num_connected_decrypt == num_peers)
99 { 175 {
100 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 176 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
101 "all peers connected\n"); 177 "decrypt: all peers connected\n");
178 }
179}
180
181
182/**
183 * Called when a decryption has succeeded.
184 *
185 * @param cls Plaintext
186 * @param plaintext Plaintext
187 */
188static void decrypt_cb (void *cls,
189 const struct GNUNET_SECRETSHARING_Plaintext *plaintext)
190{
191 struct GNUNET_SECRETSHARING_DecryptionHandle **dhp = cls;
192 unsigned int n = dhp - decrypt_handles;
193 num_decrypted++;
194
195 *dhp = NULL;
196
197 if (NULL == plaintext)
198 {
199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt failed for peer %u\n", n);
200 return;
201 }
202 else if (0 == memcmp (&reference_plaintext, plaintext, sizeof (struct GNUNET_SECRETSHARING_Plaintext)))
203 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypt got correct result for peer %u\n", n);
204 else
205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt got wrong result for peer %u\n", n);
206
207 if (num_decrypted == num_peers)
208 {
209 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "every peer decrypted\n");
210 GNUNET_SCHEDULER_shutdown ();
211 }
212
213 *dhp = NULL;
214}
215
216
217
218/**
219 * Adapter function called to establish a connection to
220 * a service.
221 *
222 * @param cls closure
223 * @param cfg configuration of the peer to connect to; will be available until
224 * GNUNET_TESTBED_operation_done() is called on the operation returned
225 * from GNUNET_TESTBED_service_connect()
226 * @return service handle to return in 'op_result', NULL on error
227 */
228static void *
229decrypt_connect_adapter (void *cls,
230 const struct GNUNET_CONFIGURATION_Handle *cfg)
231{
232 struct GNUNET_SECRETSHARING_DecryptionHandle **hp = cls;
233 unsigned int n = hp - decrypt_handles;
234
235 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
236 "decrypt connect adapter, %d peers\n",
237 num_peers);
238 *hp = GNUNET_SECRETSHARING_decrypt (cfg, shares[n], &ciphertext,
239 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES),
240 decrypt_cb,
241 hp);
242
243 return *hp;
244}
245
246
247/**
248 * Adapter function called to destroy a connection to
249 * a service.
250 *
251 * @param cls closure
252 * @param op_result service handle returned from the connect adapter
253 */
254static void
255decrypt_disconnect_adapter(void *cls, void *op_result)
256{
257 struct GNUNET_SECRETSHARING_DecryptionHandle **dh = cls;
258 if (NULL != *dh)
259 {
260 GNUNET_SECRETSHARING_decrypt_cancel (*dh);
261 *dh = NULL;
102 } 262 }
103} 263}
104 264
105 265
106static void 266static void
107secret_ready_cb (void *cls, 267secret_ready_cb (void *cls,
108 const struct GNUNET_SECRETSHARING_Share *my_share, 268 struct GNUNET_SECRETSHARING_Share *my_share,
109 const struct GNUNET_SECRETSHARING_PublicKey *public_key, 269 struct GNUNET_SECRETSHARING_PublicKey *public_key,
110 unsigned int num_ready_peers, 270 unsigned int num_ready_peers,
111 const struct GNUNET_PeerIdentity *ready_peers) 271 struct GNUNET_PeerIdentity *ready_peers)
112{ 272{
113 struct GNUNET_SECRETSHARING_Session **sp = cls; 273 struct GNUNET_SECRETSHARING_Session **sp = cls;
114 unsigned int n = sp - session_handles; 274 unsigned int n = sp - session_handles;
115 if (NULL == my_share || NULL == public_key) 275 char pubkey_str[1024];
276 char *ret;
277
278 num_generated++;
279 *sp = NULL;
280 shares[n] = my_share;
281 if (NULL == my_share)
116 { 282 {
117 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "key generation failed for peer #%u\n", n); 283 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "key generation failed for peer #%u\n", n);
118 return;
119 } 284 }
120 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "secret ready for peer #%u\n", n); 285 else
121 // FIXME: end profiler or try decryption if all secrets are ready 286 {
287 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "secret ready for peer #%u\n", n);
288 /* we're the first to get the key -> store it */
289 if (num_generated == 1)
290 {
291 common_pubkey = *public_key;
292 }
293 else if (0 != memcmp (public_key, &common_pubkey, sizeof (struct GNUNET_SECRETSHARING_PublicKey)))
294 {
295 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "generated public keys do not match\n");
296 GNUNET_SCHEDULER_shutdown ();
297 return;
298 }
299 }
300
301 ret = GNUNET_STRINGS_data_to_string (public_key, sizeof *public_key, pubkey_str, 1024);
302 GNUNET_assert (NULL != ret);
303 *ret = '\0';
304 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "key generation successful for peer #%u, pubkey %s\n", n,
305 pubkey_str);
306
307 // FIXME: destroy testbed operation
308
309 if (num_generated == num_peers)
310 {
311 int i;
312 if (GNUNET_NO == decrypt)
313 {
314 GNUNET_SCHEDULER_shutdown ();
315 return;
316 }
317
318 // compute g^42
319 GNUNET_SECRETSHARING_plaintext_generate_i (&reference_plaintext, 42);
320 GNUNET_SECRETSHARING_encrypt (&common_pubkey, &reference_plaintext, &ciphertext);
321
322 // FIXME: store the ops somewhere!
323 for (i = 0; i < num_peers; i++)
324 GNUNET_TESTBED_service_connect (NULL, peers[i], "secretsharing", &decrypt_connect_complete, NULL,
325 &decrypt_connect_adapter, &decrypt_disconnect_adapter, &decrypt_handles[i]);
326 }
122} 327}
123 328
124 329
@@ -133,8 +338,8 @@ secret_ready_cb (void *cls,
133 * @return service handle to return in 'op_result', NULL on error 338 * @return service handle to return in 'op_result', NULL on error
134 */ 339 */
135static void * 340static void *
136connect_adapter (void *cls, 341session_connect_adapter (void *cls,
137 const struct GNUNET_CONFIGURATION_Handle *cfg) 342 const struct GNUNET_CONFIGURATION_Handle *cfg)
138{ 343{
139 struct GNUNET_SECRETSHARING_Session **sp = cls; 344 struct GNUNET_SECRETSHARING_Session **sp = cls;
140 345
@@ -152,6 +357,7 @@ connect_adapter (void *cls,
152} 357}
153 358
154 359
360
155/** 361/**
156 * Adapter function called to destroy a connection to 362 * Adapter function called to destroy a connection to
157 * a service. 363 * a service.
@@ -160,9 +366,14 @@ connect_adapter (void *cls,
160 * @param op_result service handle returned from the connect adapter 366 * @param op_result service handle returned from the connect adapter
161 */ 367 */
162static void 368static void
163disconnect_adapter(void *cls, void *op_result) 369session_disconnect_adapter (void *cls, void *op_result)
164{ 370{
165 /* FIXME: what to do here? */ 371 struct GNUNET_SECRETSHARING_Session **sp = cls;
372 if (NULL != *sp)
373 {
374 GNUNET_SECRETSHARING_session_destroy (*sp);
375 *sp = NULL;
376 }
166} 377}
167 378
168 379
@@ -195,8 +406,8 @@ peer_info_cb (void *cb_cls,
195 if (num_retrieved_peer_ids == num_peers) 406 if (num_retrieved_peer_ids == num_peers)
196 for (i = 0; i < num_peers; i++) 407 for (i = 0; i < num_peers; i++)
197 testbed_operations[i] = 408 testbed_operations[i] =
198 GNUNET_TESTBED_service_connect (NULL, peers[i], "secretsharing", connect_complete, NULL, 409 GNUNET_TESTBED_service_connect (NULL, peers[i], "secretsharing", session_connect_complete, NULL,
199 connect_adapter, disconnect_adapter, &session_handles[i]); 410 session_connect_adapter, session_disconnect_adapter, &session_handles[i]);
200 } 411 }
201 else 412 else
202 { 413 {
@@ -238,8 +449,11 @@ test_master (void *cls,
238 449
239 peer_ids = GNUNET_malloc (num_peers * sizeof (struct GNUNET_PeerIdentity)); 450 peer_ids = GNUNET_malloc (num_peers * sizeof (struct GNUNET_PeerIdentity));
240 451
241 session_handles = GNUNET_malloc (num_peers * sizeof (struct GNUNET_SECRETSHARING_Session *)); 452 session_handles = GNUNET_new_array (num_peers, struct GNUNET_SECRETSHARING_Session *);
242 testbed_operations = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); 453 decrypt_handles = GNUNET_new_array (num_peers, struct GNUNET_SECRETSHARING_DecryptionHandle *);
454 testbed_operations = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *);
455 shares = GNUNET_new_array (num_peers, struct GNUNET_SECRETSHARING_Share *);
456
243 457
244 for (i = 0; i < num_peers; i++) 458 for (i = 0; i < num_peers; i++)
245 GNUNET_TESTBED_peer_get_information (peers[i], 459 GNUNET_TESTBED_peer_get_information (peers[i],
@@ -305,6 +519,9 @@ main (int argc, char **argv)
305 { 'k', "threshold", NULL, 519 { 'k', "threshold", NULL,
306 gettext_noop ("threshold"), 520 gettext_noop ("threshold"),
307 GNUNET_YES, &GNUNET_GETOPT_set_uint, &threshold }, 521 GNUNET_YES, &GNUNET_GETOPT_set_uint, &threshold },
522 { 'd', "decrypt", NULL,
523 gettext_noop ("also profile decryption"),
524 GNUNET_NO, &GNUNET_GETOPT_set_one, &decrypt },
308 { 'V', "verbose", NULL, 525 { 'V', "verbose", NULL,
309 gettext_noop ("be more verbose (print received values)"), 526 gettext_noop ("be more verbose (print received values)"),
310 GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose }, 527 GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose },
diff --git a/src/secretsharing/gnunet-service-secretsharing.c b/src/secretsharing/gnunet-service-secretsharing.c
index 38dabc3a8..1fcc4e351 100644
--- a/src/secretsharing/gnunet-service-secretsharing.c
+++ b/src/secretsharing/gnunet-service-secretsharing.c
@@ -33,6 +33,9 @@
33#include <gcrypt.h> 33#include <gcrypt.h>
34 34
35 35
36#define EXTRA_CHECKS 1
37
38
36/** 39/**
37 * Info about a peer in a key generation session. 40 * Info about a peer in a key generation session.
38 */ 41 */
@@ -45,6 +48,7 @@ struct KeygenPeerInfo
45 48
46 /** 49 /**
47 * The peer's paillier public key. 50 * The peer's paillier public key.
51 * Freshly generated for each keygen session.
48 */ 52 */
49 gcry_mpi_t paillier_n; 53 gcry_mpi_t paillier_n;
50 54
@@ -92,7 +96,7 @@ struct DecryptPeerInfo
92 * Original index in the key generation round. 96 * Original index in the key generation round.
93 * Necessary for computing the lagrange coefficients. 97 * Necessary for computing the lagrange coefficients.
94 */ 98 */
95 unsigned int real_index; 99 unsigned int original_index;
96 100
97 /** 101 /**
98 * Set to the partial decryption of 102 * Set to the partial decryption of
@@ -323,52 +327,11 @@ static struct GNUNET_SERVER_Handle *srv;
323 327
324 328
325/** 329/**
326 * If target != size, move @a target bytes to the end of the size-sized
327 * buffer and zero out the first @a target - @a size bytes.
328 *
329 * @param buf original buffer
330 * @param size number of bytes in @a buf
331 * @param target target size of the buffer
332 */
333static void
334adjust (unsigned char *buf,
335 size_t size,
336 size_t target)
337{
338 if (size < target)
339 {
340 memmove (&buf[target - size], buf, size);
341 memset (buf, 0, target - size);
342 }
343}
344
345
346/**
347 * Print an MPI to a buffer, so that is contains the MPI's
348 * the little endian representation of size @a size.
349 *
350 * @param buf buffer to write to
351 * @param x mpi to be written in the buffer
352 * @param size how many bytes should the little endian binary
353 * representation of @a x use?
354 */
355static void
356print_mpi_fixed (void *buf, gcry_mpi_t x, size_t size)
357{
358 size_t written;
359 GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG,
360 buf, size, &written,
361 x));
362 adjust (buf, written, size);
363}
364
365
366/**
367 * Get the peer info belonging to a peer identity in a keygen session. 330 * Get the peer info belonging to a peer identity in a keygen session.
368 * 331 *
369 * @param ks the keygen session 332 * @param ks The keygen session.
370 * @param peer the peer identity 333 * @param peer The peer identity.
371 * @return the keygen peer info, or NULL if the peer could not be found 334 * @return The Keygen peer info, or NULL if the peer could not be found.
372 */ 335 */
373static struct KeygenPeerInfo * 336static struct KeygenPeerInfo *
374get_keygen_peer_info (const struct KeygenSession *ks, 337get_keygen_peer_info (const struct KeygenSession *ks,
@@ -385,13 +348,13 @@ get_keygen_peer_info (const struct KeygenSession *ks,
385/** 348/**
386 * Get the peer info belonging to a peer identity in a decrypt session. 349 * Get the peer info belonging to a peer identity in a decrypt session.
387 * 350 *
388 * @param ks the decrypt session 351 * @param ks The decrypt session.
389 * @param peer the peer identity 352 * @param peer The peer identity.
390 * @return the decrypt peer info, or NULL if the peer could not be found 353 * @return The decrypt peer info, or NULL if the peer could not be found.
391 */ 354 */
392static struct DecryptPeerInfo * 355static struct DecryptPeerInfo *
393get_decrypt_peer_info (const struct DecryptSession *ds, 356get_decrypt_peer_info (const struct DecryptSession *ds,
394 const struct GNUNET_PeerIdentity *peer) 357 const struct GNUNET_PeerIdentity *peer)
395{ 358{
396 unsigned int i; 359 unsigned int i;
397 for (i = 0; i < ds->share->num_peers; i++) 360 for (i = 0; i < ds->share->num_peers; i++)
@@ -428,8 +391,8 @@ time_between (struct GNUNET_TIME_Absolute start,
428/** 391/**
429 * Compare two peer identities. Indended to be used with qsort or bsearch. 392 * Compare two peer identities. Indended to be used with qsort or bsearch.
430 * 393 *
431 * @param p1 some peer identity 394 * @param p1 Some peer identity.
432 * @param p2 some peer identity 395 * @param p2 Some peer identity.
433 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2. 396 * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2.
434 */ 397 */
435static int 398static int
@@ -442,10 +405,10 @@ peer_id_cmp (const void *p1, const void *p2)
442/** 405/**
443 * Get the index of a peer in an array of peers 406 * Get the index of a peer in an array of peers
444 * 407 *
445 * @param haystack array of peers 408 * @param haystack Array of peers.
446 * @param n size of @a haystack 409 * @param n Size of @a haystack.
447 * @param needle peer to find 410 * @param needle Peer to find
448 * @return index of @a needle in @a haystack, or -1 if peer 411 * @return Index of @a needle in @a haystack, or -1 if peer
449 * is not in the list. 412 * is not in the list.
450 */ 413 */
451static int 414static int
@@ -464,11 +427,11 @@ peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n,
464 * Normalize the given list of peers, by including the local peer 427 * Normalize the given list of peers, by including the local peer
465 * (if it is missing) and sorting the peers by their identity. 428 * (if it is missing) and sorting the peers by their identity.
466 * 429 *
467 * @param listed peers in the unnormalized list 430 * @param listed Peers in the unnormalized list.
468 * @param num_listed peers in the un-normalized list 431 * @param num_listed Peers in the un-normalized list.
469 * @param[out] num_normalized number of peers in the normalized list 432 * @param[out] num_normalized Number of peers in the normalized list.
470 * @param[out] my_peer_idx index of the local peer in the normalized list 433 * @param[out] my_peer_idx Index of the local peer in the normalized list.
471 * @return normalized list, must be free'd by the caller 434 * @return Normalized list, must be free'd by the caller.
472 */ 435 */
473static struct GNUNET_PeerIdentity * 436static struct GNUNET_PeerIdentity *
474normalize_peers (struct GNUNET_PeerIdentity *listed, 437normalize_peers (struct GNUNET_PeerIdentity *listed,
@@ -477,6 +440,7 @@ normalize_peers (struct GNUNET_PeerIdentity *listed,
477 unsigned int *my_peer_idx) 440 unsigned int *my_peer_idx)
478{ 441{
479 unsigned int local_peer_in_list; 442 unsigned int local_peer_in_list;
443 /* number of peers in the normalized list */
480 unsigned int n; 444 unsigned int n;
481 struct GNUNET_PeerIdentity *normalized; 445 struct GNUNET_PeerIdentity *normalized;
482 446
@@ -506,10 +470,10 @@ normalize_peers (struct GNUNET_PeerIdentity *listed,
506 470
507 471
508/** 472/**
509 * Get a the j-th lagrage coefficient for a set of indices. 473 * Get a the j-th lagrange coefficient for a set of indices.
510 * 474 *
511 * @param[out] coeff the lagrange coefficient 475 * @param[out] coeff the lagrange coefficient
512 * @param j lagrage coefficient we want to compute 476 * @param j lagrange coefficient we want to compute
513 * @param indices indices 477 * @param indices indices
514 * @param num number of indices in @a indices 478 * @param num number of indices in @a indices
515 */ 479 */
@@ -518,7 +482,7 @@ compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
518 unsigned int *indices, 482 unsigned int *indices,
519 unsigned int num) 483 unsigned int num)
520{ 484{
521 int i; 485 unsigned int i;
522 /* numerator */ 486 /* numerator */
523 gcry_mpi_t n; 487 gcry_mpi_t n;
524 /* denominator */ 488 /* denominator */
@@ -535,22 +499,27 @@ compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j,
535 gcry_mpi_set_ui (n, 1); 499 gcry_mpi_set_ui (n, 1);
536 gcry_mpi_set_ui (d, 1); 500 gcry_mpi_set_ui (d, 1);
537 501
538 gcry_mpi_set_ui (coeff, 0);
539 for (i = 0; i < num; i++) 502 for (i = 0; i < num; i++)
540 { 503 {
541 int l = indices[i]; 504 unsigned int l = indices[i];
542 if (l == j) 505 if (l == j)
543 continue; 506 continue;
544 gcry_mpi_mul_ui (n, n, l); 507 gcry_mpi_mul_ui (n, n, l + 1);
545 // d <- d * (l-j) 508 // d <- d * (l-j)
546 gcry_mpi_set_ui (tmp, l); 509 gcry_mpi_set_ui (tmp, l + 1);
547 gcry_mpi_sub_ui (tmp, tmp, j); 510 gcry_mpi_sub_ui (tmp, tmp, j + 1);
548 gcry_mpi_mul (d, d, tmp); 511 gcry_mpi_mul (d, d, tmp);
549 } 512 }
550 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
551 // now we do the actual division, with everything mod q, as we 519 // now we do the actual division, with everything mod q, as we
552 // are not operating on elemets from <g>, but on exponents 520 // are not operating on elements from <g>, but on exponents
553 GNUNET_assert (0 == gcry_mpi_invm (d, d, elgamal_q)); 521 GNUNET_assert (0 != gcry_mpi_invm (d, d, elgamal_q));
522
554 gcry_mpi_mulm (coeff, n, d, elgamal_q); 523 gcry_mpi_mulm (coeff, n, d, elgamal_q);
555 524
556 gcry_mpi_release (n); 525 gcry_mpi_release (n);
@@ -580,11 +549,22 @@ paillier_create (gcry_mpi_t n, gcry_mpi_t lambda, gcry_mpi_t mu)
580 GNUNET_assert (0 != (phi = gcry_mpi_new (PAILLIER_BITS))); 549 GNUNET_assert (0 != (phi = gcry_mpi_new (PAILLIER_BITS)));
581 GNUNET_assert (0 != (tmp = gcry_mpi_new (PAILLIER_BITS))); 550 GNUNET_assert (0 != (tmp = gcry_mpi_new (PAILLIER_BITS)));
582 551
583 // generate rsa modulus 552 p = q = NULL;
584 GNUNET_assert (0 == gcry_prime_generate (&p, PAILLIER_BITS / 2, 0, NULL, NULL, NULL, 553
585 GCRY_WEAK_RANDOM, 0)); 554 // Generate two distinct primes.
586 GNUNET_assert (0 == gcry_prime_generate (&q, PAILLIER_BITS / 2, 0, NULL, NULL, NULL, 555 // The probability that the loop body
556 // is executed more than once is very low.
557 do {
558 if (NULL != p)
559 gcry_mpi_release (p);
560 if (NULL != q)
561 gcry_mpi_release (q);
562 // generate rsa modulus
563 GNUNET_assert (0 == gcry_prime_generate (&p, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
564 GCRY_WEAK_RANDOM, 0));
565 GNUNET_assert (0 == gcry_prime_generate (&q, PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
587 GCRY_WEAK_RANDOM, 0)); 566 GCRY_WEAK_RANDOM, 0));
567 } while (0 == gcry_mpi_cmp (p, q));
588 gcry_mpi_mul (n, p, q); 568 gcry_mpi_mul (n, p, q);
589 // compute phi(n) = (p-1)(q-1) 569 // compute phi(n) = (p-1)(q-1)
590 gcry_mpi_sub_ui (phi, p, 1); 570 gcry_mpi_sub_ui (phi, p, 1);
@@ -604,7 +584,7 @@ paillier_create (gcry_mpi_t n, gcry_mpi_t lambda, gcry_mpi_t mu)
604/** 584/**
605 * Encrypt a value using Paillier's scheme. 585 * Encrypt a value using Paillier's scheme.
606 * 586 *
607 * @param c resulting ciphertext 587 * @param[out] c resulting ciphertext
608 * @param m plaintext to encrypt 588 * @param m plaintext to encrypt
609 * @param n n-component of public key 589 * @param n n-component of public key
610 */ 590 */
@@ -628,7 +608,7 @@ paillier_encrypt (gcry_mpi_t c, gcry_mpi_t m, gcry_mpi_t n)
628 { 608 {
629 gcry_mpi_randomize (r, PAILLIER_BITS, GCRY_WEAK_RANDOM); 609 gcry_mpi_randomize (r, PAILLIER_BITS, GCRY_WEAK_RANDOM);
630 } 610 }
631 while (gcry_mpi_cmp (r, n) > 0); 611 while (gcry_mpi_cmp (r, n) >= 0);
632 612
633 gcry_mpi_powm (c, g, m, n_square); 613 gcry_mpi_powm (c, g, m, n_square);
634 gcry_mpi_powm (r, r, n, n_square); 614 gcry_mpi_powm (r, r, n, n_square);
@@ -636,6 +616,7 @@ paillier_encrypt (gcry_mpi_t c, gcry_mpi_t m, gcry_mpi_t n)
636 616
637 gcry_mpi_release (n_square); 617 gcry_mpi_release (n_square);
638 gcry_mpi_release (r); 618 gcry_mpi_release (r);
619 gcry_mpi_release (g);
639} 620}
640 621
641 622
@@ -652,17 +633,69 @@ static void
652paillier_decrypt (gcry_mpi_t m, gcry_mpi_t c, gcry_mpi_t mu, gcry_mpi_t lambda, gcry_mpi_t n) 633paillier_decrypt (gcry_mpi_t m, gcry_mpi_t c, gcry_mpi_t mu, gcry_mpi_t lambda, gcry_mpi_t n)
653{ 634{
654 gcry_mpi_t n_square; 635 gcry_mpi_t n_square;
636
655 GNUNET_assert (0 != (n_square = gcry_mpi_new (0))); 637 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
638
656 gcry_mpi_mul (n_square, n, n); 639 gcry_mpi_mul (n_square, n, n);
640 // m = c^lambda mod n^2
657 gcry_mpi_powm (m, c, lambda, n_square); 641 gcry_mpi_powm (m, c, lambda, n_square);
642 // m = m - 1
658 gcry_mpi_sub_ui (m, m, 1); 643 gcry_mpi_sub_ui (m, m, 1);
659 // m = m/n 644 // m <- m/n
660 gcry_mpi_div (m, NULL, m, n, 0); 645 gcry_mpi_div (m, NULL, m, n, 0);
661 gcry_mpi_mulm (m, m, mu, n); 646 gcry_mpi_mulm (m, m, mu, n);
662 gcry_mpi_release (n_square); 647 gcry_mpi_release (n_square);
663} 648}
664 649
665 650
651static void
652decrypt_session_destroy (struct DecryptSession *ds)
653{
654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt session\n");
655
656 GNUNET_CONTAINER_DLL_remove (decrypt_sessions_head, decrypt_sessions_tail, ds);
657
658 if (NULL != ds->client_mq)
659 {
660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt MQ\n");
661 GNUNET_MQ_destroy (ds->client_mq);
662 ds->client_mq = NULL;
663 }
664
665 if (NULL != ds->client)
666 {
667 GNUNET_SERVER_client_disconnect (ds->client);
668 ds->client = NULL;
669 }
670
671 GNUNET_free (ds);
672}
673
674
675static void
676keygen_session_destroy (struct KeygenSession *ks)
677{
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen session\n");
679
680 GNUNET_CONTAINER_DLL_remove (keygen_sessions_head, keygen_sessions_tail, ks);
681
682 if (NULL != ks->client_mq)
683 {
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen MQ\n");
685 GNUNET_MQ_destroy (ks->client_mq);
686 ks->client_mq = NULL;
687 }
688
689 if (NULL != ks->client)
690 {
691 GNUNET_SERVER_client_disconnect (ks->client);
692 ks->client = NULL;
693 }
694
695 GNUNET_free (ks);
696}
697
698
666/** 699/**
667 * Task run during shutdown. 700 * Task run during shutdown.
668 * 701 *
@@ -672,7 +705,11 @@ paillier_decrypt (gcry_mpi_t m, gcry_mpi_t c, gcry_mpi_t mu, gcry_mpi_t lambda,
672static void 705static void
673cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 706cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
674{ 707{
675 /* FIXME: do clean up here */ 708 while (NULL != decrypt_sessions_head)
709 decrypt_session_destroy (decrypt_sessions_head);
710
711 while (NULL != keygen_sessions_head)
712 keygen_session_destroy (keygen_sessions_head);
676} 713}
677 714
678 715
@@ -685,23 +722,31 @@ static void
685generate_presecret_polynomial (struct KeygenSession *ks) 722generate_presecret_polynomial (struct KeygenSession *ks)
686{ 723{
687 int i; 724 int i;
725 gcry_mpi_t v;
726
688 GNUNET_assert (NULL == ks->presecret_polynomial); 727 GNUNET_assert (NULL == ks->presecret_polynomial);
689 ks->presecret_polynomial = GNUNET_malloc (ks->threshold * sizeof (gcry_mpi_t)); 728 ks->presecret_polynomial = GNUNET_new_array (ks->threshold, gcry_mpi_t);
690 for (i = 0; i < ks->threshold; i++) 729 for (i = 0; i < ks->threshold; i++)
691 { 730 {
692 ks->presecret_polynomial[i] = gcry_mpi_new (GNUNET_SECRETSHARING_KEY_BITS); 731 v = ks->presecret_polynomial[i] = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS);
693 GNUNET_assert (0 != ks->presecret_polynomial[i]); 732 GNUNET_assert (NULL != v);
694 gcry_mpi_randomize (ks->presecret_polynomial[i], GNUNET_SECRETSHARING_KEY_BITS, 733 // Randomize v such that 0 < v < elgamal_q.
695 GCRY_WEAK_RANDOM); 734 // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1.
735 do
736 {
737 gcry_mpi_randomize (v, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM);
738 } while ((gcry_mpi_cmp_ui (v, 0) == 0) || (gcry_mpi_cmp (v, elgamal_q) >= 0));
696 } 739 }
697} 740}
698 741
699 742
700/** 743/**
701 * Consensus element handler for round one. 744 * Consensus element handler for round one.
745 * We should get one ephemeral key for each peer.
702 * 746 *
703 * @param cls closure (keygen session) 747 * @param cls Closure (keygen session).
704 * @param element the element from consensus 748 * @param element The element from consensus, or
749 * NULL if consensus failed.
705 */ 750 */
706static void 751static void
707keygen_round1_new_element (void *cls, 752keygen_round1_new_element (void *cls,
@@ -717,6 +762,7 @@ keygen_round1_new_element (void *cls,
717 return; 762 return;
718 } 763 }
719 764
765 /* elements have fixed size */
720 if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData)) 766 if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData))
721 { 767 {
722 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 768 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -729,7 +775,6 @@ keygen_round1_new_element (void *cls,
729 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n"); 775 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n");
730 776
731 d = element->data; 777 d = element->data;
732
733 info = get_keygen_peer_info (ks, &d->peer); 778 info = get_keygen_peer_info (ks, &d->peer);
734 779
735 if (NULL == info) 780 if (NULL == info)
@@ -739,6 +784,7 @@ keygen_round1_new_element (void *cls,
739 return; 784 return;
740 } 785 }
741 786
787 /* Check that the right amount of data has been signed. */
742 if (d->purpose.size != 788 if (d->purpose.size !=
743 htonl (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose))) 789 htonl (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)))
744 { 790 {
@@ -752,11 +798,8 @@ keygen_round1_new_element (void *cls,
752 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n"); 798 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n");
753 return; 799 return;
754 } 800 }
755 801 GNUNET_CRYPTO_mpi_scan_unsigned (&info->paillier_n, &d->pubkey.n, PAILLIER_BITS / 8);
756 GNUNET_assert (0 == gcry_mpi_scan (&info->paillier_n, GCRYMPI_FMT_USG, 802 GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->pubkey.n, PAILLIER_BITS / 8);
757 &d->pubkey.n, sizeof d->pubkey.n, NULL));
758 GNUNET_assert (0 == gcry_mpi_scan (&info->presecret_commitment, GCRYMPI_FMT_USG,
759 &d->commitment, sizeof d->commitment, NULL));
760 info->round1_valid = GNUNET_YES; 803 info->round1_valid = GNUNET_YES;
761} 804}
762 805
@@ -796,16 +839,20 @@ keygen_round2_conclude (void *cls)
796 unsigned int i; 839 unsigned int i;
797 unsigned int j; 840 unsigned int j;
798 struct GNUNET_SECRETSHARING_Share *share; 841 struct GNUNET_SECRETSHARING_Share *share;
842 /* our share */
799 gcry_mpi_t s; 843 gcry_mpi_t s;
844 /* public key */
800 gcry_mpi_t h; 845 gcry_mpi_t h;
801 846
802 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n"); 847 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n");
803 848
804 GNUNET_assert (0 != (s = gcry_mpi_new (GNUNET_SECRETSHARING_KEY_BITS))); 849 GNUNET_assert (0 != (s = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
805 GNUNET_assert (0 != (h = gcry_mpi_new (GNUNET_SECRETSHARING_KEY_BITS))); 850 GNUNET_assert (0 != (h = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
806 851
807 // multiplicative identity 852 // multiplicative identity
808 gcry_mpi_set_ui (s, 1); 853 gcry_mpi_set_ui (h, 1);
854 // additive identity
855 gcry_mpi_set_ui (s, 0);
809 856
810 share = GNUNET_new (struct GNUNET_SECRETSHARING_Share); 857 share = GNUNET_new (struct GNUNET_SECRETSHARING_Share);
811 858
@@ -820,6 +867,9 @@ keygen_round2_conclude (void *cls)
820 GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement); 867 GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement);
821 share->original_indices = GNUNET_new_array (share->num_peers, uint16_t); 868 share->original_indices = GNUNET_new_array (share->num_peers, uint16_t);
822 869
870 /* maybe we're not even in the list of peers? */
871 share->my_peer = share->num_peers;
872
823 j = 0; 873 j = 0;
824 for (i = 0; i < ks->num_peers; i++) 874 for (i = 0; i < ks->num_peers; i++)
825 { 875 {
@@ -829,13 +879,18 @@ keygen_round2_conclude (void *cls)
829 gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p); 879 gcry_mpi_mulm (h, h, ks->info[i].public_key_share, elgamal_p);
830 share->peers[i] = ks->info[i].peer; 880 share->peers[i] = ks->info[i].peer;
831 share->original_indices[i] = j++; 881 share->original_indices[i] = j++;
882 if (0 == memcmp (&share->peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity)))
883 share->my_peer = i;
832 } 884 }
833 } 885 }
834 886
835 print_mpi_fixed (&share->my_share, s, GNUNET_SECRETSHARING_KEY_BITS / 8); 887 GNUNET_CRYPTO_mpi_print_unsigned (&share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, s);
836 print_mpi_fixed (&share->public_key, h, GNUNET_SECRETSHARING_KEY_BITS / 8); 888 GNUNET_CRYPTO_mpi_print_unsigned (&share->public_key, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, h);
837 889
838 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen successful with %u peers\n", share->num_peers); 890 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers);
891
892 /* Write the share. If 0 peers completed the dkg, an empty
893 * share will be sent. */
839 894
840 m = GNUNET_malloc (sizeof (struct GNUNET_SECRETSHARING_SecretReadyMessage) + 895 m = GNUNET_malloc (sizeof (struct GNUNET_SECRETSHARING_SecretReadyMessage) +
841 ks->num_peers * sizeof (struct GNUNET_PeerIdentity)); 896 ks->num_peers * sizeof (struct GNUNET_PeerIdentity));
@@ -872,13 +927,19 @@ insert_round2_element (struct KeygenSession *ks)
872 unsigned int i; 927 unsigned int i;
873 gcry_mpi_t idx; 928 gcry_mpi_t idx;
874 gcry_mpi_t v; 929 gcry_mpi_t v;
930 gcry_mpi_t c;
875 931
876 GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_KEY_BITS))); 932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting round2 element\n",
877 GNUNET_assert (0 != (idx = gcry_mpi_new (GNUNET_SECRETSHARING_KEY_BITS))); 933 ks->local_peer_idx);
934
935 GNUNET_assert (NULL != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
936 GNUNET_assert (NULL != (idx = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
937 GNUNET_assert (NULL != (c = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
878 938
879 element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) + 939 element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
880 2 * GNUNET_SECRETSHARING_KEY_BITS / 8 * ks->num_peers + 940 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers +
881 1 * GNUNET_SECRETSHARING_KEY_BITS / 8 * ks->threshold); 941 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold +
942 PAILLIER_BITS * 2 / 8 * ks->num_peers);
882 943
883 element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size); 944 element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size);
884 element->size = element_size; 945 element->size = element_size;
@@ -887,6 +948,8 @@ insert_round2_element (struct KeygenSession *ks)
887 d = (void *) element->data; 948 d = (void *) element->data;
888 d->peer = my_peer; 949 d->peer = my_peer;
889 950
951 // start inserting vector elements
952 // after the fixed part of the element's data
890 pos = (void *) &d[1]; 953 pos = (void *) &d[1];
891 last_pos = pos + element_size; 954 last_pos = pos + element_size;
892 955
@@ -895,38 +958,55 @@ insert_round2_element (struct KeygenSession *ks)
895 { 958 {
896 ptrdiff_t remaining = last_pos - pos; 959 ptrdiff_t remaining = last_pos - pos;
897 GNUNET_assert (remaining > 0); 960 GNUNET_assert (remaining > 0);
898 gcry_mpi_set_ui (idx, i); 961 gcry_mpi_set_ui (idx, i + 1);
899 // evaluate the polynomial 962 // evaluate the polynomial
900 horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_p); 963 horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q);
901 // take g to the result 964 // take g to the result
902 gcry_mpi_powm (v, elgamal_g, v, elgamal_p); 965 gcry_mpi_powm (v, elgamal_g, v, elgamal_p);
903 print_mpi_fixed (pos, v, GNUNET_SECRETSHARING_KEY_BITS / 8); 966 GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
904 pos += GNUNET_SECRETSHARING_KEY_BITS / 8; 967 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8;
905 } 968 }
906 969
970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp preshares\n",
971 ks->local_peer_idx);
972
907 // encrypted pre-shares 973 // encrypted pre-shares
908 for (i = 0; i < ks->num_peers; i++) 974 for (i = 0; i < ks->num_peers; i++)
909 { 975 {
910 ptrdiff_t remaining = last_pos - pos; 976 ptrdiff_t remaining = last_pos - pos;
911 GNUNET_assert (remaining > 0); 977 GNUNET_assert (remaining > 0);
912 if (GNUNET_NO == ks->info[i].round1_valid) 978 if (GNUNET_NO == ks->info[i].round1_valid)
913 gcry_mpi_set_ui (v, 0); 979 {
980 gcry_mpi_set_ui (c, 0);
981 }
914 else 982 else
915 paillier_encrypt (v, ks->presecret_polynomial[0], ks->info[i].paillier_n); 983 {
916 print_mpi_fixed (pos, v, GNUNET_SECRETSHARING_KEY_BITS / 8); 984 gcry_mpi_set_ui (idx, i + 1);
917 pos += GNUNET_SECRETSHARING_KEY_BITS / 8; 985 // evaluate the polynomial
986 horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q);
987 // encrypt the result
988 paillier_encrypt (c, v, ks->info[i].paillier_n);
989 }
990 GNUNET_CRYPTO_mpi_print_unsigned (pos, PAILLIER_BITS * 2 / 8, c);
991 pos += PAILLIER_BITS * 2 / 8;
918 } 992 }
919 993
994 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed enc preshares\n",
995 ks->local_peer_idx);
996
920 // exponentiated coefficients 997 // exponentiated coefficients
921 for (i = 0; i < ks->threshold; i++) 998 for (i = 0; i < ks->threshold; i++)
922 { 999 {
923 ptrdiff_t remaining = last_pos - pos; 1000 ptrdiff_t remaining = last_pos - pos;
924 GNUNET_assert (remaining > 0); 1001 GNUNET_assert (remaining > 0);
925 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p); 1002 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p);
926 print_mpi_fixed (pos, v, GNUNET_SECRETSHARING_KEY_BITS / 8); 1003 GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
927 pos += GNUNET_SECRETSHARING_KEY_BITS / 8; 1004 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8;
928 } 1005 }
929 1006
1007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp coefficients\n",
1008 ks->local_peer_idx);
1009
930 d->purpose.size = htonl (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose)); 1010 d->purpose.size = htonl (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose));
931 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2); 1011 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2);
932 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature); 1012 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature);
@@ -957,8 +1037,9 @@ keygen_round2_new_element (void *cls,
957 } 1037 }
958 1038
959 expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) + 1039 expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) +
960 2 * GNUNET_SECRETSHARING_KEY_BITS / 8 * ks->num_peers + 1040 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers +
961 1 * GNUNET_SECRETSHARING_KEY_BITS / 8 * ks->threshold); 1041 PAILLIER_BITS / 8 * 2 * ks->num_peers +
1042 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold);
962 1043
963 if (element->size != expected_element_size) 1044 if (element->size != expected_element_size)
964 { 1045 {
@@ -1001,31 +1082,28 @@ keygen_round2_new_element (void *cls,
1001 1082
1002 pos = (void *) &d[1]; 1083 pos = (void *) &d[1];
1003 // skip exponentiated pre-shares 1084 // skip exponentiated pre-shares
1004 pos += GNUNET_SECRETSHARING_KEY_BITS / 8 * ks->num_peers; 1085 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
1005 // skip encrypted pre-shares 1086 // skip encrypted pre-shares
1006 pos += PAILLIER_BITS / 8 * ks->num_peers; 1087 pos += PAILLIER_BITS * 2 / 8 * ks->num_peers;
1007 // the first exponentiated coefficient is the public key share 1088 // the first exponentiated coefficient is the public key share
1008 GNUNET_assert (0 == gcry_mpi_scan (&info->public_key_share, GCRYMPI_FMT_USG, 1089 GNUNET_CRYPTO_mpi_scan_unsigned (&info->public_key_share, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1009 pos, GNUNET_SECRETSHARING_KEY_BITS / 8, NULL));
1010 1090
1011 pos = (void *) &d[1]; 1091 pos = (void *) &d[1];
1012 // skip exp. pre-shares 1092 // skip exp. pre-shares
1013 pos += GNUNET_SECRETSHARING_KEY_BITS / 8 * ks->num_peers; 1093 pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers;
1014 // skip to the encrypted value for our peer 1094 // skip to the encrypted value for our peer
1015 pos += PAILLIER_BITS / 8 * ks->local_peer_idx; 1095 pos += PAILLIER_BITS * 2 / 8 * ks->local_peer_idx;
1016 1096
1017 GNUNET_assert (0 == gcry_mpi_scan (&c, GCRYMPI_FMT_USG, 1097 GNUNET_CRYPTO_mpi_scan_unsigned (&c, pos, PAILLIER_BITS * 2 / 8);
1018 pos, PAILLIER_BITS / 8, NULL));
1019 1098
1020 GNUNET_assert (0 != (info->decrypted_preshare = mpi_new (0))); 1099 GNUNET_assert (0 != (info->decrypted_preshare = mpi_new (0)));
1021 1100
1022 paillier_decrypt (info->decrypted_preshare, c, ks->paillier_lambda, ks->paillier_mu, 1101 paillier_decrypt (info->decrypted_preshare, c, ks->paillier_mu, ks->paillier_lambda,
1023 ks->info[ks->local_peer_idx].paillier_n); 1102 ks->info[ks->local_peer_idx].paillier_n);
1024
1025 // TODO: validate zero knowledge proofs 1103 // TODO: validate zero knowledge proofs
1026 1104
1027 if (d->purpose.size != 1105 if (ntohl (d->purpose.size) !=
1028 htons (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose))) 1106 element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose))
1029 { 1107 {
1030 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n"); 1108 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n");
1031 return; 1109 return;
@@ -1082,29 +1160,25 @@ insert_round1_element (struct KeygenSession *ks)
1082 // g^a_{i,0} 1160 // g^a_{i,0}
1083 gcry_mpi_t v; 1161 gcry_mpi_t v;
1084 // big-endian representation of 'v' 1162 // big-endian representation of 'v'
1085 unsigned char v_data[GNUNET_SECRETSHARING_KEY_BITS / 8]; 1163 unsigned char v_data[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
1086 1164
1087 element = GNUNET_malloc (sizeof *element + sizeof *d); 1165 element = GNUNET_malloc (sizeof *element + sizeof *d);
1088 d = (void *) &element[1]; 1166 d = (void *) &element[1];
1089 element->data = d; 1167 element->data = d;
1090 element->size = sizeof *d; 1168 element->size = sizeof *d;
1091 1169
1092 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "alloc'd size %u\n", sizeof *element + sizeof *d);
1093 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "element size %u\n", element->size);
1094
1095
1096 d->peer = my_peer; 1170 d->peer = my_peer;
1097 1171
1098 GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_KEY_BITS))); 1172 GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS)));
1099 1173
1100 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p); 1174 gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p);
1101 1175
1102 print_mpi_fixed (v_data, v, GNUNET_SECRETSHARING_KEY_BITS); 1176 GNUNET_CRYPTO_mpi_print_unsigned (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v);
1103 1177
1104 GNUNET_CRYPTO_hash (v_data, GNUNET_SECRETSHARING_KEY_BITS / 8, &d->commitment); 1178 GNUNET_CRYPTO_hash (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, &d->commitment);
1105 1179
1106 print_mpi_fixed (d->pubkey.n, ks->info[ks->local_peer_idx].paillier_n, 1180 GNUNET_CRYPTO_mpi_print_unsigned (d->pubkey.n, PAILLIER_BITS / 8,
1107 PAILLIER_BITS / 8); 1181 ks->info[ks->local_peer_idx].paillier_n);
1108 1182
1109 d->purpose.size = htonl ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)); 1183 d->purpose.size = htonl ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose));
1110 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1); 1184 d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1);
@@ -1158,7 +1232,7 @@ static void handle_client_keygen (void *cls,
1158 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id, 1232 ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id,
1159 keygen_round1_new_element, ks); 1233 keygen_round1_new_element, ks);
1160 1234
1161 ks->info = GNUNET_malloc (ks->num_peers * sizeof (struct KeygenPeerInfo)); 1235 ks->info = GNUNET_new_array (ks->num_peers, struct KeygenPeerInfo);
1162 1236
1163 for (i = 0; i < ks->num_peers; i++) 1237 for (i = 0; i < ks->num_peers; i++)
1164 ks->info[i].peer = ks->peers[i]; 1238 ks->info[i].peer = ks->peers[i];
@@ -1171,12 +1245,15 @@ static void handle_client_keygen (void *cls,
1171 ks->paillier_lambda, 1245 ks->paillier_lambda,
1172 ks->paillier_mu); 1246 ks->paillier_mu);
1173 1247
1248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated paillier key pair\n", ks->local_peer_idx);
1174 1249
1175 generate_presecret_polynomial (ks); 1250 generate_presecret_polynomial (ks);
1176 1251
1252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated presecret polynomial\n", ks->local_peer_idx);
1253
1177 insert_round1_element (ks); 1254 insert_round1_element (ks);
1178 1255
1179 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "starting conclude of round 1\n"); 1256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Concluding for round 1\n", ks->local_peer_idx);
1180 1257
1181 GNUNET_CONSENSUS_conclude (ks->consensus, 1258 GNUNET_CONSENSUS_conclude (ks->consensus,
1182 /* half the overall time */ 1259 /* half the overall time */
@@ -1185,6 +1262,8 @@ static void handle_client_keygen (void *cls,
1185 ks); 1262 ks);
1186 1263
1187 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1264 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1265
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Waiting for round 1 elements ...\n", ks->local_peer_idx);
1188} 1267}
1189 1268
1190 1269
@@ -1201,6 +1280,7 @@ decrypt_conclude (void *cls)
1201 gcry_mpi_t m; 1280 gcry_mpi_t m;
1202 gcry_mpi_t tmp; 1281 gcry_mpi_t tmp;
1203 gcry_mpi_t c_2; 1282 gcry_mpi_t c_2;
1283 gcry_mpi_t prod;
1204 unsigned int *indices; 1284 unsigned int *indices;
1205 unsigned int num; 1285 unsigned int num;
1206 unsigned int i; 1286 unsigned int i;
@@ -1209,6 +1289,7 @@ decrypt_conclude (void *cls)
1209 GNUNET_assert (0 != (lagrange = gcry_mpi_new (0))); 1289 GNUNET_assert (0 != (lagrange = gcry_mpi_new (0)));
1210 GNUNET_assert (0 != (m = gcry_mpi_new (0))); 1290 GNUNET_assert (0 != (m = gcry_mpi_new (0)));
1211 GNUNET_assert (0 != (tmp = gcry_mpi_new (0))); 1291 GNUNET_assert (0 != (tmp = gcry_mpi_new (0)));
1292 GNUNET_assert (0 != (prod = gcry_mpi_new (0)));
1212 1293
1213 num = 0; 1294 num = 0;
1214 for (i = 0; i < ds->share->num_peers; i++) 1295 for (i = 0; i < ds->share->num_peers; i++)
@@ -1219,30 +1300,36 @@ decrypt_conclude (void *cls)
1219 j = 0; 1300 j = 0;
1220 for (i = 0; i < ds->share->num_peers; i++) 1301 for (i = 0; i < ds->share->num_peers; i++)
1221 if (NULL != ds->info[i].partial_decryption) 1302 if (NULL != ds->info[i].partial_decryption)
1222 indices[j++] = ds->info[i].real_index; 1303 indices[j++] = ds->info[i].original_index;
1223 1304
1224 gcry_mpi_set_ui (m, 1); 1305 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: decrypt conclude, with %u peers\n",
1306 ds->share->my_peer, num);
1225 1307
1308 gcry_mpi_set_ui (prod, 1);
1226 for (i = 0; i < num; i++) 1309 for (i = 0; i < num; i++)
1227 { 1310 {
1311
1312 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: index of %u: %u\n",
1313 ds->share->my_peer, i, indices[i]);
1228 compute_lagrange_coefficient (lagrange, indices[i], indices, num); 1314 compute_lagrange_coefficient (lagrange, indices[i], indices, num);
1229 // w_j^{\lambda_j} 1315 // w_i^{\lambda_i}
1230 gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p); 1316 gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p);
1231 gcry_mpi_mulm (m, m, tmp, elgamal_p);
1232 }
1233 1317
1234 GNUNET_assert (0 == gcry_mpi_scan (&c_2, GCRYMPI_FMT_USG, ds->ciphertext.c2_bits, 1318 // product of all exponentiated partiel decryptions ...
1235 GNUNET_SECRETSHARING_KEY_BITS / 8, NULL)); 1319 gcry_mpi_mulm (prod, prod, tmp, elgamal_p);
1320 }
1236 1321
1237 // m <- c_2 / m 1322 GNUNET_CRYPTO_mpi_scan_unsigned (&c_2, ds->ciphertext.c2_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1238 gcry_mpi_invm (m, m, elgamal_p);
1239 gcry_mpi_mulm (m, c_2, m, elgamal_p);
1240 1323
1324 GNUNET_assert (0 != gcry_mpi_invm (prod, prod, elgamal_p));
1325 gcry_mpi_mulm (m, c_2, prod, elgamal_p);
1241 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE); 1326 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE);
1242 print_mpi_fixed (&msg->plaintext, m, GNUNET_SECRETSHARING_KEY_BITS / 8); 1327 GNUNET_CRYPTO_mpi_print_unsigned (&msg->plaintext, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, m);
1243 msg->success = htonl (1); 1328 msg->success = htonl (1);
1244 GNUNET_MQ_send (ds->client_mq, ev); 1329 GNUNET_MQ_send (ds->client_mq, ev);
1245 1330
1331 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sent decrypt done to client\n");
1332
1246 // FIXME: what if not enough peers participated? 1333 // FIXME: what if not enough peers participated?
1247} 1334}
1248 1335
@@ -1291,8 +1378,8 @@ decrypt_new_element (void *cls,
1291 1378
1292 // FIXME: check NIZP first 1379 // FIXME: check NIZP first
1293 1380
1294 GNUNET_assert (0 == gcry_mpi_scan (&info->partial_decryption, 1381 GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption,
1295 GCRYMPI_FMT_USG, &d->partial_decryption, GNUNET_SECRETSHARING_KEY_BITS / 8, NULL)); 1382 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1296} 1383}
1297 1384
1298static void 1385static void
@@ -1303,22 +1390,37 @@ insert_decrypt_element (struct DecryptSession *ds)
1303 gcry_mpi_t x; 1390 gcry_mpi_t x;
1304 gcry_mpi_t s; 1391 gcry_mpi_t s;
1305 1392
1306 GNUNET_assert (0 == gcry_mpi_scan (&x, GCRYMPI_FMT_USG, ds->ciphertext.c1_bits, GNUNET_SECRETSHARING_KEY_BITS / 8, NULL)); 1393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n",
1307 GNUNET_assert (0 == gcry_mpi_scan (&s, GCRYMPI_FMT_USG, &ds->share->my_share, GNUNET_SECRETSHARING_KEY_BITS / 8, NULL)); 1394 ds->share->my_peer);
1395
1396 GNUNET_CRYPTO_mpi_scan_unsigned (&x, &ds->ciphertext.c1_bits,
1397 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1398 GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share,
1399 GNUNET_SECRETSHARING_ELGAMAL_BITS / 8);
1308 1400
1309 gcry_mpi_powm (x, x, s, elgamal_p); 1401 gcry_mpi_powm (x, x, s, elgamal_p);
1310 1402
1311 element.data = (void *) &d; 1403 element.data = (void *) &d;
1312 element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData); 1404 element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData);
1405 element.type = 0;
1313 1406
1407 /* make vagrind happy until we implement the real deal ... */
1408 memset (&d.nizk_commit1, 0, sizeof d.nizk_commit1);
1409 memset (&d.nizk_commit2, 0, sizeof d.nizk_commit2);
1410 memset (&d.nizk_response, 0, sizeof d.nizk_response);
1411
1412 d.ciphertext = ds->ciphertext;
1314 d.peer = my_peer; 1413 d.peer = my_peer;
1315 d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose)); 1414 d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose));
1316 d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION); 1415 d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION);
1416
1317 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature); 1417 GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature);
1318 1418
1319 print_mpi_fixed (&d.partial_decryption, x, GNUNET_SECRETSHARING_KEY_BITS / 8); 1419 GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, x);
1320 1420
1321 GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL); 1421 GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL);
1422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element done!\n",
1423 ds->share->my_peer);
1322} 1424}
1323 1425
1324 1426
@@ -1339,6 +1441,7 @@ static void handle_client_decrypt (void *cls,
1339 (const void *) message; 1441 (const void *) message;
1340 struct DecryptSession *ds; 1442 struct DecryptSession *ds;
1341 struct GNUNET_HashCode session_id; 1443 struct GNUNET_HashCode session_id;
1444 unsigned int i;
1342 1445
1343 ds = GNUNET_new (struct DecryptSession); 1446 ds = GNUNET_new (struct DecryptSession);
1344 // FIXME: check if session already exists 1447 // FIXME: check if session already exists
@@ -1359,52 +1462,82 @@ static void handle_client_decrypt (void *cls,
1359 ds->share->num_peers, 1462 ds->share->num_peers,
1360 ds->share->peers, 1463 ds->share->peers,
1361 &session_id, 1464 &session_id,
1362 decrypt_new_element, 1465 &decrypt_new_element,
1363 ds); 1466 ds);
1364 1467
1468
1469 ds->info = GNUNET_new_array (ds->share->num_peers, struct DecryptPeerInfo);
1470 for (i = 0; i < ds->share->num_peers; i++)
1471 {
1472 ds->info[i].peer = ds->share->peers[i];
1473 ds->info[i].original_index = ds->share->original_indices[i];
1474 }
1475
1365 insert_decrypt_element (ds); 1476 insert_decrypt_element (ds);
1366 1477
1367 GNUNET_CONSENSUS_conclude (ds->consensus, ds->deadline, decrypt_conclude, ds); 1478 GNUNET_CONSENSUS_conclude (ds->consensus, ds->deadline, decrypt_conclude, ds);
1479
1480 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1481
1482 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypting with %u peers\n",
1483 ds->share->num_peers);
1368} 1484}
1369 1485
1370 1486
1371static void 1487static void
1372init_crypto_constants (void) 1488init_crypto_constants (void)
1373{ 1489{
1374 /* 1024-bit safe prime */
1375 const char *elgamal_p_hex =
1376 "0x08a347d3d69e8b2dd7d1b12a08dfbccbebf4ca"
1377 "6f4269a0814e158a34312964d946b3ef22882317"
1378 "2bcf30fc08f772774cb404f9bc002a6f66b09a79"
1379 "d810d67c4f8cb3bedc6060e3c8ef874b1b64df71"
1380 "6c7d2b002da880e269438d5a776e6b5f253c8df5"
1381 "6a16b1c7ce58def07c03db48238aadfc52a354a2"
1382 "7ed285b0c1675cad3f3";
1383 /* 1023-bit Sophie Germain prime, q = (p-1)/2 */
1384 const char *elgamal_q_hex =
1385 "0x0451a3e9eb4f4596ebe8d895046fde65f5fa65"
1386 "37a134d040a70ac51a1894b26ca359f79144118b"
1387 "95e7987e047bb93ba65a027cde001537b3584d3c"
1388 "ec086b3e27c659df6e303071e477c3a58db26fb8"
1389 "b63e958016d4407134a1c6ad3bb735af929e46fa"
1390 "b50b58e3e72c6f783e01eda411c556fe2951aa51"
1391 "3f6942d860b3ae569f9";
1392 /* generator of the unique size q subgroup of Z_p^* */
1393 const char *elgamal_g_hex =
1394 "0x05c00c36d2e822950087ef09d8252994adc4e4"
1395 "8fe3ec70269f035b46063aff0c99b633fd64df43"
1396 "02442e1914c829a41505a275438871f365e91c12"
1397 "3d5303ef9e90f4b8cb89bf86cc9b513e74a72634"
1398 "9cfd9f953674fab5d511e1c078fc72d72b34086f"
1399 "c82b4b951989eb85325cb203ff98df76bc366bba"
1400 "1d7024c3650f60d0da";
1401
1402 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX, 1490 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX,
1403 elgamal_q_hex, 0, NULL)); 1491 GNUNET_SECRETSHARING_ELGAMAL_Q_HEX, 0, NULL));
1404 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX, 1492 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX,
1405 elgamal_p_hex, 0, NULL)); 1493 GNUNET_SECRETSHARING_ELGAMAL_P_HEX, 0, NULL));
1406 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX, 1494 GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX,
1407 elgamal_g_hex, 0, NULL)); 1495 GNUNET_SECRETSHARING_ELGAMAL_G_HEX, 0, NULL));
1496}
1497
1498
1499static struct KeygenSession *
1500keygen_session_get (struct GNUNET_SERVER_Client *client)
1501{
1502 struct KeygenSession *ks;
1503 for (ks = keygen_sessions_head; NULL != ks; ks = ks->next)
1504 if (ks->client == client)
1505 return ks;
1506 return NULL;
1507}
1508
1509static struct DecryptSession *
1510decrypt_session_get (struct GNUNET_SERVER_Client *client)
1511{
1512 struct DecryptSession *ds;
1513 for (ds = decrypt_sessions_head; NULL != ds; ds = ds->next)
1514 if (ds->client == client)
1515 return ds;
1516 return NULL;
1517}
1518
1519
1520/**
1521 * Clean up after a client has disconnected
1522 *
1523 * @param cls closure, unused
1524 * @param client the client to clean up after
1525 */
1526static void
1527handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1528{
1529 struct KeygenSession *ks;
1530 struct DecryptSession *ds;
1531
1532 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handling client disconnect\n");
1533
1534 ks = keygen_session_get (client);
1535 if (NULL != ks)
1536 keygen_session_destroy (ks);
1537
1538 ds = decrypt_session_get (client);
1539 if (NULL != ds)
1540 decrypt_session_destroy (ds);
1408} 1541}
1409 1542
1410 1543
@@ -1443,6 +1576,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
1443 return; 1576 return;
1444 } 1577 }
1445 GNUNET_SERVER_add_handlers (server, handlers); 1578 GNUNET_SERVER_add_handlers (server, handlers);
1579 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1446 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, 1580 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
1447 NULL); 1581 NULL);
1448} 1582}
diff --git a/src/secretsharing/secretsharing.h b/src/secretsharing/secretsharing.h
index 232721410..e94ff46b7 100644
--- a/src/secretsharing/secretsharing.h
+++ b/src/secretsharing/secretsharing.h
@@ -40,7 +40,7 @@ struct GNUNET_SECRETSHARING_FieldElement
40 /** 40 /**
41 * Value of an element in <elgamal_g>. 41 * Value of an element in <elgamal_g>.
42 */ 42 */
43 unsigned char bits[GNUNET_SECRETSHARING_KEY_BITS / 8]; 43 unsigned char bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8];
44}; 44};
45 45
46 46
@@ -107,6 +107,10 @@ struct GNUNET_SECRETSHARING_ShareHeaderNBO
107}; 107};
108 108
109 109
110/**
111 * Notify the client that then threshold secret has been
112 * established.
113 */
110struct GNUNET_SECRETSHARING_SecretReadyMessage 114struct GNUNET_SECRETSHARING_SecretReadyMessage
111{ 115{
112 /** 116 /**
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 */
91static gcry_mpi_t elgamal_q;
92
93/**
94 * Modulus of the prime field used for ElGamal.
95 * Initialized in #init_crypto_constants.
96 */
97static gcry_mpi_t elgamal_p;
98
99/**
100 * Generator for prime field of order 'elgamal_q'.
101 * Initialized in #init_crypto_constants.
102 */
103static gcry_mpi_t elgamal_g;
104
105
106static void
107ensure_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
86static void 121static void
87handle_session_client_error (void *cls, enum GNUNET_MQ_Error error) 122handle_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)
95static void 130static void
96handle_decrypt_client_error (void *cls, enum GNUNET_MQ_Error error) 131handle_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
101static void 139static void
102handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg) 140handle_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
161void
162GNUNET_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
169static void 219static void
170handle_decrypt_done (void *cls, const struct GNUNET_MessageHeader *msg) 220handle_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 */
189struct GNUNET_SECRETSHARING_DecryptionHandle * 252struct GNUNET_SECRETSHARING_DecryptionHandle *
190GNUNET_SECRETSHARING_decrypt (struct GNUNET_CONFIGURATION_Handle *cfg, 253GNUNET_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
298int
299GNUNET_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 */
347int
348GNUNET_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
395void
396GNUNET_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
diff --git a/src/secretsharing/secretsharing_common.c b/src/secretsharing/secretsharing_common.c
index 9f1e4900b..9f21a1102 100644
--- a/src/secretsharing/secretsharing_common.c
+++ b/src/secretsharing/secretsharing_common.c
@@ -94,7 +94,7 @@ GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share
94 char *p; 94 char *p;
95 int n; 95 int n;
96 96
97 payload_size = ntohs (sh->num_peers) * 97 payload_size = ntohs (share->num_peers) *
98 (sizeof (uint16_t) + sizeof (struct GNUNET_SECRETSHARING_FieldElement) + 98 (sizeof (uint16_t) + sizeof (struct GNUNET_SECRETSHARING_FieldElement) +
99 sizeof (struct GNUNET_PeerIdentity)); 99 sizeof (struct GNUNET_PeerIdentity));
100 100
@@ -134,3 +134,4 @@ GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share
134 return GNUNET_OK; 134 return GNUNET_OK;
135} 135}
136 136
137
diff --git a/src/secretsharing/test_secretsharing.conf b/src/secretsharing/test_secretsharing.conf
index 9cbb95608..6ce865e3a 100644
--- a/src/secretsharing/test_secretsharing.conf
+++ b/src/secretsharing/test_secretsharing.conf
@@ -1,6 +1,6 @@
1[secretsharing] 1[secretsharing]
2AUTOSTART = YES 2AUTOSTART = YES
3PREFIX = valgrind 3#PREFIX = valgrind
4 4
5[consensus] 5[consensus]
6AUTOSTART = YES 6AUTOSTART = YES
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 98af961d5..b502adb4b 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -91,6 +91,7 @@ libgnunetutil_la_SOURCES = \
91 crypto_hash.c \ 91 crypto_hash.c \
92 crypto_hkdf.c \ 92 crypto_hkdf.c \
93 crypto_kdf.c \ 93 crypto_kdf.c \
94 crypto_mpi.c \
94 crypto_random.c \ 95 crypto_random.c \
95 disk.c \ 96 disk.c \
96 disk.h \ 97 disk.h \
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index 6bd96b365..71b8470fe 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -133,72 +133,6 @@ adjust (unsigned char *buf,
133 133
134 134
135/** 135/**
136 * Output the given MPI value to the given buffer.
137 *
138 * @param buf where to output to
139 * @param size number of bytes in @a buf
140 * @param val value to write to @a buf
141 */
142static void
143mpi_print (unsigned char *buf,
144 size_t size,
145 gcry_mpi_t val)
146{
147 size_t rsize;
148
149 if (gcry_mpi_get_flag (val, GCRYMPI_FLAG_OPAQUE))
150 {
151 /* Store opaque MPIs left aligned into the buffer. */
152 unsigned int nbits;
153 const void *p;
154
155 p = gcry_mpi_get_opaque (val, &nbits);
156 GNUNET_assert (p);
157 rsize = (nbits+7)/8;
158 if (rsize > size)
159 rsize = size;
160 memcpy (buf, p, rsize);
161 if (rsize < size)
162 memset (buf+rsize, 0, size - rsize);
163 }
164 else
165 {
166 /* Store regular MPIs as unsigned integers right aligned into
167 the buffer. */
168 rsize = size;
169 GNUNET_assert (0 ==
170 gcry_mpi_print (GCRYMPI_FMT_USG, buf, rsize, &rsize,
171 val));
172 adjust (buf, rsize, size);
173 }
174}
175
176
177/**
178 * Convert data buffer into MPI value.
179 *
180 * @param result where to store MPI value (allocated)
181 * @param data raw data (GCRYMPI_FMT_USG)
182 * @param size number of bytes in @a data
183 */
184static void
185mpi_scan (gcry_mpi_t *result,
186 const unsigned char *data,
187 size_t size)
188{
189 int rc;
190
191 if (0 != (rc = gcry_mpi_scan (result,
192 GCRYMPI_FMT_USG,
193 data, size, &size)))
194 {
195 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
196 GNUNET_assert (0);
197 }
198}
199
200
201/**
202 * Convert the given private key from the network format to the 136 * Convert the given private key from the network format to the
203 * S-expression that can be used by libgcrypt. 137 * S-expression that can be used by libgcrypt.
204 * 138 *
@@ -317,7 +251,7 @@ GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *
317 gcry_sexp_release (sexp); 251 gcry_sexp_release (sexp);
318 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); 252 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
319 GNUNET_assert (q); 253 GNUNET_assert (q);
320 mpi_print (pub->q_y, sizeof (pub->q_y), q); 254 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
321 gcry_mpi_release (q); 255 gcry_mpi_release (q);
322 gcry_ctx_release (ctx); 256 gcry_ctx_release (ctx);
323} 257}
@@ -343,7 +277,7 @@ GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *
343 gcry_sexp_release (sexp); 277 gcry_sexp_release (sexp);
344 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); 278 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
345 GNUNET_assert (q); 279 GNUNET_assert (q);
346 mpi_print (pub->q_y, sizeof (pub->q_y), q); 280 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
347 gcry_mpi_release (q); 281 gcry_mpi_release (q);
348 gcry_ctx_release (ctx); 282 gcry_ctx_release (ctx);
349} 283}
@@ -369,7 +303,7 @@ GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *
369 gcry_sexp_release (sexp); 303 gcry_sexp_release (sexp);
370 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); 304 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
371 GNUNET_assert (q); 305 GNUNET_assert (q);
372 mpi_print (pub->q_y, sizeof (pub->q_y), q); 306 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
373 gcry_mpi_release (q); 307 gcry_mpi_release (q);
374 gcry_ctx_release (ctx); 308 gcry_ctx_release (ctx);
375} 309}
@@ -578,7 +512,7 @@ GNUNET_CRYPTO_ecdhe_key_create ()
578 } 512 }
579 gcry_sexp_release (priv_sexp); 513 gcry_sexp_release (priv_sexp);
580 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey); 514 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
581 mpi_print (priv->d, sizeof (priv->d), d); 515 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
582 gcry_mpi_release (d); 516 gcry_mpi_release (d);
583 return priv; 517 return priv;
584} 518}
@@ -628,7 +562,7 @@ GNUNET_CRYPTO_ecdsa_key_create ()
628 } 562 }
629 gcry_sexp_release (priv_sexp); 563 gcry_sexp_release (priv_sexp);
630 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); 564 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
631 mpi_print (priv->d, sizeof (priv->d), d); 565 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
632 gcry_mpi_release (d); 566 gcry_mpi_release (d);
633 return priv; 567 return priv;
634} 568}
@@ -677,7 +611,7 @@ GNUNET_CRYPTO_eddsa_key_create ()
677 } 611 }
678 gcry_sexp_release (priv_sexp); 612 gcry_sexp_release (priv_sexp);
679 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey); 613 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
680 mpi_print (priv->d, sizeof (priv->d), d); 614 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
681 gcry_mpi_release (d); 615 gcry_mpi_release (d);
682 return priv; 616 return priv;
683} 617}
@@ -700,7 +634,7 @@ GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
700 634
701 if (once) 635 if (once)
702 return &anonymous; 636 return &anonymous;
703 mpi_print (anonymous.d, 637 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
704 sizeof (anonymous.d), 638 sizeof (anonymous.d),
705 GCRYMPI_CONST_ONE); 639 GCRYMPI_CONST_ONE);
706 once = 1; 640 once = 1;
@@ -1222,8 +1156,8 @@ GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1222 return GNUNET_SYSERR; 1156 return GNUNET_SYSERR;
1223 } 1157 }
1224 gcry_sexp_release (sig_sexp); 1158 gcry_sexp_release (sig_sexp);
1225 mpi_print (sig->r, sizeof (sig->r), rs[0]); 1159 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1226 mpi_print (sig->s, sizeof (sig->s), rs[1]); 1160 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1227 gcry_mpi_release (rs[0]); 1161 gcry_mpi_release (rs[0]);
1228 gcry_mpi_release (rs[1]); 1162 gcry_mpi_release (rs[1]);
1229 return GNUNET_OK; 1163 return GNUNET_OK;
@@ -1272,8 +1206,8 @@ GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1272 return GNUNET_SYSERR; 1206 return GNUNET_SYSERR;
1273 } 1207 }
1274 gcry_sexp_release (sig_sexp); 1208 gcry_sexp_release (sig_sexp);
1275 mpi_print (sig->r, sizeof (sig->r), rs[0]); 1209 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1276 mpi_print (sig->s, sizeof (sig->s), rs[1]); 1210 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1277 gcry_mpi_release (rs[0]); 1211 gcry_mpi_release (rs[0]);
1278 gcry_mpi_release (rs[1]); 1212 gcry_mpi_release (rs[1]);
1279 return GNUNET_OK; 1213 return GNUNET_OK;
@@ -1425,7 +1359,7 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1425 q = gcry_mpi_ec_get_point ("q", ctx, 0); 1359 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1426 1360
1427 /* second, extract the d value from our private key */ 1361 /* second, extract the d value from our private key */
1428 mpi_scan (&d, priv->d, sizeof (priv->d)); 1362 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1429 1363
1430 /* then call the 'multiply' function, to compute the product */ 1364 /* then call the 'multiply' function, to compute the product */
1431 result = gcry_mpi_point_new (0); 1365 result = gcry_mpi_point_new (0);
@@ -1447,7 +1381,7 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1447 1381
1448 rsize = sizeof (xbuf); 1382 rsize = sizeof (xbuf);
1449 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE)); 1383 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1450 /* result_x can be negative here, so we do not use 'mpi_print' 1384 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1451 as that does not include the sign bit; x should be a 255-bit 1385 as that does not include the sign bit; x should be a 255-bit
1452 value, so with the sign it should fit snugly into the 256-bit 1386 value, so with the sign it should fit snugly into the 256-bit
1453 xbuf */ 1387 xbuf */
@@ -1484,7 +1418,7 @@ derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1484 label, strlen (label), 1418 label, strlen (label),
1485 context, strlen (context), 1419 context, strlen (context),
1486 NULL, 0); 1420 NULL, 0);
1487 mpi_scan (&h, (unsigned char *) &hc, sizeof (hc)); 1421 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof (hc));
1488 return h; 1422 return h;
1489} 1423}
1490 1424
@@ -1520,7 +1454,7 @@ GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateK
1520 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub); 1454 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1521 1455
1522 h = derive_h (&pub, label, context); 1456 h = derive_h (&pub, label, context);
1523 mpi_scan (&x, priv->d, sizeof (priv->d)); 1457 GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof (priv->d));
1524 d = gcry_mpi_new (256); 1458 d = gcry_mpi_new (256);
1525 gcry_mpi_mulm (d, h, x, n); 1459 gcry_mpi_mulm (d, h, x, n);
1526 gcry_mpi_release (h); 1460 gcry_mpi_release (h);
@@ -1528,7 +1462,7 @@ GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateK
1528 gcry_mpi_release (n); 1462 gcry_mpi_release (n);
1529 gcry_ctx_release (ctx); 1463 gcry_ctx_release (ctx);
1530 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); 1464 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1531 mpi_print (ret->d, sizeof (ret->d), d); 1465 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1532 gcry_mpi_release (d); 1466 gcry_mpi_release (d);
1533 return ret; 1467 return ret;
1534} 1468}
@@ -1588,7 +1522,7 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey
1588 gcry_mpi_point_release (v); 1522 gcry_mpi_point_release (v);
1589 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); 1523 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1590 GNUNET_assert (q_y); 1524 GNUNET_assert (q_y);
1591 mpi_print (result->q_y, sizeof result->q_y, q_y); 1525 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof result->q_y, q_y);
1592 gcry_mpi_release (q_y); 1526 gcry_mpi_release (q_y);
1593 gcry_ctx_release (ctx); 1527 gcry_ctx_release (ctx);
1594} 1528}
diff --git a/src/util/crypto_mpi.c b/src/util/crypto_mpi.c
new file mode 100644
index 000000000..8e52424cf
--- /dev/null
+++ b/src/util/crypto_mpi.c
@@ -0,0 +1,132 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file util/crypto_mpi.c
23 * @brief Helper functions for libgcrypt MPIs
24 * @author Christian Grothoff
25 * @author Florian Dold
26 */
27#include "platform.h"
28#include <gcrypt.h>
29#include "gnunet_util_lib.h"
30
31
32#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
33
34/**
35 * Log an error message at log-level 'level' that indicates
36 * a failure of the command 'cmd' with the message given
37 * by gcry_strerror(rc).
38 */
39#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
40
41
42/**
43 * If target != size, move @a target bytes to the end of the size-sized
44 * buffer and zero out the first @a target - @a size bytes.
45 *
46 * @param buf original buffer
47 * @param size number of bytes in @a buf
48 * @param target target size of the buffer
49 */
50static void
51adjust (void *buf,
52 size_t size,
53 size_t target)
54{
55 if (size < target)
56 {
57 memmove (&buf[target - size], buf, size);
58 memset (buf, 0, target - size);
59 }
60}
61
62
63/**
64 * Output the given MPI value to the given buffer in
65 * network byte order.
66 * The MPI @a val may not be negative.
67 *
68 * @param buf where to output to
69 * @param size number of bytes in @a buf
70 * @param val value to write to @a buf
71 */
72void
73GNUNET_CRYPTO_mpi_print_unsigned (void *buf,
74 size_t size,
75 gcry_mpi_t val)
76{
77 size_t rsize;
78
79 if (gcry_mpi_get_flag (val, GCRYMPI_FLAG_OPAQUE))
80 {
81 /* Store opaque MPIs left aligned into the buffer. */
82 unsigned int nbits;
83 const void *p;
84
85 p = gcry_mpi_get_opaque (val, &nbits);
86 GNUNET_assert (p);
87 rsize = (nbits+7)/8;
88 if (rsize > size)
89 rsize = size;
90 memcpy (buf, p, rsize);
91 if (rsize < size)
92 memset (buf+rsize, 0, size - rsize);
93 }
94 else
95 {
96 /* Store regular MPIs as unsigned integers right aligned into
97 the buffer. */
98 rsize = size;
99 GNUNET_assert (0 ==
100 gcry_mpi_print (GCRYMPI_FMT_USG, buf, rsize, &rsize,
101 val));
102 adjust (buf, rsize, size);
103 }
104}
105
106
107/**
108 * Convert data buffer into MPI value.
109 * The buffer is interpreted as network
110 * byte order, unsigned integer.
111 *
112 * @param result where to store MPI value (allocated)
113 * @param data raw data (GCRYMPI_FMT_USG)
114 * @param size number of bytes in @a data
115 */
116void
117GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result,
118 const void *data,
119 size_t size)
120{
121 int rc;
122
123 if (0 != (rc = gcry_mpi_scan (result,
124 GCRYMPI_FMT_USG,
125 data, size, &size)))
126 {
127 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
128 GNUNET_assert (0);
129 }
130}
131
132/* end of crypto_mpi.c */