aboutsummaryrefslogtreecommitdiff
path: root/src/revocation/revocation_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/revocation/revocation_api.c')
-rw-r--r--src/revocation/revocation_api.c793
1 files changed, 0 insertions, 793 deletions
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
deleted file mode 100644
index f2b95bafa..000000000
--- a/src/revocation/revocation_api.c
+++ /dev/null
@@ -1,793 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file revocation/revocation_api.c
22 * @brief API to perform and access key revocations
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_revocation_service.h"
27#include "gnunet_signatures.h"
28#include "gnunet_protocols.h"
29#include "revocation.h"
30#include <inttypes.h>
31
32/**
33 * Handle for the key revocation query.
34 */
35struct GNUNET_REVOCATION_Query
36{
37 /**
38 * Message queue to the service.
39 */
40 struct GNUNET_MQ_Handle *mq;
41
42 /**
43 * Function to call with the result.
44 */
45 GNUNET_REVOCATION_Callback func;
46
47 /**
48 * Closure for @e func.
49 */
50 void *func_cls;
51};
52
53
54/**
55 * Helper struct that holds a found pow nonce
56 * and the corresponding number of leading zeroes.
57 */
58struct 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 */
76struct 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_PowP *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
106static struct GNUNET_CRYPTO_PowSalt salt = { "GnsRevocationPow" };
107
108/**
109 * Generic error handler, called with the appropriate
110 * error code and the same closure specified at the creation of
111 * the message queue.
112 * Not every message queue implementation supports an error handler.
113 *
114 * @param cls closure with the `struct GNUNET_NSE_Handle *`
115 * @param error error code
116 */
117static void
118query_mq_error_handler (void *cls,
119 enum GNUNET_MQ_Error error)
120{
121 struct GNUNET_REVOCATION_Query *q = cls;
122
123 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
124 "Revocation query MQ error\n");
125 q->func (q->func_cls,
126 GNUNET_SYSERR);
127 GNUNET_REVOCATION_query_cancel (q);
128}
129
130
131/**
132 * Handle response to our revocation query.
133 *
134 * @param cls our `struct GNUNET_REVOCATION_Query` handle
135 * @param qrm response we got
136 */
137static void
138handle_revocation_query_response (void *cls,
139 const struct QueryResponseMessage *qrm)
140{
141 struct GNUNET_REVOCATION_Query *q = cls;
142
143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
144 "Revocation query result: %d\n",
145 (uint32_t) ntohl (qrm->is_valid));
146 q->func (q->func_cls,
147 ntohl (qrm->is_valid));
148 GNUNET_REVOCATION_query_cancel (q);
149}
150
151
152/**
153 * Check if a key was revoked.
154 *
155 * @param cfg the configuration to use
156 * @param key key to check for revocation
157 * @param func function to call with the result of the check
158 * @param func_cls closure to pass to @a func
159 * @return handle to use in #GNUNET_REVOCATION_query_cancel to stop REVOCATION from invoking the callback
160 */
161struct GNUNET_REVOCATION_Query *
162GNUNET_REVOCATION_query (const struct GNUNET_CONFIGURATION_Handle *cfg,
163 const struct GNUNET_IDENTITY_PublicKey *key,
164 GNUNET_REVOCATION_Callback func,
165 void *func_cls)
166{
167 struct GNUNET_REVOCATION_Query *q
168 = GNUNET_new (struct GNUNET_REVOCATION_Query);
169 struct GNUNET_MQ_MessageHandler handlers[] = {
170 GNUNET_MQ_hd_fixed_size (revocation_query_response,
171 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE,
172 struct QueryResponseMessage,
173 q),
174 GNUNET_MQ_handler_end ()
175 };
176 struct QueryMessage *qm;
177 struct GNUNET_MQ_Envelope *env;
178
179 q->mq = GNUNET_CLIENT_connect (cfg,
180 "revocation",
181 handlers,
182 &query_mq_error_handler,
183 q);
184 if (NULL == q->mq)
185 {
186 GNUNET_free (q);
187 return NULL;
188 }
189 q->func = func;
190 q->func_cls = func_cls;
191 env = GNUNET_MQ_msg (qm,
192 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY);
193 qm->reserved = htonl (0);
194 qm->key = *key;
195 GNUNET_MQ_send (q->mq,
196 env);
197 return q;
198}
199
200
201/**
202 * Cancel key revocation check.
203 *
204 * @param q query to cancel
205 */
206void
207GNUNET_REVOCATION_query_cancel (struct GNUNET_REVOCATION_Query *q)
208{
209 if (NULL != q->mq)
210 {
211 GNUNET_MQ_destroy (q->mq);
212 q->mq = NULL;
213 }
214 GNUNET_free (q);
215}
216
217
218/**
219 * Handle for the key revocation operation.
220 */
221struct GNUNET_REVOCATION_Handle
222{
223 /**
224 * Message queue to the service.
225 */
226 struct GNUNET_MQ_Handle *mq;
227
228 /**
229 * Function to call once we are done.
230 */
231 GNUNET_REVOCATION_Callback func;
232
233 /**
234 * Closure for @e func.
235 */
236 void *func_cls;
237};
238
239
240/**
241 * Generic error handler, called with the appropriate
242 * error code and the same closure specified at the creation of
243 * the message queue.
244 * Not every message queue implementation supports an error handler.
245 *
246 * @param cls closure with the `struct GNUNET_NSE_Handle *`
247 * @param error error code
248 */
249static void
250revocation_mq_error_handler (void *cls,
251 enum GNUNET_MQ_Error error)
252{
253 struct GNUNET_REVOCATION_Handle *h = cls;
254
255 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
256 "Revocation MQ error\n");
257 h->func (h->func_cls,
258 GNUNET_SYSERR);
259 GNUNET_REVOCATION_revoke_cancel (h);
260}
261
262
263/**
264 * Handle response to our revocation query.
265 *
266 * @param cls our `struct GNUNET_REVOCATION_Handle` handle
267 * @param rrm response we got
268 */
269static void
270handle_revocation_response (void *cls,
271 const struct RevocationResponseMessage *rrm)
272{
273 struct GNUNET_REVOCATION_Handle *h = cls;
274
275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
276 "Revocation transmission result: %d\n",
277 (uint32_t) ntohl (rrm->is_valid));
278 h->func (h->func_cls,
279 ntohl (rrm->is_valid));
280 GNUNET_REVOCATION_revoke_cancel (h);
281}
282
283
284/**
285 * Perform key revocation.
286 *
287 * @param cfg the configuration to use
288 * @param key public key of the key to revoke
289 * @param sig signature to use on the revocation (should have been
290 * created using #GNUNET_REVOCATION_sign_revocation).
291 * @param ts revocation timestamp
292 * @param pow proof of work to use (should have been created by
293 * iteratively calling #GNUNET_REVOCATION_check_pow)
294 * @param func function to call with the result of the check
295 * (called with `is_valid` being #GNUNET_NO if
296 * the revocation worked).
297 * @param func_cls closure to pass to @a func
298 * @return handle to use in #GNUNET_REVOCATION_revoke_cancel to stop REVOCATION from invoking the callback
299 */
300struct GNUNET_REVOCATION_Handle *
301GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
302 const struct GNUNET_REVOCATION_PowP *pow,
303 GNUNET_REVOCATION_Callback func,
304 void *func_cls)
305{
306 struct GNUNET_REVOCATION_Handle *h
307 = GNUNET_new (struct GNUNET_REVOCATION_Handle);
308 struct GNUNET_MQ_MessageHandler handlers[] = {
309 GNUNET_MQ_hd_fixed_size (revocation_response,
310 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE,
311 struct RevocationResponseMessage,
312 h),
313 GNUNET_MQ_handler_end ()
314 };
315 unsigned long long matching_bits;
316 struct GNUNET_TIME_Relative epoch_duration;
317 struct RevokeMessage *rm;
318 struct GNUNET_MQ_Envelope *env;
319
320 if ((GNUNET_OK !=
321 GNUNET_CONFIGURATION_get_value_number (cfg,
322 "REVOCATION",
323 "WORKBITS",
324 &matching_bits)))
325 {
326 GNUNET_break (0);
327 GNUNET_free (h);
328 return NULL;
329 }
330 if ((GNUNET_OK !=
331 GNUNET_CONFIGURATION_get_value_time (cfg,
332 "REVOCATION",
333 "EPOCH_DURATION",
334 &epoch_duration)))
335 {
336 GNUNET_break (0);
337 GNUNET_free (h);
338 return NULL;
339 }
340 if (GNUNET_YES != GNUNET_REVOCATION_check_pow (pow,
341 (unsigned int) matching_bits,
342 epoch_duration))
343 {
344 GNUNET_break (0);
345 GNUNET_free (h);
346 return NULL;
347 }
348
349
350 h->mq = GNUNET_CLIENT_connect (cfg,
351 "revocation",
352 handlers,
353 &revocation_mq_error_handler,
354 h);
355 if (NULL == h->mq)
356 {
357 GNUNET_free (h);
358 return NULL;
359 }
360 h->func = func;
361 h->func_cls = func_cls;
362 size_t extra_len = GNUNET_REVOCATION_proof_get_size (pow);
363 env = GNUNET_MQ_msg_extra (rm,
364 extra_len,
365 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
366 rm->pow_size = htonl (extra_len);
367 memcpy (&rm[1], pow, extra_len);
368 GNUNET_MQ_send (h->mq,
369 env);
370 return h;
371}
372
373
374/**
375 * Cancel key revocation.
376 *
377 * @param h operation to cancel
378 */
379void
380GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h)
381{
382 if (NULL != h->mq)
383 {
384 GNUNET_MQ_destroy (h->mq);
385 h->mq = NULL;
386 }
387 GNUNET_free (h);
388}
389
390
391/**
392 * Count the leading zeroes in hash.
393 *
394 * @param hash to count leading zeros in
395 * @return the number of leading zero bits.
396 */
397static unsigned int
398count_leading_zeroes (const struct GNUNET_HashCode *hash)
399{
400 unsigned int hash_count;
401 hash_count = 0;
402 while ((0 == GNUNET_CRYPTO_hash_get_bit_ltr (hash, hash_count)))
403 hash_count++;
404 return hash_count;
405}
406
407
408/**
409 * Calculate the average zeros in the pows.
410 *
411 * @param ph the PowHandle
412 * @return the average number of zeroes.
413 */
414static unsigned int
415calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph)
416{
417 double sum = 0.0;
418 for (unsigned int j = 0; j<POW_COUNT; j++)
419 sum += ph->best[j].bits;
420 double avg = sum / POW_COUNT;
421 return avg;
422}
423
424
425enum GNUNET_GenericReturnValue
426check_signature_identity (const struct GNUNET_REVOCATION_PowP *pow,
427 const struct GNUNET_IDENTITY_PublicKey *key)
428{
429 struct GNUNET_REVOCATION_SignaturePurposePS *spurp;
430 struct GNUNET_IDENTITY_Signature *sig;
431 const struct GNUNET_IDENTITY_PublicKey *pk;
432 size_t ksize;
433
434 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
435 ksize = GNUNET_IDENTITY_key_get_length (pk);
436
437 spurp = GNUNET_malloc (sizeof (*spurp) + ksize);
438 spurp->timestamp = pow->timestamp;
439 spurp->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
440 spurp->purpose.size = htonl (sizeof(*spurp) + ksize);
441 GNUNET_IDENTITY_write_key_to_buffer (pk,
442 (char*) &spurp[1],
443 ksize);
444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
445 "Expected signature payload len: %u\n",
446 ntohl (spurp->purpose.size));
447 sig = (struct GNUNET_IDENTITY_Signature *) ((char*) &pow[1] + ksize);
448 if (GNUNET_OK !=
449 GNUNET_IDENTITY_signature_verify_ (GNUNET_SIGNATURE_PURPOSE_REVOCATION,
450 &spurp->purpose,
451 sig,
452 key))
453 {
454 return GNUNET_SYSERR;
455 }
456 return GNUNET_OK;
457}
458
459
460enum GNUNET_GenericReturnValue
461check_signature (const struct GNUNET_REVOCATION_PowP *pow)
462{
463 const struct GNUNET_IDENTITY_PublicKey *pk;
464
465 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
466 return check_signature_identity (pow, pk);
467}
468
469
470/**
471 * Check if the given proof-of-work is valid.
472 *
473 * @param pow proof of work
474 * @param matching_bits how many bits must match (configuration)
475 * @param epoch_duration length of single epoch in configuration
476 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
477 */
478enum GNUNET_GenericReturnValue
479GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
480 unsigned int difficulty,
481 struct GNUNET_TIME_Relative epoch_duration)
482{
483 char buf[sizeof(struct GNUNET_IDENTITY_PublicKey)
484 + sizeof (struct GNUNET_TIME_AbsoluteNBO)
485 + sizeof (uint64_t)] GNUNET_ALIGN;
486 struct GNUNET_HashCode result;
487 struct GNUNET_TIME_Absolute ts;
488 struct GNUNET_TIME_Absolute exp;
489 struct GNUNET_TIME_Relative ttl;
490 struct GNUNET_TIME_Relative buffer;
491 unsigned int score = 0;
492 unsigned int tmp_score = 0;
493 unsigned int epochs;
494 uint64_t pow_val;
495 ssize_t pklen;
496 const struct GNUNET_IDENTITY_PublicKey *pk;
497
498 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
499
500 /**
501 * Check if signature valid
502 */
503 if (GNUNET_OK != check_signature (pow))
504 {
505 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
506 "Proof of work signature invalid!\n");
507 return GNUNET_SYSERR;
508 }
509
510 /**
511 * First, check if PoW set is strictly monotically increasing
512 */
513 for (unsigned int i = 0; i < POW_COUNT - 1; i++)
514 {
515 if (GNUNET_ntohll (pow->pow[i]) >= GNUNET_ntohll (pow->pow[i + 1]))
516 return GNUNET_NO;
517 }
518 GNUNET_memcpy (&buf[sizeof(uint64_t)],
519 &pow->timestamp,
520 sizeof (uint64_t));
521 pklen = GNUNET_IDENTITY_key_get_length (pk);
522 if (0 > pklen)
523 {
524 GNUNET_break (0);
525 return GNUNET_NO;
526 }
527 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
528 pk,
529 pklen);
530 for (unsigned int i = 0; i < POW_COUNT; i++)
531 {
532 pow_val = GNUNET_ntohll (pow->pow[i]);
533 GNUNET_memcpy (buf, &pow->pow[i], sizeof(uint64_t));
534 GNUNET_CRYPTO_pow_hash (&salt,
535 buf,
536 sizeof(buf),
537 &result);
538 tmp_score = count_leading_zeroes (&result);
539 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540 "Score %u with %" PRIu64 " (#%u)\n",
541 tmp_score, pow_val, i);
542
543 score += tmp_score;
544
545 }
546 score = score / POW_COUNT;
547 if (score < difficulty)
548 return GNUNET_NO;
549 epochs = score - difficulty;
550
551 /**
552 * Check expiration
553 */
554 ts = GNUNET_TIME_absolute_ntoh (pow->timestamp);
555 ttl = GNUNET_TIME_relative_multiply (epoch_duration,
556 epochs);
557 /**
558 * Extend by 10% for unsynchronized clocks
559 */
560 buffer = GNUNET_TIME_relative_divide (epoch_duration,
561 10);
562 exp = GNUNET_TIME_absolute_add (ts, ttl);
563 exp = GNUNET_TIME_absolute_add (exp,
564 buffer);
565
566 if (0 != GNUNET_TIME_absolute_get_remaining (ts).rel_value_us)
567 return GNUNET_NO; /* Not yet valid. */
568 /* Revert to actual start time */
569 ts = GNUNET_TIME_absolute_add (ts,
570 buffer);
571
572 if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
573 return GNUNET_NO; /* expired */
574 return GNUNET_YES;
575}
576
577
578enum GNUNET_GenericReturnValue
579sign_pow_identity (const struct GNUNET_IDENTITY_PrivateKey *key,
580 struct GNUNET_REVOCATION_PowP *pow)
581{
582 struct GNUNET_TIME_Absolute ts = GNUNET_TIME_absolute_get ();
583 struct GNUNET_REVOCATION_SignaturePurposePS *rp;
584 const struct GNUNET_IDENTITY_PublicKey *pk;
585 size_t ksize;
586 char *sig;
587
588 /**
589 * Predate the validity period to prevent rejections due to
590 * unsynchronized clocks
591 */
592 ts = GNUNET_TIME_absolute_subtract (ts,
593 GNUNET_TIME_UNIT_WEEKS);
594 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
595 ksize = GNUNET_IDENTITY_key_get_length (pk);
596 pow->timestamp = GNUNET_TIME_absolute_hton (ts);
597 rp = GNUNET_malloc (sizeof (*rp) + ksize);
598 rp->timestamp = pow->timestamp;
599 rp->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
600 rp->purpose.size = htonl (sizeof(*rp) + ksize);
601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
602 "Signature payload len: %u\n",
603 ntohl (rp->purpose.size));
604 GNUNET_IDENTITY_write_key_to_buffer (pk,
605 ((char*) &rp[1]),
606 ksize);
607 sig = ((char*) &pow[1]) + ksize;
608 int result = GNUNET_IDENTITY_sign_ (key,
609 &rp->purpose,
610 (void*) sig);
611 if (result == GNUNET_SYSERR)
612 return GNUNET_NO;
613 else
614 return result;
615}
616
617
618enum GNUNET_GenericReturnValue
619sign_pow (const struct GNUNET_IDENTITY_PrivateKey *key,
620 struct GNUNET_REVOCATION_PowP *pow)
621{
622 struct GNUNET_IDENTITY_PublicKey *pk;
623
624 pk = (struct GNUNET_IDENTITY_PublicKey *) &pow[1];
625 GNUNET_IDENTITY_key_get_public (key, pk);
626 return sign_pow_identity (key, pow);
627}
628
629
630/**
631 * Initializes a fresh PoW computation.
632 *
633 * @param key the key to calculate the PoW for.
634 * @param[out] pow starting point for PoW calculation (not yet valid)
635 */
636void
637GNUNET_REVOCATION_pow_init (const struct GNUNET_IDENTITY_PrivateKey *key,
638 struct GNUNET_REVOCATION_PowP *pow)
639{
640 GNUNET_assert (GNUNET_OK == sign_pow (key, pow));
641}
642
643
644/**
645 * Starts a proof-of-work calculation given the pow object as well as
646 * target epochs and difficulty.
647 *
648 * @param pow the PoW to based calculations on.
649 * @param epochs the number of epochs for which the PoW must be valid.
650 * @param difficulty the base difficulty of the PoW.
651 * @return a handle for use in PoW rounds
652 */
653struct GNUNET_REVOCATION_PowCalculationHandle*
654GNUNET_REVOCATION_pow_start (struct GNUNET_REVOCATION_PowP *pow,
655 int epochs,
656 unsigned int difficulty)
657{
658 struct GNUNET_REVOCATION_PowCalculationHandle *pc;
659 struct GNUNET_TIME_Relative ttl;
660
661
662 pc = GNUNET_new (struct GNUNET_REVOCATION_PowCalculationHandle);
663 pc->pow = pow;
664 ttl = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
665 epochs);
666 pc->pow->ttl = GNUNET_TIME_relative_hton (ttl);
667 pc->current_pow = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
668 UINT64_MAX);
669 pc->difficulty = difficulty;
670 pc->epochs = epochs;
671 return pc;
672}
673
674
675/**
676 * Comparison function for quicksort
677 *
678 * @param a left element
679 * @param b right element
680 * @return a-b
681 */
682static int
683cmp_pow_value (const void *a, const void *b)
684{
685 return (GNUNET_ntohll (*(uint64_t*) a) - GNUNET_ntohll (*(uint64_t*) b));
686}
687
688
689/**
690 * Calculate a key revocation valid for broadcasting for a number
691 * of epochs.
692 *
693 * @param pc handle to the PoW, initially called with NULL.
694 * @param epochs number of epochs for which the revocation must be valid.
695 * @param pow current pow value to try
696 * @param difficulty current base difficulty to achieve
697 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
698 */
699enum GNUNET_GenericReturnValue
700GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
701{
702 char buf[sizeof(struct GNUNET_IDENTITY_PublicKey)
703 + sizeof (uint64_t)
704 + sizeof (uint64_t)] GNUNET_ALIGN;
705 struct GNUNET_HashCode result;
706 const struct GNUNET_IDENTITY_PublicKey *pk;
707 unsigned int zeros;
708 int ret;
709 uint64_t pow_nbo;
710 ssize_t ksize;
711
712 pc->current_pow++;
713 pk = (const struct GNUNET_IDENTITY_PublicKey *) &(pc->pow[1]);
714
715 /**
716 * Do not try duplicates
717 */
718 for (unsigned int i = 0; i < POW_COUNT; i++)
719 if (pc->current_pow == pc->best[i].pow)
720 return GNUNET_NO;
721 pow_nbo = GNUNET_htonll (pc->current_pow);
722 GNUNET_memcpy (buf, &pow_nbo, sizeof(uint64_t));
723 GNUNET_memcpy (&buf[sizeof(uint64_t)],
724 &pc->pow->timestamp,
725 sizeof (uint64_t));
726 ksize = GNUNET_IDENTITY_key_get_length (pk);
727 GNUNET_assert (0 < ksize);
728 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
729 pk,
730 ksize);
731 GNUNET_CRYPTO_pow_hash (&salt,
732 buf,
733 sizeof(buf),
734 &result);
735 zeros = count_leading_zeroes (&result);
736 for (unsigned int i = 0; i < POW_COUNT; i++)
737 {
738 if (pc->best[i].bits < zeros)
739 {
740 pc->best[i].bits = zeros;
741 pc->best[i].pow = pc->current_pow;
742 pc->pow->pow[i] = pow_nbo;
743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
744 "New best score %u with %" PRIu64 " (#%u)\n",
745 zeros, pc->current_pow, i);
746
747 break;
748 }
749 }
750 ret = calculate_score (pc) >= pc->difficulty + pc->epochs ? GNUNET_YES :
751 GNUNET_NO;
752 if (GNUNET_YES == ret)
753 {
754 /* Sort POWs) */
755 qsort (pc->pow->pow, POW_COUNT, sizeof (uint64_t), &cmp_pow_value);
756 }
757 return ret;
758}
759
760
761/**
762 * Stop a PoW calculation
763 *
764 * @param pc the calculation to clean up
765 * @return #GNUNET_YES if pow valid, #GNUNET_NO if pow was set but is not
766 * valid
767 */
768void
769GNUNET_REVOCATION_pow_stop (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
770{
771 GNUNET_free (pc);
772}
773
774
775size_t
776GNUNET_REVOCATION_proof_get_size (const struct GNUNET_REVOCATION_PowP *pow)
777{
778 size_t size;
779 size_t ksize;
780 const struct GNUNET_IDENTITY_PublicKey *pk;
781 const struct GNUNET_IDENTITY_Signature *sig;
782
783 size = sizeof (struct GNUNET_REVOCATION_PowP);
784 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
785 ksize = GNUNET_IDENTITY_key_get_length (pk);
786 size += ksize;
787 sig = (struct GNUNET_IDENTITY_Signature *) ((char*) &pow[1] + ksize);
788 size += GNUNET_IDENTITY_signature_get_length (sig);
789 return size;
790}
791
792
793/* end of revocation_api.c */