diff options
author | Schanzenbach, Martin <mschanzenbach@posteo.de> | 2020-04-22 17:10:57 +0200 |
---|---|---|
committer | Schanzenbach, Martin <mschanzenbach@posteo.de> | 2020-04-22 17:10:57 +0200 |
commit | f225e568840aa0233fd41b7ccd838e8ba2031bf9 (patch) | |
tree | 80f6bc4247c6f5fbddcd27099ecbc3dc3203ca1f /src/revocation | |
parent | bf99d2243fedaeb662b5d7b20138cf2ee064a110 (diff) | |
parent | c4fa48421916ff0777e9cf1bbb3b83634392a494 (diff) | |
download | gnunet-f225e568840aa0233fd41b7ccd838e8ba2031bf9.tar.gz gnunet-f225e568840aa0233fd41b7ccd838e8ba2031bf9.zip |
Merge branch 'schanzen/argon_pow'
Diffstat (limited to 'src/revocation')
-rw-r--r-- | src/revocation/gnunet-revocation.c | 210 | ||||
-rw-r--r-- | src/revocation/gnunet-service-revocation.c | 39 | ||||
-rw-r--r-- | src/revocation/plugin_block_revocation.c | 30 | ||||
-rw-r--r-- | src/revocation/revocation.conf.in | 1 | ||||
-rw-r--r-- | src/revocation/revocation.h | 19 | ||||
-rw-r--r-- | src/revocation/revocation_api.c | 360 | ||||
-rw-r--r-- | src/revocation/test_revocation.c | 27 | ||||
-rw-r--r-- | src/revocation/test_revocation.conf | 1 |
8 files changed, 492 insertions, 195 deletions
diff --git a/src/revocation/gnunet-revocation.c b/src/revocation/gnunet-revocation.c index 14e23b244..8b7cf33c6 100644 --- a/src/revocation/gnunet-revocation.c +++ b/src/revocation/gnunet-revocation.c | |||
@@ -28,6 +28,10 @@ | |||
28 | #include "gnunet_revocation_service.h" | 28 | #include "gnunet_revocation_service.h" |
29 | #include "gnunet_identity_service.h" | 29 | #include "gnunet_identity_service.h" |
30 | 30 | ||
31 | /** | ||
32 | * Pow passes | ||
33 | */ | ||
34 | static unsigned int pow_passes = 1; | ||
31 | 35 | ||
32 | /** | 36 | /** |
33 | * Final status code. | 37 | * Final status code. |
@@ -55,6 +59,11 @@ static char *revoke_ego; | |||
55 | static char *test_ego; | 59 | static char *test_ego; |
56 | 60 | ||
57 | /** | 61 | /** |
62 | * -e option. | ||
63 | */ | ||
64 | static unsigned int epochs = 1; | ||
65 | |||
66 | /** | ||
58 | * Handle for revocation query. | 67 | * Handle for revocation query. |
59 | */ | 68 | */ |
60 | static struct GNUNET_REVOCATION_Query *q; | 69 | static struct GNUNET_REVOCATION_Query *q; |
@@ -80,10 +89,19 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; | |||
80 | static unsigned long long matching_bits; | 89 | static unsigned long long matching_bits; |
81 | 90 | ||
82 | /** | 91 | /** |
92 | * Epoch length | ||
93 | */ | ||
94 | static struct GNUNET_TIME_Relative epoch_duration; | ||
95 | |||
96 | /** | ||
83 | * Task used for proof-of-work calculation. | 97 | * Task used for proof-of-work calculation. |
84 | */ | 98 | */ |
85 | static struct GNUNET_SCHEDULER_Task *pow_task; | 99 | static struct GNUNET_SCHEDULER_Task *pow_task; |
86 | 100 | ||
101 | /** | ||
102 | * Proof-of-work object | ||
103 | */ | ||
104 | static struct GNUNET_REVOCATION_Pow proof_of_work; | ||
87 | 105 | ||
88 | /** | 106 | /** |
89 | * Function run if the user aborts with CTRL-C. | 107 | * Function run if the user aborts with CTRL-C. |
@@ -93,6 +111,7 @@ static struct GNUNET_SCHEDULER_Task *pow_task; | |||
93 | static void | 111 | static void |
94 | do_shutdown (void *cls) | 112 | do_shutdown (void *cls) |
95 | { | 113 | { |
114 | fprintf (stderr, "%s", _ ("Shutting down...\n")); | ||
96 | if (NULL != el) | 115 | if (NULL != el) |
97 | { | 116 | { |
98 | GNUNET_IDENTITY_ego_lookup_cancel (el); | 117 | GNUNET_IDENTITY_ego_lookup_cancel (el); |
@@ -188,37 +207,13 @@ print_revocation_result (void *cls, int is_valid) | |||
188 | 207 | ||
189 | 208 | ||
190 | /** | 209 | /** |
191 | * Data needed to perform a revocation. | ||
192 | */ | ||
193 | struct RevocationData | ||
194 | { | ||
195 | /** | ||
196 | * Public key. | ||
197 | */ | ||
198 | struct GNUNET_CRYPTO_EcdsaPublicKey key; | ||
199 | |||
200 | /** | ||
201 | * Revocation signature data. | ||
202 | */ | ||
203 | struct GNUNET_CRYPTO_EcdsaSignature sig; | ||
204 | |||
205 | /** | ||
206 | * Proof of work (in NBO). | ||
207 | */ | ||
208 | uint64_t pow GNUNET_PACKED; | ||
209 | }; | ||
210 | |||
211 | |||
212 | /** | ||
213 | * Perform the revocation. | 210 | * Perform the revocation. |
214 | */ | 211 | */ |
215 | static void | 212 | static void |
216 | perform_revocation (const struct RevocationData *rd) | 213 | perform_revocation () |
217 | { | 214 | { |
218 | h = GNUNET_REVOCATION_revoke (cfg, | 215 | h = GNUNET_REVOCATION_revoke (cfg, |
219 | &rd->key, | 216 | &proof_of_work, |
220 | &rd->sig, | ||
221 | rd->pow, | ||
222 | &print_revocation_result, | 217 | &print_revocation_result, |
223 | NULL); | 218 | NULL); |
224 | } | 219 | } |
@@ -231,13 +226,13 @@ perform_revocation (const struct RevocationData *rd) | |||
231 | * @param rd data to sync | 226 | * @param rd data to sync |
232 | */ | 227 | */ |
233 | static void | 228 | static void |
234 | sync_rd (const struct RevocationData *rd) | 229 | sync_pow () |
235 | { | 230 | { |
236 | if ((NULL != filename) && | 231 | if ((NULL != filename) && |
237 | (sizeof(struct RevocationData) == | 232 | (sizeof(struct GNUNET_REVOCATION_Pow) != |
238 | GNUNET_DISK_fn_write (filename, | 233 | GNUNET_DISK_fn_write (filename, |
239 | &rd, | 234 | &proof_of_work, |
240 | sizeof(rd), | 235 | sizeof(struct GNUNET_REVOCATION_Pow), |
241 | GNUNET_DISK_PERM_USER_READ | 236 | GNUNET_DISK_PERM_USER_READ |
242 | | GNUNET_DISK_PERM_USER_WRITE))) | 237 | | GNUNET_DISK_PERM_USER_WRITE))) |
243 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); | 238 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); |
@@ -252,15 +247,16 @@ sync_rd (const struct RevocationData *rd) | |||
252 | static void | 247 | static void |
253 | calculate_pow_shutdown (void *cls) | 248 | calculate_pow_shutdown (void *cls) |
254 | { | 249 | { |
255 | struct RevocationData *rd = cls; | 250 | struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls; |
256 | 251 | fprintf (stderr, "%s", _ ("Cancelling calculation.\n")); | |
252 | sync_pow (); | ||
257 | if (NULL != pow_task) | 253 | if (NULL != pow_task) |
258 | { | 254 | { |
259 | GNUNET_SCHEDULER_cancel (pow_task); | 255 | GNUNET_SCHEDULER_cancel (pow_task); |
260 | pow_task = NULL; | 256 | pow_task = NULL; |
261 | } | 257 | } |
262 | sync_rd (rd); | 258 | if (NULL != ph) |
263 | GNUNET_free (rd); | 259 | GNUNET_REVOCATION_pow_stop (ph); |
264 | } | 260 | } |
265 | 261 | ||
266 | 262 | ||
@@ -272,38 +268,26 @@ calculate_pow_shutdown (void *cls) | |||
272 | static void | 268 | static void |
273 | calculate_pow (void *cls) | 269 | calculate_pow (void *cls) |
274 | { | 270 | { |
275 | struct RevocationData *rd = cls; | 271 | struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls; |
276 | 272 | ||
277 | /* store temporary results */ | 273 | /* store temporary results */ |
278 | pow_task = NULL; | 274 | pow_task = NULL; |
279 | if (0 == (rd->pow % 128)) | 275 | if (0 == (pow_passes % 128)) |
280 | sync_rd (rd); | 276 | sync_pow (); |
281 | /* display progress estimate */ | ||
282 | if ((0 == ((1 << matching_bits) / 100 / 50)) || | ||
283 | (0 == (rd->pow % ((1 << matching_bits) / 100 / 50)))) | ||
284 | fprintf (stderr, "%s", "."); | ||
285 | if ((0 != rd->pow) && ((0 == ((1 << matching_bits) / 100)) || | ||
286 | (0 == (rd->pow % ((1 << matching_bits) / 100))))) | ||
287 | fprintf (stderr, | ||
288 | " - @ %3u%% (estimate)\n", | ||
289 | (unsigned int) (rd->pow * 100) / (1 << matching_bits)); | ||
290 | /* actually do POW calculation */ | 277 | /* actually do POW calculation */ |
291 | rd->pow++; | 278 | if (GNUNET_OK == GNUNET_REVOCATION_pow_round (ph)) |
292 | if (GNUNET_OK == GNUNET_REVOCATION_check_pow (&rd->key, | ||
293 | rd->pow, | ||
294 | (unsigned int) matching_bits)) | ||
295 | { | 279 | { |
296 | if ((NULL != filename) && | 280 | if ((NULL != filename) && |
297 | (sizeof(struct RevocationData) != | 281 | (sizeof(struct GNUNET_REVOCATION_Pow) != |
298 | GNUNET_DISK_fn_write (filename, | 282 | GNUNET_DISK_fn_write (filename, |
299 | rd, | 283 | &proof_of_work, |
300 | sizeof(struct RevocationData), | 284 | sizeof(struct GNUNET_REVOCATION_Pow), |
301 | GNUNET_DISK_PERM_USER_READ | 285 | GNUNET_DISK_PERM_USER_READ |
302 | | GNUNET_DISK_PERM_USER_WRITE))) | 286 | | GNUNET_DISK_PERM_USER_WRITE))) |
303 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); | 287 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); |
304 | if (perform) | 288 | if (perform) |
305 | { | 289 | { |
306 | perform_revocation (rd); | 290 | perform_revocation (); |
307 | } | 291 | } |
308 | else | 292 | else |
309 | { | 293 | { |
@@ -316,7 +300,19 @@ calculate_pow (void *cls) | |||
316 | } | 300 | } |
317 | return; | 301 | return; |
318 | } | 302 | } |
319 | pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, rd); | 303 | pow_passes++; |
304 | /** | ||
305 | * Otherwise CTRL-C does not work | ||
306 | */ | ||
307 | if (0 == pow_passes % 128) | ||
308 | pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
309 | &calculate_pow, | ||
310 | ph); | ||
311 | else | ||
312 | pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
313 | &calculate_pow, | ||
314 | ph); | ||
315 | |||
320 | } | 316 | } |
321 | 317 | ||
322 | 318 | ||
@@ -329,8 +325,9 @@ calculate_pow (void *cls) | |||
329 | static void | 325 | static void |
330 | ego_callback (void *cls, const struct GNUNET_IDENTITY_Ego *ego) | 326 | ego_callback (void *cls, const struct GNUNET_IDENTITY_Ego *ego) |
331 | { | 327 | { |
332 | struct RevocationData *rd; | ||
333 | struct GNUNET_CRYPTO_EcdsaPublicKey key; | 328 | struct GNUNET_CRYPTO_EcdsaPublicKey key; |
329 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; | ||
330 | struct GNUNET_REVOCATION_PowCalculationHandle *ph = NULL; | ||
334 | 331 | ||
335 | el = NULL; | 332 | el = NULL; |
336 | if (NULL == ego) | 333 | if (NULL == ego) |
@@ -340,44 +337,55 @@ ego_callback (void *cls, const struct GNUNET_IDENTITY_Ego *ego) | |||
340 | return; | 337 | return; |
341 | } | 338 | } |
342 | GNUNET_IDENTITY_ego_get_public_key (ego, &key); | 339 | GNUNET_IDENTITY_ego_get_public_key (ego, &key); |
343 | rd = GNUNET_new (struct RevocationData); | 340 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego); |
341 | memset (&proof_of_work, 0, sizeof (proof_of_work)); | ||
344 | if ((NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test (filename)) && | 342 | if ((NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test (filename)) && |
345 | (sizeof(struct RevocationData) == | 343 | (sizeof(proof_of_work) == |
346 | GNUNET_DISK_fn_read (filename, rd, sizeof(struct RevocationData)))) | 344 | GNUNET_DISK_fn_read (filename, &proof_of_work, sizeof(proof_of_work)))) |
347 | { | 345 | { |
348 | if (0 != GNUNET_memcmp (&rd->key, &key)) | 346 | if (0 != GNUNET_memcmp (&proof_of_work.key, &key)) |
349 | { | 347 | { |
350 | fprintf (stderr, | 348 | fprintf (stderr, |
351 | _ ("Error: revocation certificate in `%s' is not for `%s'\n"), | 349 | _ ("Error: revocation certificate in `%s' is not for `%s'\n"), |
352 | filename, | 350 | filename, |
353 | revoke_ego); | 351 | revoke_ego); |
354 | GNUNET_free (rd); | ||
355 | return; | 352 | return; |
356 | } | 353 | } |
357 | } | 354 | if (GNUNET_YES == |
358 | else | 355 | GNUNET_REVOCATION_check_pow (&proof_of_work, |
359 | { | 356 | (unsigned int) matching_bits, |
360 | GNUNET_REVOCATION_sign_revocation (GNUNET_IDENTITY_ego_get_private_key ( | 357 | epoch_duration)) |
361 | ego), | 358 | { |
362 | &rd->sig); | 359 | fprintf (stderr, "%s", _ ("Revocation certificate ready\n")); |
363 | rd->key = key; | 360 | if (perform) |
364 | } | 361 | perform_revocation (); |
365 | if (GNUNET_YES == | 362 | else |
366 | GNUNET_REVOCATION_check_pow (&key, rd->pow, (unsigned int) matching_bits)) | 363 | GNUNET_SCHEDULER_shutdown (); |
367 | { | 364 | return; |
368 | fprintf (stderr, "%s", _ ("Revocation certificate ready\n")); | 365 | } |
369 | if (perform) | 366 | /** |
370 | perform_revocation (rd); | 367 | * Certificate not yet ready |
371 | else | 368 | */ |
372 | GNUNET_SCHEDULER_shutdown (); | 369 | fprintf (stderr, |
373 | GNUNET_free (rd); | 370 | "%s", |
374 | return; | 371 | _ ("Continuing calculation where left off...\n")); |
372 | ph = GNUNET_REVOCATION_pow_start (&proof_of_work, | ||
373 | epochs, | ||
374 | matching_bits); | ||
375 | } | 375 | } |
376 | fprintf (stderr, | 376 | fprintf (stderr, |
377 | "%s", | 377 | "%s", |
378 | _ ("Revocation certificate not ready, calculating proof of work\n")); | 378 | _ ("Revocation certificate not ready, calculating proof of work\n")); |
379 | pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, rd); | 379 | if (NULL == ph) |
380 | GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, rd); | 380 | { |
381 | GNUNET_REVOCATION_pow_init (privkey, | ||
382 | &proof_of_work); | ||
383 | ph = GNUNET_REVOCATION_pow_start (&proof_of_work, | ||
384 | epochs, /* Epochs */ | ||
385 | matching_bits); | ||
386 | } | ||
387 | pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph); | ||
388 | GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph); | ||
381 | } | 389 | } |
382 | 390 | ||
383 | 391 | ||
@@ -396,7 +404,6 @@ run (void *cls, | |||
396 | const struct GNUNET_CONFIGURATION_Handle *c) | 404 | const struct GNUNET_CONFIGURATION_Handle *c) |
397 | { | 405 | { |
398 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; | 406 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; |
399 | struct RevocationData rd; | ||
400 | 407 | ||
401 | cfg = c; | 408 | cfg = c; |
402 | if (NULL != test_ego) | 409 | if (NULL != test_ego) |
@@ -429,6 +436,17 @@ run (void *cls, | |||
429 | "WORKBITS"); | 436 | "WORKBITS"); |
430 | return; | 437 | return; |
431 | } | 438 | } |
439 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, | ||
440 | "REVOCATION", | ||
441 | "EPOCH_DURATION", | ||
442 | &epoch_duration)) | ||
443 | { | ||
444 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
445 | "REVOCATION", | ||
446 | "EPOCH_DURATION"); | ||
447 | return; | ||
448 | } | ||
449 | |||
432 | if (NULL != revoke_ego) | 450 | if (NULL != revoke_ego) |
433 | { | 451 | { |
434 | if (! perform && (NULL == filename)) | 452 | if (! perform && (NULL == filename)) |
@@ -445,7 +463,9 @@ run (void *cls, | |||
445 | } | 463 | } |
446 | if ((NULL != filename) && (perform)) | 464 | if ((NULL != filename) && (perform)) |
447 | { | 465 | { |
448 | if (sizeof(rd) != GNUNET_DISK_fn_read (filename, &rd, sizeof(rd))) | 466 | if (sizeof(proof_of_work) != GNUNET_DISK_fn_read (filename, |
467 | &proof_of_work, | ||
468 | sizeof(proof_of_work))) | ||
449 | { | 469 | { |
450 | fprintf (stderr, | 470 | fprintf (stderr, |
451 | _ ("Failed to read revocation certificate from `%s'\n"), | 471 | _ ("Failed to read revocation certificate from `%s'\n"), |
@@ -454,18 +474,20 @@ run (void *cls, | |||
454 | } | 474 | } |
455 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | 475 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); |
456 | if (GNUNET_YES != | 476 | if (GNUNET_YES != |
457 | GNUNET_REVOCATION_check_pow (&rd.key, | 477 | GNUNET_REVOCATION_check_pow (&proof_of_work, |
458 | rd.pow, | 478 | (unsigned int) matching_bits, |
459 | (unsigned int) matching_bits)) | 479 | epoch_duration)) |
460 | { | 480 | { |
461 | struct RevocationData *cp = GNUNET_new (struct RevocationData); | 481 | struct GNUNET_REVOCATION_PowCalculationHandle *ph; |
482 | ph = GNUNET_REVOCATION_pow_start (&proof_of_work, | ||
483 | epochs, /* Epochs */ | ||
484 | matching_bits); | ||
462 | 485 | ||
463 | *cp = rd; | 486 | pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph); |
464 | pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, cp); | 487 | GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph); |
465 | GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, cp); | ||
466 | return; | 488 | return; |
467 | } | 489 | } |
468 | perform_revocation (&rd); | 490 | perform_revocation (); |
469 | return; | 491 | return; |
470 | } | 492 | } |
471 | fprintf (stderr, "%s", _ ("No action specified. Nothing to do.\n")); | 493 | fprintf (stderr, "%s", _ ("No action specified. Nothing to do.\n")); |
@@ -511,6 +533,12 @@ main (int argc, char *const *argv) | |||
511 | gettext_noop ( | 533 | gettext_noop ( |
512 | "test if the public key KEY has been revoked"), | 534 | "test if the public key KEY has been revoked"), |
513 | &test_ego), | 535 | &test_ego), |
536 | GNUNET_GETOPT_option_uint ('e', | ||
537 | "epochs", | ||
538 | "EPOCHS", | ||
539 | gettext_noop ( | ||
540 | "number of epochs to calculate for"), | ||
541 | &epochs), | ||
514 | 542 | ||
515 | GNUNET_GETOPT_OPTION_END | 543 | GNUNET_GETOPT_OPTION_END |
516 | }; | 544 | }; |
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c index 3e811cd9a..3c08e8452 100644 --- a/src/revocation/gnunet-service-revocation.c +++ b/src/revocation/gnunet-service-revocation.c | |||
@@ -129,6 +129,11 @@ static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle; | |||
129 | static unsigned long long revocation_work_required; | 129 | static unsigned long long revocation_work_required; |
130 | 130 | ||
131 | /** | 131 | /** |
132 | * Length of an expiration expoch | ||
133 | */ | ||
134 | static struct GNUNET_TIME_Relative epoch_duration; | ||
135 | |||
136 | /** | ||
132 | * Our application ID for set union operations. Must be the | 137 | * Our application ID for set union operations. Must be the |
133 | * same for all (compatible) peers. | 138 | * same for all (compatible) peers. |
134 | */ | 139 | */ |
@@ -167,25 +172,15 @@ new_peer_entry (const struct GNUNET_PeerIdentity *peer) | |||
167 | static int | 172 | static int |
168 | verify_revoke_message (const struct RevokeMessage *rm) | 173 | verify_revoke_message (const struct RevokeMessage *rm) |
169 | { | 174 | { |
170 | if (GNUNET_YES != | 175 | if (GNUNET_YES != GNUNET_REVOCATION_check_pow (&rm->proof_of_work, |
171 | GNUNET_REVOCATION_check_pow (&rm->public_key, | 176 | (unsigned int) revocation_work_required, |
172 | rm->proof_of_work, | 177 | epoch_duration)) |
173 | (unsigned int) revocation_work_required)) | ||
174 | { | 178 | { |
175 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 179 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
176 | "Proof of work invalid!\n"); | 180 | "Proof of work invalid!\n"); |
177 | GNUNET_break_op (0); | 181 | GNUNET_break_op (0); |
178 | return GNUNET_NO; | 182 | return GNUNET_NO; |
179 | } | 183 | } |
180 | if (GNUNET_OK != | ||
181 | GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REVOCATION, | ||
182 | &rm->purpose, | ||
183 | &rm->signature, | ||
184 | &rm->public_key)) | ||
185 | { | ||
186 | GNUNET_break_op (0); | ||
187 | return GNUNET_NO; | ||
188 | } | ||
189 | return GNUNET_YES; | 184 | return GNUNET_YES; |
190 | } | 185 | } |
191 | 186 | ||
@@ -308,7 +303,7 @@ publicize_rm (const struct RevokeMessage *rm) | |||
308 | struct GNUNET_HashCode hc; | 303 | struct GNUNET_HashCode hc; |
309 | struct GNUNET_SET_Element e; | 304 | struct GNUNET_SET_Element e; |
310 | 305 | ||
311 | GNUNET_CRYPTO_hash (&rm->public_key, | 306 | GNUNET_CRYPTO_hash (&rm->proof_of_work.key, |
312 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), | 307 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), |
313 | &hc); | 308 | &hc); |
314 | if (GNUNET_YES == | 309 | if (GNUNET_YES == |
@@ -848,6 +843,20 @@ run (void *cls, | |||
848 | GNUNET_free (fn); | 843 | GNUNET_free (fn); |
849 | return; | 844 | return; |
850 | } | 845 | } |
846 | if (GNUNET_OK != | ||
847 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
848 | "REVOCATION", | ||
849 | "EPOCH_DURATION", | ||
850 | &epoch_duration)) | ||
851 | { | ||
852 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
853 | "REVOCATION", | ||
854 | "EPOCH_DURATION"); | ||
855 | GNUNET_SCHEDULER_shutdown (); | ||
856 | GNUNET_free (fn); | ||
857 | return; | ||
858 | } | ||
859 | |||
851 | revocation_set = GNUNET_SET_create (cfg, | 860 | revocation_set = GNUNET_SET_create (cfg, |
852 | GNUNET_SET_OPERATION_UNION); | 861 | GNUNET_SET_OPERATION_UNION); |
853 | revocation_union_listen_handle | 862 | revocation_union_listen_handle |
@@ -893,7 +902,7 @@ run (void *cls, | |||
893 | return; | 902 | return; |
894 | } | 903 | } |
895 | GNUNET_break (0 == ntohl (rm->reserved)); | 904 | GNUNET_break (0 == ntohl (rm->reserved)); |
896 | GNUNET_CRYPTO_hash (&rm->public_key, | 905 | GNUNET_CRYPTO_hash (&rm->proof_of_work.key, |
897 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), | 906 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), |
898 | &hc); | 907 | &hc); |
899 | GNUNET_break (GNUNET_OK == | 908 | GNUNET_break (GNUNET_OK == |
diff --git a/src/revocation/plugin_block_revocation.c b/src/revocation/plugin_block_revocation.c index 8d16b8781..291c56f70 100644 --- a/src/revocation/plugin_block_revocation.c +++ b/src/revocation/plugin_block_revocation.c | |||
@@ -52,6 +52,7 @@ | |||
52 | struct InternalContext | 52 | struct InternalContext |
53 | { | 53 | { |
54 | unsigned int matching_bits; | 54 | unsigned int matching_bits; |
55 | struct GNUNET_TIME_Relative epoch_duration; | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | 58 | ||
@@ -142,24 +143,15 @@ block_plugin_revocation_evaluate (void *cls, | |||
142 | GNUNET_break_op (0); | 143 | GNUNET_break_op (0); |
143 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | 144 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; |
144 | } | 145 | } |
145 | if (GNUNET_YES != | 146 | if (0 >= |
146 | GNUNET_REVOCATION_check_pow (&rm->public_key, | 147 | GNUNET_REVOCATION_check_pow (&rm->proof_of_work, |
147 | rm->proof_of_work, | 148 | ic->matching_bits, |
148 | ic->matching_bits)) | 149 | ic->epoch_duration)) |
149 | { | 150 | { |
150 | GNUNET_break_op (0); | 151 | GNUNET_break_op (0); |
151 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | 152 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; |
152 | } | 153 | } |
153 | if (GNUNET_OK != | 154 | GNUNET_CRYPTO_hash (&rm->proof_of_work.key, |
154 | GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REVOCATION, | ||
155 | &rm->purpose, | ||
156 | &rm->signature, | ||
157 | &rm->public_key)) | ||
158 | { | ||
159 | GNUNET_break_op (0); | ||
160 | return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; | ||
161 | } | ||
162 | GNUNET_CRYPTO_hash (&rm->public_key, | ||
163 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), | 155 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), |
164 | &chash); | 156 | &chash); |
165 | if (GNUNET_YES == | 157 | if (GNUNET_YES == |
@@ -195,7 +187,7 @@ block_plugin_revocation_get_key (void *cls, | |||
195 | GNUNET_break_op (0); | 187 | GNUNET_break_op (0); |
196 | return GNUNET_SYSERR; | 188 | return GNUNET_SYSERR; |
197 | } | 189 | } |
198 | GNUNET_CRYPTO_hash (&rm->public_key, | 190 | GNUNET_CRYPTO_hash (&rm->proof_of_work.key, |
199 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), | 191 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), |
200 | key); | 192 | key); |
201 | return GNUNET_OK; | 193 | return GNUNET_OK; |
@@ -218,6 +210,7 @@ libgnunet_plugin_block_revocation_init (void *cls) | |||
218 | struct GNUNET_BLOCK_PluginFunctions *api; | 210 | struct GNUNET_BLOCK_PluginFunctions *api; |
219 | struct InternalContext *ic; | 211 | struct InternalContext *ic; |
220 | unsigned long long matching_bits; | 212 | unsigned long long matching_bits; |
213 | struct GNUNET_TIME_Relative epoch_duration; | ||
221 | 214 | ||
222 | if (GNUNET_OK != | 215 | if (GNUNET_OK != |
223 | GNUNET_CONFIGURATION_get_value_number (cfg, | 216 | GNUNET_CONFIGURATION_get_value_number (cfg, |
@@ -225,6 +218,12 @@ libgnunet_plugin_block_revocation_init (void *cls) | |||
225 | "WORKBITS", | 218 | "WORKBITS", |
226 | &matching_bits)) | 219 | &matching_bits)) |
227 | return NULL; | 220 | return NULL; |
221 | if (GNUNET_OK != | ||
222 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
223 | "REVOCATION", | ||
224 | "EPOCH_DURATION", | ||
225 | &epoch_duration)) | ||
226 | return NULL; | ||
228 | 227 | ||
229 | api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); | 228 | api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); |
230 | api->evaluate = &block_plugin_revocation_evaluate; | 229 | api->evaluate = &block_plugin_revocation_evaluate; |
@@ -233,6 +232,7 @@ libgnunet_plugin_block_revocation_init (void *cls) | |||
233 | api->types = types; | 232 | api->types = types; |
234 | ic = GNUNET_new (struct InternalContext); | 233 | ic = GNUNET_new (struct InternalContext); |
235 | ic->matching_bits = (unsigned int) matching_bits; | 234 | ic->matching_bits = (unsigned int) matching_bits; |
235 | ic->epoch_duration = epoch_duration; | ||
236 | api->cls = ic; | 236 | api->cls = ic; |
237 | return api; | 237 | return api; |
238 | } | 238 | } |
diff --git a/src/revocation/revocation.conf.in b/src/revocation/revocation.conf.in index 5ad41cd49..346168785 100644 --- a/src/revocation/revocation.conf.in +++ b/src/revocation/revocation.conf.in | |||
@@ -14,5 +14,6 @@ UNIX_MATCH_GID = YES | |||
14 | # (using only a single-core) with SCRYPT. | 14 | # (using only a single-core) with SCRYPT. |
15 | # DO NOT CHANGE THIS VALUE, doing so will break the protocol! | 15 | # DO NOT CHANGE THIS VALUE, doing so will break the protocol! |
16 | WORKBITS = 25 | 16 | WORKBITS = 25 |
17 | EPOCH_DURATION = 356 d | ||
17 | 18 | ||
18 | DATABASE = $GNUNET_DATA_HOME/revocation.dat | 19 | DATABASE = $GNUNET_DATA_HOME/revocation.dat |
diff --git a/src/revocation/revocation.h b/src/revocation/revocation.h index b6e7a07ec..868c2b853 100644 --- a/src/revocation/revocation.h +++ b/src/revocation/revocation.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define REVOCATION_H | 27 | #define REVOCATION_H |
28 | 28 | ||
29 | #include "gnunet_util_lib.h" | 29 | #include "gnunet_util_lib.h" |
30 | #include "gnunet_revocation_service.h" | ||
30 | 31 | ||
31 | GNUNET_NETWORK_STRUCT_BEGIN | 32 | GNUNET_NETWORK_STRUCT_BEGIN |
32 | 33 | ||
@@ -91,23 +92,7 @@ struct RevokeMessage | |||
91 | /** | 92 | /** |
92 | * Number that causes a hash collision with the @e public_key. | 93 | * Number that causes a hash collision with the @e public_key. |
93 | */ | 94 | */ |
94 | uint64_t proof_of_work GNUNET_PACKED; | 95 | struct GNUNET_REVOCATION_Pow proof_of_work; |
95 | |||
96 | /** | ||
97 | * Signature confirming revocation. | ||
98 | */ | ||
99 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
100 | |||
101 | /** | ||
102 | * Must have purpose #GNUNET_SIGNATURE_PURPOSE_REVOCATION, | ||
103 | * size expands over the public key. (@deprecated) | ||
104 | */ | ||
105 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
106 | |||
107 | /** | ||
108 | * Key to revoke. | ||
109 | */ | ||
110 | struct GNUNET_CRYPTO_EcdsaPublicKey public_key; | ||
111 | }; | 96 | }; |
112 | 97 | ||
113 | 98 | ||
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c index 4755d4816..18a312ab8 100644 --- a/src/revocation/revocation_api.c +++ b/src/revocation/revocation_api.c | |||
@@ -27,8 +27,7 @@ | |||
27 | #include "gnunet_signatures.h" | 27 | #include "gnunet_signatures.h" |
28 | #include "gnunet_protocols.h" | 28 | #include "gnunet_protocols.h" |
29 | #include "revocation.h" | 29 | #include "revocation.h" |
30 | #include <gcrypt.h> | 30 | #include <inttypes.h> |
31 | |||
32 | 31 | ||
33 | /** | 32 | /** |
34 | * Handle for the key revocation query. | 33 | * Handle for the key revocation query. |
@@ -53,6 +52,58 @@ struct GNUNET_REVOCATION_Query | |||
53 | 52 | ||
54 | 53 | ||
55 | /** | 54 | /** |
55 | * Helper struct that holds a found pow nonce | ||
56 | * and the corresponding number of leading zeroes. | ||
57 | */ | ||
58 | struct BestPow | ||
59 | { | ||
60 | /** | ||
61 | * PoW nonce | ||
62 | */ | ||
63 | uint64_t pow; | ||
64 | |||
65 | /** | ||
66 | * Corresponding zero bits in hash | ||
67 | */ | ||
68 | unsigned int bits; | ||
69 | }; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * The handle to a PoW calculation. | ||
74 | * Used in iterative PoW rounds. | ||
75 | */ | ||
76 | struct GNUNET_REVOCATION_PowCalculationHandle | ||
77 | { | ||
78 | /** | ||
79 | * Current set of found PoWs | ||
80 | */ | ||
81 | struct BestPow best[POW_COUNT]; | ||
82 | |||
83 | /** | ||
84 | * The final PoW result data structure. | ||
85 | */ | ||
86 | struct GNUNET_REVOCATION_Pow *pow; | ||
87 | |||
88 | /** | ||
89 | * The current nonce to try | ||
90 | */ | ||
91 | uint64_t current_pow; | ||
92 | |||
93 | /** | ||
94 | * Epochs how long the PoW should be valid. | ||
95 | * This is added on top of the difficulty in the PoW. | ||
96 | */ | ||
97 | unsigned int epochs; | ||
98 | |||
99 | /** | ||
100 | * The difficulty (leading zeros) to achieve. | ||
101 | */ | ||
102 | unsigned int difficulty; | ||
103 | |||
104 | }; | ||
105 | |||
106 | /** | ||
56 | * Generic error handler, called with the appropriate | 107 | * Generic error handler, called with the appropriate |
57 | * error code and the same closure specified at the creation of | 108 | * error code and the same closure specified at the creation of |
58 | * the message queue. | 109 | * the message queue. |
@@ -235,6 +286,7 @@ handle_revocation_response (void *cls, | |||
235 | * @param key public key of the key to revoke | 286 | * @param key public key of the key to revoke |
236 | * @param sig signature to use on the revocation (should have been | 287 | * @param sig signature to use on the revocation (should have been |
237 | * created using #GNUNET_REVOCATION_sign_revocation). | 288 | * created using #GNUNET_REVOCATION_sign_revocation). |
289 | * @param ts revocation timestamp | ||
238 | * @param pow proof of work to use (should have been created by | 290 | * @param pow proof of work to use (should have been created by |
239 | * iteratively calling #GNUNET_REVOCATION_check_pow) | 291 | * iteratively calling #GNUNET_REVOCATION_check_pow) |
240 | * @param func funtion to call with the result of the check | 292 | * @param func funtion to call with the result of the check |
@@ -245,9 +297,7 @@ handle_revocation_response (void *cls, | |||
245 | */ | 297 | */ |
246 | struct GNUNET_REVOCATION_Handle * | 298 | struct GNUNET_REVOCATION_Handle * |
247 | GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, | 299 | GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, |
248 | const struct GNUNET_CRYPTO_EcdsaPublicKey *key, | 300 | const struct GNUNET_REVOCATION_Pow *pow, |
249 | const struct GNUNET_CRYPTO_EcdsaSignature *sig, | ||
250 | uint64_t pow, | ||
251 | GNUNET_REVOCATION_Callback func, | 301 | GNUNET_REVOCATION_Callback func, |
252 | void *func_cls) | 302 | void *func_cls) |
253 | { | 303 | { |
@@ -261,23 +311,39 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
261 | GNUNET_MQ_handler_end () | 311 | GNUNET_MQ_handler_end () |
262 | }; | 312 | }; |
263 | unsigned long long matching_bits; | 313 | unsigned long long matching_bits; |
314 | struct GNUNET_TIME_Relative epoch_duration; | ||
264 | struct RevokeMessage *rm; | 315 | struct RevokeMessage *rm; |
265 | struct GNUNET_MQ_Envelope *env; | 316 | struct GNUNET_MQ_Envelope *env; |
266 | 317 | ||
267 | if ((GNUNET_OK == | 318 | if ((GNUNET_OK != |
268 | GNUNET_CONFIGURATION_get_value_number (cfg, | 319 | GNUNET_CONFIGURATION_get_value_number (cfg, |
269 | "REVOCATION", | 320 | "REVOCATION", |
270 | "WORKBITS", | 321 | "WORKBITS", |
271 | &matching_bits)) && | 322 | &matching_bits))) |
272 | (GNUNET_YES != | 323 | { |
273 | GNUNET_REVOCATION_check_pow (key, | 324 | GNUNET_break (0); |
274 | pow, | 325 | GNUNET_free (h); |
275 | (unsigned int) matching_bits))) | 326 | return NULL; |
327 | } | ||
328 | if ((GNUNET_OK != | ||
329 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
330 | "REVOCATION", | ||
331 | "EPOCH_DURATION", | ||
332 | &epoch_duration))) | ||
276 | { | 333 | { |
277 | GNUNET_break (0); | 334 | GNUNET_break (0); |
278 | GNUNET_free (h); | 335 | GNUNET_free (h); |
279 | return NULL; | 336 | return NULL; |
280 | } | 337 | } |
338 | if (GNUNET_YES != GNUNET_REVOCATION_check_pow (pow, | ||
339 | (unsigned int) matching_bits, | ||
340 | epoch_duration)) | ||
341 | { | ||
342 | GNUNET_break (0); | ||
343 | GNUNET_free (h); | ||
344 | return NULL; | ||
345 | } | ||
346 | |||
281 | 347 | ||
282 | h->mq = GNUNET_CLIENT_connect (cfg, | 348 | h->mq = GNUNET_CLIENT_connect (cfg, |
283 | "revocation", | 349 | "revocation", |
@@ -294,12 +360,7 @@ GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
294 | env = GNUNET_MQ_msg (rm, | 360 | env = GNUNET_MQ_msg (rm, |
295 | GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); | 361 | GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); |
296 | rm->reserved = htonl (0); | 362 | rm->reserved = htonl (0); |
297 | rm->proof_of_work = pow; | 363 | rm->proof_of_work = *pow; |
298 | rm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); | ||
299 | rm->purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | ||
300 | + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
301 | rm->public_key = *key; | ||
302 | rm->signature = *sig; | ||
303 | GNUNET_MQ_send (h->mq, | 364 | GNUNET_MQ_send (h->mq, |
304 | env); | 365 | env); |
305 | return h; | 366 | return h; |
@@ -342,56 +403,263 @@ count_leading_zeroes (const struct GNUNET_HashCode *hash) | |||
342 | 403 | ||
343 | 404 | ||
344 | /** | 405 | /** |
345 | * Check if the given proof-of-work value | 406 | * Calculate the average zeros in the pows. |
346 | * would be acceptable for revoking the given key. | ||
347 | * | 407 | * |
348 | * @param key key to check for | 408 | * @param ph the PowHandle |
349 | * @param pow proof of work value | 409 | * @return the average number of zeroes. |
410 | */ | ||
411 | static unsigned int | ||
412 | calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph) | ||
413 | { | ||
414 | double sum = 0.0; | ||
415 | for (unsigned int j = 0; j<POW_COUNT; j++) | ||
416 | sum += ph->best[j].bits; | ||
417 | double avg = sum / POW_COUNT; | ||
418 | return avg; | ||
419 | } | ||
420 | |||
421 | |||
422 | /** | ||
423 | * Check if the given proof-of-work is valid. | ||
424 | * | ||
425 | * @param pow proof of work | ||
350 | * @param matching_bits how many bits must match (configuration) | 426 | * @param matching_bits how many bits must match (configuration) |
427 | * @param epoch_duration length of single epoch in configuration | ||
428 | * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not | ||
429 | */ | ||
430 | enum GNUNET_GenericReturnValue | ||
431 | GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_Pow *pow, | ||
432 | unsigned int difficulty, | ||
433 | struct GNUNET_TIME_Relative epoch_duration) | ||
434 | { | ||
435 | char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) | ||
436 | + sizeof (struct GNUNET_TIME_AbsoluteNBO) | ||
437 | + sizeof (uint64_t)] GNUNET_ALIGN; | ||
438 | struct GNUNET_REVOCATION_SignaturePurpose spurp; | ||
439 | struct GNUNET_HashCode result; | ||
440 | struct GNUNET_TIME_Absolute ts; | ||
441 | struct GNUNET_TIME_Absolute exp; | ||
442 | struct GNUNET_TIME_Relative ttl; | ||
443 | struct GNUNET_TIME_Relative buffer; | ||
444 | unsigned int score = 0; | ||
445 | unsigned int tmp_score = 0; | ||
446 | unsigned int epochs; | ||
447 | uint64_t pow_val; | ||
448 | |||
449 | /** | ||
450 | * Check if signature valid | ||
451 | */ | ||
452 | spurp.key = pow->key; | ||
453 | spurp.timestamp = pow->timestamp; | ||
454 | spurp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); | ||
455 | spurp.purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | ||
456 | + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) | ||
457 | + sizeof (struct GNUNET_TIME_AbsoluteNBO)); | ||
458 | if (GNUNET_OK != | ||
459 | GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REVOCATION, | ||
460 | &spurp.purpose, | ||
461 | &pow->signature, | ||
462 | &pow->key)) | ||
463 | { | ||
464 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
465 | "Proof of work signature invalid!\n"); | ||
466 | return GNUNET_NO; | ||
467 | } | ||
468 | |||
469 | /** | ||
470 | * First, check if any duplicates are in the PoW set | ||
471 | */ | ||
472 | for (unsigned int i = 0; i < POW_COUNT; i++) | ||
473 | { | ||
474 | for (unsigned int j = i + 1; j < POW_COUNT; j++) | ||
475 | { | ||
476 | if (pow->pow[i] == pow->pow[j]) | ||
477 | return GNUNET_NO; | ||
478 | } | ||
479 | } | ||
480 | GNUNET_memcpy (&buf[sizeof(uint64_t)], | ||
481 | &pow->timestamp, | ||
482 | sizeof (uint64_t)); | ||
483 | GNUNET_memcpy (&buf[sizeof(uint64_t) * 2], | ||
484 | &pow->key, | ||
485 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
486 | for (unsigned int i = 0; i < POW_COUNT; i++) | ||
487 | { | ||
488 | pow_val = GNUNET_ntohll (pow->pow[i]); | ||
489 | GNUNET_memcpy (buf, &pow_val, sizeof(uint64_t)); | ||
490 | GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work", | ||
491 | buf, | ||
492 | sizeof(buf), | ||
493 | &result); | ||
494 | tmp_score = count_leading_zeroes (&result); | ||
495 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
496 | "Score %u with %" PRIu64 " (#%u)\n", | ||
497 | tmp_score, pow_val, i); | ||
498 | score += tmp_score; | ||
499 | |||
500 | } | ||
501 | score = score / POW_COUNT; | ||
502 | if (score < difficulty) | ||
503 | return GNUNET_NO; | ||
504 | epochs = score - difficulty; | ||
505 | |||
506 | /** | ||
507 | * Check expiration | ||
508 | */ | ||
509 | ts = GNUNET_TIME_absolute_ntoh (pow->timestamp); | ||
510 | ttl = GNUNET_TIME_relative_multiply (epoch_duration, | ||
511 | epochs); | ||
512 | /** | ||
513 | * Extend by 10% for unsynchronized clocks | ||
514 | */ | ||
515 | buffer = GNUNET_TIME_relative_divide (epoch_duration, | ||
516 | 10); | ||
517 | exp = GNUNET_TIME_absolute_add (ts, ttl); | ||
518 | exp = GNUNET_TIME_absolute_add (exp, | ||
519 | buffer); | ||
520 | |||
521 | if (0 != GNUNET_TIME_absolute_get_remaining (ts).rel_value_us) | ||
522 | return GNUNET_NO; /* Not yet valid. */ | ||
523 | /* Revert to actual start time */ | ||
524 | ts = GNUNET_TIME_absolute_add (ts, | ||
525 | buffer); | ||
526 | |||
527 | if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us) | ||
528 | return GNUNET_NO; /* expired */ | ||
529 | return GNUNET_YES; | ||
530 | } | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Initializes a fresh PoW computation. | ||
535 | * | ||
536 | * @param key the key to calculate the PoW for. | ||
537 | * @param[out] pow starting point for PoW calculation (not yet valid) | ||
538 | */ | ||
539 | void | ||
540 | GNUNET_REVOCATION_pow_init (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | ||
541 | struct GNUNET_REVOCATION_Pow *pow) | ||
542 | { | ||
543 | struct GNUNET_TIME_Absolute ts = GNUNET_TIME_absolute_get (); | ||
544 | struct GNUNET_REVOCATION_SignaturePurpose rp; | ||
545 | |||
546 | /** | ||
547 | * Predate the validity period to prevent rejections due to | ||
548 | * unsynchronized clocks | ||
549 | */ | ||
550 | ts = GNUNET_TIME_absolute_subtract (ts, | ||
551 | GNUNET_TIME_UNIT_WEEKS); | ||
552 | |||
553 | pow->timestamp = GNUNET_TIME_absolute_hton (ts); | ||
554 | rp.timestamp = pow->timestamp; | ||
555 | rp.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); | ||
556 | rp.purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | ||
557 | + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) | ||
558 | + sizeof (struct GNUNET_TIME_AbsoluteNBO)); | ||
559 | GNUNET_CRYPTO_ecdsa_key_get_public (key, &pow->key); | ||
560 | rp.key = pow->key; | ||
561 | GNUNET_assert (GNUNET_OK == | ||
562 | GNUNET_CRYPTO_ecdsa_sign_ (key, | ||
563 | &rp.purpose, | ||
564 | &pow->signature)); | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * Starts a proof-of-work calculation given the pow object as well as | ||
570 | * target epochs and difficulty. | ||
571 | * | ||
572 | * @param pow the PoW to based calculations on. | ||
573 | * @param epochs the number of epochs for which the PoW must be valid. | ||
574 | * @param difficulty the base difficulty of the PoW. | ||
575 | * @return a handle for use in PoW rounds | ||
576 | */ | ||
577 | struct GNUNET_REVOCATION_PowCalculationHandle* | ||
578 | GNUNET_REVOCATION_pow_start (struct GNUNET_REVOCATION_Pow *pow, | ||
579 | int epochs, | ||
580 | unsigned int difficulty) | ||
581 | { | ||
582 | struct GNUNET_REVOCATION_PowCalculationHandle *pc; | ||
583 | |||
584 | pc = GNUNET_new (struct GNUNET_REVOCATION_PowCalculationHandle); | ||
585 | pc->pow = pow; | ||
586 | pc->current_pow = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
587 | UINT64_MAX); | ||
588 | pc->difficulty = difficulty; | ||
589 | pc->epochs = epochs; | ||
590 | return pc; | ||
591 | } | ||
592 | |||
593 | |||
594 | /** | ||
595 | * Calculate a key revocation valid for broadcasting for a number | ||
596 | * of epochs. | ||
597 | * | ||
598 | * @param pc handle to the PoW, initially called with NULL. | ||
599 | * @param epochs number of epochs for which the revocation must be valid. | ||
600 | * @param pow current pow value to try | ||
601 | * @param difficulty current base difficulty to achieve | ||
351 | * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not | 602 | * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not |
352 | */ | 603 | */ |
353 | int | 604 | enum GNUNET_GenericReturnValue |
354 | GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, | 605 | GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc) |
355 | uint64_t pow, | ||
356 | unsigned int matching_bits) | ||
357 | { | 606 | { |
358 | char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) | 607 | char buf[sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey) |
359 | + sizeof(pow)] GNUNET_ALIGN; | 608 | + sizeof (uint64_t) |
609 | + sizeof (uint64_t)] GNUNET_ALIGN; | ||
360 | struct GNUNET_HashCode result; | 610 | struct GNUNET_HashCode result; |
611 | unsigned int zeros; | ||
612 | |||
613 | pc->current_pow++; | ||
361 | 614 | ||
362 | GNUNET_memcpy (buf, &pow, sizeof(pow)); | 615 | /** |
363 | GNUNET_memcpy (&buf[sizeof(pow)], key, | 616 | * Do not try duplicates |
617 | */ | ||
618 | for (unsigned int i = 0; i < POW_COUNT; i++) | ||
619 | if (pc->current_pow == pc->best[i].pow) | ||
620 | return GNUNET_NO; | ||
621 | |||
622 | GNUNET_memcpy (buf, &pc->current_pow, sizeof(uint64_t)); | ||
623 | GNUNET_memcpy (&buf[sizeof(uint64_t)], | ||
624 | &pc->pow->timestamp, | ||
625 | sizeof (uint64_t)); | ||
626 | GNUNET_memcpy (&buf[sizeof(uint64_t) * 2], | ||
627 | &pc->pow->key, | ||
364 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); | 628 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); |
365 | GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work", | 629 | GNUNET_CRYPTO_pow_hash ("gnunet-revocation-proof-of-work", |
366 | buf, | 630 | buf, |
367 | sizeof(buf), | 631 | sizeof(buf), |
368 | &result); | 632 | &result); |
369 | return (count_leading_zeroes (&result) >= | 633 | zeros = count_leading_zeroes (&result); |
370 | matching_bits) ? GNUNET_YES : GNUNET_NO; | 634 | for (unsigned int i = 0; i < POW_COUNT; i++) |
635 | { | ||
636 | if (pc->best[i].bits < zeros) | ||
637 | { | ||
638 | pc->best[i].bits = zeros; | ||
639 | pc->best[i].pow = pc->current_pow; | ||
640 | pc->pow->pow[i] = GNUNET_htonll (pc->current_pow); | ||
641 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
642 | "New best score %u with %" PRIu64 " (#%u)\n", | ||
643 | zeros, pc->current_pow, i); | ||
644 | break; | ||
645 | } | ||
646 | } | ||
647 | return calculate_score (pc) >= pc->difficulty + pc->epochs ? GNUNET_YES : | ||
648 | GNUNET_NO; | ||
371 | } | 649 | } |
372 | 650 | ||
373 | 651 | ||
374 | /** | 652 | /** |
375 | * Create a revocation signature. | 653 | * Stop a PoW calculation |
376 | * | 654 | * |
377 | * @param key private key of the key to revoke | 655 | * @param pc the calculation to clean up |
378 | * @param sig where to write the revocation signature | 656 | * @return #GNUNET_YES if pow valid, #GNUNET_NO if pow was set but is not |
657 | * valid | ||
379 | */ | 658 | */ |
380 | void | 659 | void |
381 | GNUNET_REVOCATION_sign_revocation (const struct | 660 | GNUNET_REVOCATION_pow_stop (struct GNUNET_REVOCATION_PowCalculationHandle *pc) |
382 | GNUNET_CRYPTO_EcdsaPrivateKey *key, | ||
383 | struct GNUNET_CRYPTO_EcdsaSignature *sig) | ||
384 | { | 661 | { |
385 | struct RevokeMessage rm; | 662 | GNUNET_free (pc); |
386 | |||
387 | rm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); | ||
388 | rm.purpose.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | ||
389 | + sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
390 | GNUNET_CRYPTO_ecdsa_key_get_public (key, &rm.public_key); | ||
391 | GNUNET_assert (GNUNET_OK == | ||
392 | GNUNET_CRYPTO_ecdsa_sign_ (key, | ||
393 | &rm.purpose, | ||
394 | sig)); | ||
395 | } | 663 | } |
396 | 664 | ||
397 | 665 | ||
diff --git a/src/revocation/test_revocation.c b/src/revocation/test_revocation.c index 012bac09e..f193d5f6c 100644 --- a/src/revocation/test_revocation.c +++ b/src/revocation/test_revocation.c | |||
@@ -45,7 +45,7 @@ struct TestPeer | |||
45 | struct GNUNET_IDENTITY_EgoLookup *ego_lookup; | 45 | struct GNUNET_IDENTITY_EgoLookup *ego_lookup; |
46 | struct GNUNET_REVOCATION_Handle *revok_handle; | 46 | struct GNUNET_REVOCATION_Handle *revok_handle; |
47 | struct GNUNET_CORE_Handle *ch; | 47 | struct GNUNET_CORE_Handle *ch; |
48 | uint64_t pow; | 48 | struct GNUNET_REVOCATION_PowCalculationHandle *pow; |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static struct TestPeer testpeers[2]; | 51 | static struct TestPeer testpeers[2]; |
@@ -131,7 +131,7 @@ check_revocation (void *cls) | |||
131 | 131 | ||
132 | 132 | ||
133 | static void | 133 | static void |
134 | revocation_cb (void *cls, int is_valid) | 134 | revocation_cb (void *cls, enum GNUNET_GenericReturnValue is_valid) |
135 | { | 135 | { |
136 | testpeers[1].revok_handle = NULL; | 136 | testpeers[1].revok_handle = NULL; |
137 | if (GNUNET_NO == is_valid) | 137 | if (GNUNET_NO == is_valid) |
@@ -141,11 +141,14 @@ revocation_cb (void *cls, int is_valid) | |||
141 | } | 141 | } |
142 | } | 142 | } |
143 | 143 | ||
144 | struct GNUNET_REVOCATION_Pow proof_of_work; | ||
145 | |||
144 | 146 | ||
145 | static void | 147 | static void |
146 | ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) | 148 | ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) |
147 | { | 149 | { |
148 | static int completed = 0; | 150 | static int completed = 0; |
151 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; | ||
149 | 152 | ||
150 | if ((NULL != ego) && (cls == &testpeers[0])) | 153 | if ((NULL != ego) && (cls == &testpeers[0])) |
151 | { | 154 | { |
@@ -159,17 +162,20 @@ ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) | |||
159 | testpeers[1].ego_lookup = NULL; | 162 | testpeers[1].ego_lookup = NULL; |
160 | testpeers[1].privkey = GNUNET_IDENTITY_ego_get_private_key (ego); | 163 | testpeers[1].privkey = GNUNET_IDENTITY_ego_get_private_key (ego); |
161 | GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[1].pubkey); | 164 | GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[1].pubkey); |
162 | GNUNET_REVOCATION_sign_revocation (testpeers[1].privkey, &testpeers[1].sig); | ||
163 | |||
164 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Calculating proof of work...\n"); | 165 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Calculating proof of work...\n"); |
165 | testpeers[1].pow = 0; | 166 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego); |
167 | memset (&proof_of_work, 0, sizeof (proof_of_work)); | ||
168 | GNUNET_REVOCATION_pow_init (privkey, | ||
169 | &proof_of_work); | ||
170 | testpeers[1].pow = GNUNET_REVOCATION_pow_start (&proof_of_work, | ||
171 | 1, | ||
172 | 5); | ||
166 | int res = | 173 | int res = |
167 | GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey, testpeers[1].pow, 5); | 174 | GNUNET_REVOCATION_pow_round (testpeers[1].pow); |
168 | while (GNUNET_OK != res) | 175 | while (GNUNET_OK != res) |
169 | { | 176 | { |
170 | testpeers[1].pow++; | ||
171 | res = | 177 | res = |
172 | GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey, testpeers[1].pow, 5); | 178 | GNUNET_REVOCATION_pow_round (testpeers[1].pow); |
173 | } | 179 | } |
174 | fprintf (stderr, "Done calculating proof of work\n"); | 180 | fprintf (stderr, "Done calculating proof of work\n"); |
175 | completed++; | 181 | completed++; |
@@ -178,11 +184,10 @@ ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) | |||
178 | { | 184 | { |
179 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Egos retrieved\n"); | 185 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Egos retrieved\n"); |
180 | testpeers[1].revok_handle = GNUNET_REVOCATION_revoke (testpeers[1].cfg, | 186 | testpeers[1].revok_handle = GNUNET_REVOCATION_revoke (testpeers[1].cfg, |
181 | &testpeers[1].pubkey, | 187 | &proof_of_work, |
182 | &testpeers[1].sig, | ||
183 | testpeers[1].pow, | ||
184 | &revocation_cb, | 188 | &revocation_cb, |
185 | NULL); | 189 | NULL); |
190 | GNUNET_REVOCATION_pow_stop (testpeers[1].pow); | ||
186 | } | 191 | } |
187 | } | 192 | } |
188 | 193 | ||
diff --git a/src/revocation/test_revocation.conf b/src/revocation/test_revocation.conf index 3b04150c1..66e2cdcc9 100644 --- a/src/revocation/test_revocation.conf +++ b/src/revocation/test_revocation.conf | |||
@@ -7,6 +7,7 @@ SERVICEHOME=$GNUNET_TMP/test-revocation-service | |||
7 | [revocation] | 7 | [revocation] |
8 | WORKBITS = 3 | 8 | WORKBITS = 3 |
9 | IMMEDIATE_START = YES | 9 | IMMEDIATE_START = YES |
10 | EPOCH_DURATION = 365 d | ||
10 | 11 | ||
11 | [identity] | 12 | [identity] |
12 | # Directory where we store information about our egos | 13 | # Directory where we store information about our egos |