2 This file is part of GNUnet.
3 Copyright (C) 2013 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file revocation/gnunet-revocation.c
23 * @brief tool for revoking public keys
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_revocation_service.h"
29 #include "gnunet_identity_service.h"
34 static unsigned int pow_passes = 1;
49 static char *filename;
54 static char *revoke_ego;
59 static char *test_ego;
64 static unsigned int epochs = 1;
67 * Handle for revocation query.
69 static struct GNUNET_REVOCATION_Query *q;
72 * Handle for revocation.
74 static struct GNUNET_REVOCATION_Handle *h;
77 * Handle for our ego lookup.
79 static struct GNUNET_IDENTITY_EgoLookup *el;
84 static const struct GNUNET_CONFIGURATION_Handle *cfg;
87 * Number of matching bits required for revocation.
89 static unsigned long long matching_bits;
94 static struct GNUNET_TIME_Relative epoch_duration;
97 * Task used for proof-of-work calculation.
99 static struct GNUNET_SCHEDULER_Task *pow_task;
102 * Proof-of-work object
104 static struct GNUNET_REVOCATION_PowP proof_of_work;
107 * Function run if the user aborts with CTRL-C.
112 do_shutdown (void *cls)
114 fprintf (stderr, "%s", _ ("Shutting down...\n"));
117 GNUNET_IDENTITY_ego_lookup_cancel (el);
122 GNUNET_REVOCATION_query_cancel (q);
127 GNUNET_REVOCATION_revoke_cancel (h);
134 * Print the result from a revocation query.
137 * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error
140 print_query_result (void *cls, int is_valid)
146 fprintf (stdout, _ ("Key `%s' is valid\n"), test_ego);
150 fprintf (stdout, _ ("Key `%s' has been revoked\n"), test_ego);
154 fprintf (stdout, "%s", _ ("Internal error\n"));
161 GNUNET_SCHEDULER_shutdown ();
166 * Print the result from a revocation request.
169 * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error
172 print_revocation_result (void *cls, int is_valid)
178 if (NULL != revoke_ego)
180 _ ("Key for ego `%s' is still valid, revocation failed (!)\n"),
183 fprintf (stdout, "%s", _ ("Revocation failed (!)\n"));
187 if (NULL != revoke_ego)
189 _ ("Key for ego `%s' has been successfully revoked\n"),
192 fprintf (stdout, "%s", _ ("Revocation successful.\n"));
198 _ ("Internal error, key revocation might have failed\n"));
205 GNUNET_SCHEDULER_shutdown ();
210 * Perform the revocation.
213 perform_revocation ()
215 h = GNUNET_REVOCATION_revoke (cfg,
217 &print_revocation_result,
223 * Write the current state of the revocation data
226 * @param rd data to sync
231 if ((NULL != filename) &&
232 (sizeof(struct GNUNET_REVOCATION_PowP) !=
233 GNUNET_DISK_fn_write (filename,
235 sizeof(struct GNUNET_REVOCATION_PowP),
236 GNUNET_DISK_PERM_USER_READ
237 | GNUNET_DISK_PERM_USER_WRITE)))
238 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename);
243 * Perform the proof-of-work calculation.
245 * @param cls the `struct RevocationData`
248 calculate_pow_shutdown (void *cls)
250 struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls;
251 fprintf (stderr, "%s", _ ("Cancelling calculation.\n"));
253 if (NULL != pow_task)
255 GNUNET_SCHEDULER_cancel (pow_task);
259 GNUNET_REVOCATION_pow_stop (ph);
264 * Perform the proof-of-work calculation.
266 * @param cls the `struct RevocationData`
269 calculate_pow (void *cls)
271 struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls;
273 /* store temporary results */
275 if (0 == (pow_passes % 128))
277 /* actually do POW calculation */
278 if (GNUNET_OK == GNUNET_REVOCATION_pow_round (ph))
280 if ((NULL != filename) &&
281 (sizeof(struct GNUNET_REVOCATION_PowP) !=
282 GNUNET_DISK_fn_write (filename,
284 sizeof(struct GNUNET_REVOCATION_PowP),
285 GNUNET_DISK_PERM_USER_READ
286 | GNUNET_DISK_PERM_USER_WRITE)))
287 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename);
290 perform_revocation ();
294 fprintf (stderr, "%s", "\n");
296 _ ("Revocation certificate for `%s' stored in `%s'\n"),
299 GNUNET_SCHEDULER_shutdown ();
305 * Otherwise CTRL-C does not work
307 if (0 == pow_passes % 128)
308 pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
312 pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
320 * Function called with the result from the ego lookup.
323 * @param ego the ego, NULL if not found
326 ego_callback (void *cls, struct GNUNET_IDENTITY_Ego *ego)
328 struct GNUNET_CRYPTO_EcdsaPublicKey key;
329 const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
330 struct GNUNET_REVOCATION_PowCalculationHandle *ph = NULL;
335 fprintf (stdout, _ ("Ego `%s' not found.\n"), revoke_ego);
336 GNUNET_SCHEDULER_shutdown ();
339 GNUNET_IDENTITY_ego_get_public_key (ego, &key);
340 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
341 memset (&proof_of_work, 0, sizeof (proof_of_work));
342 if ((NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test (filename)) &&
343 (sizeof(proof_of_work) ==
344 GNUNET_DISK_fn_read (filename, &proof_of_work, sizeof(proof_of_work))))
346 if (0 != GNUNET_memcmp (&proof_of_work.key, &key))
349 _ ("Error: revocation certificate in `%s' is not for `%s'\n"),
355 GNUNET_REVOCATION_check_pow (&proof_of_work,
356 (unsigned int) matching_bits,
359 fprintf (stderr, "%s", _ ("Revocation certificate ready\n"));
361 perform_revocation ();
363 GNUNET_SCHEDULER_shutdown ();
367 * Certificate not yet ready
371 _ ("Continuing calculation where left off...\n"));
372 ph = GNUNET_REVOCATION_pow_start (&proof_of_work,
378 _ ("Revocation certificate not ready, calculating proof of work\n"));
381 GNUNET_REVOCATION_pow_init (privkey,
383 ph = GNUNET_REVOCATION_pow_start (&proof_of_work,
387 pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph);
388 GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph);
393 * Main function that will be run by the scheduler.
396 * @param args remaining command-line arguments
397 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
398 * @param c configuration
404 const struct GNUNET_CONFIGURATION_Handle *c)
406 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
409 if (NULL != test_ego)
412 GNUNET_CRYPTO_ecdsa_public_key_from_string (test_ego,
416 fprintf (stderr, _ ("Public key `%s' malformed\n"), test_ego);
419 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
420 q = GNUNET_REVOCATION_query (cfg, &pk, &print_query_result, NULL);
421 if (NULL != revoke_ego)
426 "Testing and revoking at the same time is not allowed, only executing test.\n"));
429 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
434 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
439 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
444 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
450 if (NULL != revoke_ego)
452 if (! perform && (NULL == filename))
456 _ ("No filename to store revocation certificate given.\n"));
460 el = GNUNET_IDENTITY_ego_lookup (cfg, revoke_ego, &ego_callback, NULL);
461 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
464 if ((NULL != filename) && (perform))
466 if (sizeof(proof_of_work) != GNUNET_DISK_fn_read (filename,
468 sizeof(proof_of_work)))
471 _ ("Failed to read revocation certificate from `%s'\n"),
475 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
477 GNUNET_REVOCATION_check_pow (&proof_of_work,
478 (unsigned int) matching_bits,
481 struct GNUNET_REVOCATION_PowCalculationHandle *ph;
482 ph = GNUNET_REVOCATION_pow_start (&proof_of_work,
486 pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph);
487 GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph);
490 perform_revocation ();
493 fprintf (stderr, "%s", _ ("No action specified. Nothing to do.\n"));
498 * The main function of gnunet-revocation.
500 * @param argc number of arguments from the command line
501 * @param argv command line arguments
502 * @return 0 ok, 1 on error
505 main (int argc, char *const *argv)
507 struct GNUNET_GETOPT_CommandLineOption options[] = {
508 GNUNET_GETOPT_option_string ('f',
512 "use NAME for the name of the revocation file"),
515 GNUNET_GETOPT_option_string (
520 "revoke the private key associated for the the private key associated with the ego NAME "),
523 GNUNET_GETOPT_option_flag (
527 "actually perform revocation, otherwise we just do the precomputation"),
530 GNUNET_GETOPT_option_string ('t',
534 "test if the public key KEY has been revoked"),
536 GNUNET_GETOPT_option_uint ('e',
540 "number of epochs to calculate for"),
543 GNUNET_GETOPT_OPTION_END
546 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
549 ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
552 gettext_noop ("help text"),
558 GNUNET_free_nz ((void *) argv);
563 /* end of gnunet-revocation.c */