aboutsummaryrefslogtreecommitdiff
path: root/src/revocation
diff options
context:
space:
mode:
Diffstat (limited to 'src/revocation')
-rw-r--r--src/revocation/.gitignore5
-rw-r--r--src/revocation/Makefile.am112
-rw-r--r--src/revocation/gnunet-revocation-tvg.c149
-rw-r--r--src/revocation/gnunet-revocation.c581
-rw-r--r--src/revocation/gnunet-service-revocation.c1027
-rw-r--r--src/revocation/plugin_block_revocation.c275
-rw-r--r--src/revocation/revocation.conf.in19
-rw-r--r--src/revocation/revocation.h117
-rw-r--r--src/revocation/revocation_api.c793
-rw-r--r--src/revocation/test_local_revocation.py.in129
-rw-r--r--src/revocation/test_revocation.c419
-rw-r--r--src/revocation/test_revocation.conf31
12 files changed, 0 insertions, 3657 deletions
diff --git a/src/revocation/.gitignore b/src/revocation/.gitignore
deleted file mode 100644
index 1432f7922..000000000
--- a/src/revocation/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
1gnunet-service-revocation
2gnunet-revocation
3test_revocation
4test_local_revocation.py
5gnunet-revocation-tvg
diff --git a/src/revocation/Makefile.am b/src/revocation/Makefile.am
deleted file mode 100644
index d0c58584e..000000000
--- a/src/revocation/Makefile.am
+++ /dev/null
@@ -1,112 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4plugindir = $(libdir)/gnunet
5
6if USE_COVERAGE
7 AM_CFLAGS = --coverage -O0
8 XLIB = -lgcov
9endif
10
11pkgcfgdir= $(pkgdatadir)/config.d/
12
13libexecdir= $(pkglibdir)/libexec/
14
15pkgcfg_DATA = \
16 revocation.conf
17
18bin_PROGRAMS = \
19 gnunet-revocation \
20 gnunet-revocation-tvg
21
22
23plugin_LTLIBRARIES = \
24 libgnunet_plugin_block_revocation.la
25
26libgnunet_plugin_block_revocation_la_SOURCES = \
27 plugin_block_revocation.c
28libgnunet_plugin_block_revocation_la_LIBADD = \
29 libgnunetrevocation.la \
30 $(top_builddir)/src/block/libgnunetblockgroup.la \
31 $(top_builddir)/src/block/libgnunetblock.la \
32 $(top_builddir)/src/util/libgnunetutil.la \
33 $(top_builddir)/src/identity/libgnunetidentity.la \
34 $(LTLIBINTL)
35libgnunet_plugin_block_revocation_la_LDFLAGS = \
36 $(GN_PLUGIN_LDFLAGS)
37
38
39gnunet_revocation_SOURCES = \
40 gnunet-revocation.c
41gnunet_revocation_LDADD = \
42 libgnunetrevocation.la \
43 $(top_builddir)/src/identity/libgnunetidentity.la \
44 $(top_builddir)/src/util/libgnunetutil.la \
45 $(GN_LIBINTL)
46
47gnunet_revocation_tvg_SOURCES = \
48 gnunet-revocation-tvg.c
49gnunet_revocation_tvg_LDADD = \
50 libgnunetrevocation.la \
51 $(top_builddir)/src/identity/libgnunetidentity.la \
52 $(top_builddir)/src/util/libgnunetutil.la \
53 $(GN_LIBINTL)
54
55
56lib_LTLIBRARIES = libgnunetrevocation.la
57
58libgnunetrevocation_la_SOURCES = \
59 revocation_api.c revocation.h
60libgnunetrevocation_la_LIBADD = \
61 $(top_builddir)/src/util/libgnunetutil.la \
62 $(top_builddir)/src/identity/libgnunetidentity.la \
63 $(LIBGCRYPT_LIBS) \
64 $(GN_LIBINTL) $(XLIB) -lgcrypt
65libgnunetrevocation_la_LDFLAGS = \
66 $(GN_LIB_LDFLAGS) \
67 -version-info 0:0:0
68
69libexec_PROGRAMS = \
70 gnunet-service-revocation
71
72
73gnunet_service_revocation_SOURCES = \
74 gnunet-service-revocation.c
75gnunet_service_revocation_LDADD = \
76 libgnunetrevocation.la \
77 $(top_builddir)/src/core/libgnunetcore.la \
78 $(top_builddir)/src/setu/libgnunetsetu.la \
79 $(top_builddir)/src/statistics/libgnunetstatistics.la \
80 $(top_builddir)/src/identity/libgnunetidentity.la \
81 $(top_builddir)/src/util/libgnunetutil.la \
82 -lm \
83 $(GN_LIBINTL)
84
85test_revocation_SOURCES = \
86 test_revocation.c
87test_revocation_LDADD = \
88 $(top_builddir)/src/identity/libgnunetidentity.la \
89 libgnunetrevocation.la \
90 $(top_builddir)/src//core/libgnunetcore.la \
91 $(top_builddir)/src/util/libgnunetutil.la \
92 $(top_builddir)/src/testbed/libgnunettestbed.la
93
94check_PROGRAMS = \
95 test_revocation
96
97check_SCRIPTS = \
98 test_local_revocation.py
99
100if ENABLE_TEST_RUN
101 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
102 TESTS = \
103 $(check_SCRIPTS) \
104 $(check_PROGRAMS)
105endif
106
107test_local_revocation.py: test_local_revocation.py.in Makefile
108 $(AWK) -v bdir="$(bindir)" -v py="$(PYTHON)" -v awkay="$(AWK_BINARY)" -v pfx="$(prefix)" -v prl="$(PERL)" -v sysconfdirectory="$(sysconfdir)" -v pkgdatadirectory="$(pkgdatadir)" -f $(top_srcdir)/bin/dosubst.awk < $(srcdir)/test_local_revocation.py.in > test_local_revocation.py
109 chmod +x test_local_revocation.py
110
111EXTRA_DIST = test_revocation.conf \
112 test_local_revocation.py.in
diff --git a/src/revocation/gnunet-revocation-tvg.c b/src/revocation/gnunet-revocation-tvg.c
deleted file mode 100644
index cb5e31fcd..000000000
--- a/src/revocation/gnunet-revocation-tvg.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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/**
22 * @file util/gnunet-revocation-tvg.c
23 * @brief Generate test vectors for revocation.
24 * @author Martin Schanzenbach
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_signatures.h"
29#include "gnunet_revocation_service.h"
30#include "gnunet_dnsparser_lib.h"
31#include "gnunet_testing_lib.h"
32#include <inttypes.h>
33
34#define TEST_EPOCHS 2
35#define TEST_DIFFICULTY 5
36
37static void
38print_bytes (void *buf,
39 size_t buf_len,
40 int fold)
41{
42 int i;
43
44 for (i = 0; i < buf_len; i++)
45 {
46 if ((0 != i) && (0 != fold) && (i % fold == 0))
47 printf ("\n");
48 printf ("%02x", ((unsigned char*) buf)[i]);
49 }
50 printf ("\n");
51}
52
53
54/**
55 * Main function that will be run.
56 *
57 * @param cls closure
58 * @param args remaining command-line arguments
59 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
60 * @param cfg configuration
61 */
62static void
63run (void *cls,
64 char *const *args,
65 const char *cfgfile,
66 const struct GNUNET_CONFIGURATION_Handle *cfg)
67{
68 struct GNUNET_IDENTITY_PrivateKey id_priv;
69 struct GNUNET_IDENTITY_PublicKey id_pub;
70 struct GNUNET_REVOCATION_PowP *pow;
71 struct GNUNET_REVOCATION_PowCalculationHandle *ph;
72 struct GNUNET_TIME_Relative exp;
73 char ztld[128];
74
75 id_priv.type = htonl (GNUNET_IDENTITY_TYPE_ECDSA);
76 GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key);
77 GNUNET_IDENTITY_key_get_public (&id_priv,
78 &id_pub);
79 GNUNET_STRINGS_data_to_string (&id_pub,
80 GNUNET_IDENTITY_key_get_length (&id_pub),
81 ztld,
82 sizeof (ztld));
83 fprintf (stdout, "Zone private key (d, little-endian scalar, with ztype prepended):\n");
84 print_bytes (&id_priv, sizeof(id_priv), 8);
85 fprintf (stdout, "\n");
86 fprintf (stdout, "Zone identifier (zid):\n");
87 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8);
88 fprintf (stdout, "\n");
89 fprintf (stdout, "Encoded zone identifier (zkl = zTLD):\n");
90 fprintf (stdout, "%s\n", ztld);
91 fprintf (stdout, "\n");
92 pow = GNUNET_malloc (GNUNET_REVOCATION_MAX_PROOF_SIZE);
93 GNUNET_REVOCATION_pow_init (&id_priv,
94 pow);
95 ph = GNUNET_REVOCATION_pow_start (pow,
96 TEST_EPOCHS,
97 TEST_DIFFICULTY);
98 fprintf (stdout, "Difficulty (%d base difficulty + %d epochs): %d\n\n",
99 TEST_DIFFICULTY,
100 TEST_EPOCHS,
101 TEST_DIFFICULTY + TEST_EPOCHS);
102 uint64_t pow_passes = 0;
103 while (GNUNET_YES != GNUNET_REVOCATION_pow_round (ph))
104 {
105 pow_passes++;
106 }
107 exp = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
108 TEST_EPOCHS);
109 GNUNET_assert (GNUNET_OK == GNUNET_REVOCATION_check_pow (pow,
110 TEST_DIFFICULTY,
111 exp));
112 fprintf (stdout, "Proof:\n");
113 print_bytes (pow,
114 GNUNET_REVOCATION_proof_get_size (pow),
115 8);
116}
117
118
119/**
120 * The main function of the test vector generation tool.
121 *
122 * @param argc number of arguments from the command line
123 * @param argv command line arguments
124 * @return 0 ok, 1 on error
125 */
126int
127main (int argc,
128 char *const *argv)
129{
130 const struct GNUNET_GETOPT_CommandLineOption options[] = {
131 GNUNET_GETOPT_OPTION_END
132 };
133
134 GNUNET_assert (GNUNET_OK ==
135 GNUNET_log_setup ("gnunet-revocation-tvg",
136 "INFO",
137 NULL));
138 if (GNUNET_OK !=
139 GNUNET_PROGRAM_run (argc, argv,
140 "gnunet-revocation-tvg",
141 "Generate test vectors for revocation",
142 options,
143 &run, NULL))
144 return 1;
145 return 0;
146}
147
148
149/* end of gnunet-revocation-tvg.c */
diff --git a/src/revocation/gnunet-revocation.c b/src/revocation/gnunet-revocation.c
deleted file mode 100644
index a7f96385c..000000000
--- a/src/revocation/gnunet-revocation.c
+++ /dev/null
@@ -1,581 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 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/**
22 * @file revocation/gnunet-revocation.c
23 * @brief tool for revoking public keys
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_revocation_service.h"
29#include "gnunet_identity_service.h"
30
31/**
32 * Pow passes
33 */
34static unsigned int pow_passes = 1;
35
36/**
37 * Final status code.
38 */
39static int ret;
40
41/**
42 * Was "-p" specified?
43 */
44static int perform;
45
46/**
47 * -f option.
48 */
49static char *filename;
50
51/**
52 * -R option
53 */
54static char *revoke_ego;
55
56/**
57 * -t option.
58 */
59static char *test_ego;
60
61/**
62 * -e option.
63 */
64static unsigned int epochs = 1;
65
66/**
67 * Handle for revocation query.
68 */
69static struct GNUNET_REVOCATION_Query *q;
70
71/**
72 * Handle for revocation.
73 */
74static struct GNUNET_REVOCATION_Handle *h;
75
76/**
77 * Handle for our ego lookup.
78 */
79static struct GNUNET_IDENTITY_EgoLookup *el;
80
81/**
82 * Our configuration.
83 */
84static const struct GNUNET_CONFIGURATION_Handle *cfg;
85
86/**
87 * Number of matching bits required for revocation.
88 */
89static unsigned long long matching_bits;
90
91/**
92 * Epoch length
93 */
94static struct GNUNET_TIME_Relative epoch_duration;
95
96/**
97 * Task used for proof-of-work calculation.
98 */
99static struct GNUNET_SCHEDULER_Task *pow_task;
100
101/**
102 * Proof-of-work object
103 */
104static struct GNUNET_REVOCATION_PowP *proof_of_work;
105
106/**
107 * Function run if the user aborts with CTRL-C.
108 *
109 * @param cls closure
110 */
111static void
112do_shutdown (void *cls)
113{
114 fprintf (stderr, "%s", _ ("Shutting down...\n"));
115 if (NULL != el)
116 {
117 GNUNET_IDENTITY_ego_lookup_cancel (el);
118 el = NULL;
119 }
120 if (NULL != q)
121 {
122 GNUNET_REVOCATION_query_cancel (q);
123 q = NULL;
124 }
125 if (NULL != h)
126 {
127 GNUNET_REVOCATION_revoke_cancel (h);
128 h = NULL;
129 }
130}
131
132
133/**
134 * Print the result from a revocation query.
135 *
136 * @param cls NULL
137 * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error
138 */
139static void
140print_query_result (void *cls, int is_valid)
141{
142 q = NULL;
143 switch (is_valid)
144 {
145 case GNUNET_YES:
146 fprintf (stdout, _ ("Key `%s' is valid\n"), test_ego);
147 break;
148
149 case GNUNET_NO:
150 fprintf (stdout, _ ("Key `%s' has been revoked\n"), test_ego);
151 break;
152
153 case GNUNET_SYSERR:
154 fprintf (stdout, "%s", _ ("Internal error\n"));
155 break;
156
157 default:
158 GNUNET_break (0);
159 break;
160 }
161 GNUNET_SCHEDULER_shutdown ();
162}
163
164
165/**
166 * Print the result from a revocation request.
167 *
168 * @param cls NULL
169 * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error
170 */
171static void
172print_revocation_result (void *cls, int is_valid)
173{
174 h = NULL;
175 switch (is_valid)
176 {
177 case GNUNET_YES:
178 if (NULL != revoke_ego)
179 fprintf (stdout,
180 _ ("Key for ego `%s' is still valid, revocation failed (!)\n"),
181 revoke_ego);
182 else
183 fprintf (stdout, "%s", _ ("Revocation failed (!)\n"));
184 break;
185
186 case GNUNET_NO:
187 if (NULL != revoke_ego)
188 fprintf (stdout,
189 _ ("Key for ego `%s' has been successfully revoked\n"),
190 revoke_ego);
191 else
192 fprintf (stdout, "%s", _ ("Revocation successful.\n"));
193 break;
194
195 case GNUNET_SYSERR:
196 fprintf (stdout,
197 "%s",
198 _ ("Internal error, key revocation might have failed\n"));
199 break;
200
201 default:
202 GNUNET_break (0);
203 break;
204 }
205 GNUNET_SCHEDULER_shutdown ();
206}
207
208
209/**
210 * Perform the revocation.
211 */
212static void
213perform_revocation ()
214{
215 h = GNUNET_REVOCATION_revoke (cfg,
216 proof_of_work,
217 &print_revocation_result,
218 NULL);
219}
220
221
222/**
223 * Write the current state of the revocation data
224 * to disk.
225 *
226 * @param rd data to sync
227 */
228static void
229sync_pow ()
230{
231 size_t psize = GNUNET_REVOCATION_proof_get_size (proof_of_work);
232 if ((NULL != filename) &&
233 (GNUNET_OK !=
234 GNUNET_DISK_fn_write (filename,
235 proof_of_work,
236 psize,
237 GNUNET_DISK_PERM_USER_READ
238 | GNUNET_DISK_PERM_USER_WRITE)))
239 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename);
240}
241
242
243/**
244 * Perform the proof-of-work calculation.
245 *
246 * @param cls the `struct RevocationData`
247 */
248static void
249calculate_pow_shutdown (void *cls)
250{
251 struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls;
252 fprintf (stderr, "%s", _ ("Cancelling calculation.\n"));
253 sync_pow ();
254 if (NULL != pow_task)
255 {
256 GNUNET_SCHEDULER_cancel (pow_task);
257 pow_task = NULL;
258 }
259 if (NULL != ph)
260 GNUNET_REVOCATION_pow_stop (ph);
261}
262
263
264/**
265 * Perform the proof-of-work calculation.
266 *
267 * @param cls the `struct RevocationData`
268 */
269static void
270calculate_pow (void *cls)
271{
272 struct GNUNET_REVOCATION_PowCalculationHandle *ph = cls;
273 size_t psize;
274
275 /* store temporary results */
276 pow_task = NULL;
277 if (0 == (pow_passes % 128))
278 sync_pow ();
279 /* actually do POW calculation */
280 if (GNUNET_OK == GNUNET_REVOCATION_pow_round (ph))
281 {
282 psize = GNUNET_REVOCATION_proof_get_size (proof_of_work);
283 if (NULL != filename)
284 {
285 (void) GNUNET_DISK_directory_remove (filename);
286 if (GNUNET_OK !=
287 GNUNET_DISK_fn_write (filename,
288 proof_of_work,
289 psize,
290 GNUNET_DISK_PERM_USER_READ
291 | GNUNET_DISK_PERM_USER_WRITE))
292 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename);
293 }
294 if (perform)
295 {
296 perform_revocation ();
297 }
298 else
299 {
300 fprintf (stderr, "%s", "\n");
301 fprintf (stderr,
302 _ ("Revocation certificate for `%s' stored in `%s'\n"),
303 revoke_ego,
304 filename);
305 GNUNET_SCHEDULER_shutdown ();
306 }
307 return;
308 }
309 pow_passes++;
310 pow_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
311 &calculate_pow,
312 ph);
313
314}
315
316
317/**
318 * Function called with the result from the ego lookup.
319 *
320 * @param cls closure
321 * @param ego the ego, NULL if not found
322 */
323static void
324ego_callback (void *cls, struct GNUNET_IDENTITY_Ego *ego)
325{
326 struct GNUNET_IDENTITY_PublicKey key;
327 const struct GNUNET_IDENTITY_PrivateKey *privkey;
328 struct GNUNET_REVOCATION_PowCalculationHandle *ph = NULL;
329 size_t psize;
330
331 el = NULL;
332 if (NULL == ego)
333 {
334 fprintf (stdout, _ ("Ego `%s' not found.\n"), revoke_ego);
335 GNUNET_SCHEDULER_shutdown ();
336 return;
337 }
338 GNUNET_IDENTITY_ego_get_public_key (ego, &key);
339 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
340 proof_of_work = GNUNET_malloc (GNUNET_REVOCATION_MAX_PROOF_SIZE);
341 if ((NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test (filename)) &&
342 (0 < (psize =
343 GNUNET_DISK_fn_read (filename, proof_of_work,
344 GNUNET_REVOCATION_MAX_PROOF_SIZE))))
345 {
346 ssize_t ksize = GNUNET_IDENTITY_key_get_length (&key);
347 if (0 > ksize)
348 {
349 fprintf (stderr,
350 _ ("Error: Key is invalid\n"));
351 return;
352 }
353 if (((psize - sizeof (*proof_of_work)) < ksize) || // Key too small
354 (0 != memcmp (&proof_of_work[1], &key, ksize))) // Keys do not match
355 {
356 fprintf (stderr,
357 _ ("Error: revocation certificate in `%s' is not for `%s'\n"),
358 filename,
359 revoke_ego);
360 return;
361 }
362 if (GNUNET_YES ==
363 GNUNET_REVOCATION_check_pow (proof_of_work,
364 (unsigned int) matching_bits,
365 epoch_duration))
366 {
367 fprintf (stderr, "%s", _ ("Revocation certificate ready\n"));
368 if (perform)
369 perform_revocation ();
370 else
371 GNUNET_SCHEDULER_shutdown ();
372 return;
373 }
374 /**
375 * Certificate not yet ready
376 */
377 fprintf (stderr,
378 "%s",
379 _ ("Continuing calculation where left off...\n"));
380 ph = GNUNET_REVOCATION_pow_start (proof_of_work,
381 epochs,
382 matching_bits);
383 }
384 fprintf (stderr,
385 "%s",
386 _ ("Revocation certificate not ready, calculating proof of work\n"));
387 if (NULL == ph)
388 {
389 GNUNET_REVOCATION_pow_init (privkey,
390 proof_of_work);
391 ph = GNUNET_REVOCATION_pow_start (proof_of_work,
392 epochs, /* Epochs */
393 matching_bits);
394 }
395 pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph);
396 GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph);
397}
398
399
400/**
401 * Main function that will be run by the scheduler.
402 *
403 * @param cls closure
404 * @param args remaining command-line arguments
405 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
406 * @param c configuration
407 */
408static void
409run (void *cls,
410 char *const *args,
411 const char *cfgfile,
412 const struct GNUNET_CONFIGURATION_Handle *c)
413{
414 struct GNUNET_IDENTITY_PublicKey pk;
415 size_t psize;
416
417 cfg = c;
418 if (NULL != test_ego)
419 {
420 if (GNUNET_OK !=
421 GNUNET_IDENTITY_public_key_from_string (test_ego,
422 &pk))
423 {
424 fprintf (stderr, _ ("Public key `%s' malformed\n"), test_ego);
425 return;
426 }
427 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
428 q = GNUNET_REVOCATION_query (cfg, &pk, &print_query_result, NULL);
429 if (NULL != revoke_ego)
430 fprintf (
431 stderr,
432 "%s",
433 _ (
434 "Testing and revoking at the same time is not allowed, only executing test.\n"));
435 return;
436 }
437 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
438 "REVOCATION",
439 "WORKBITS",
440 &matching_bits))
441 {
442 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
443 "REVOCATION",
444 "WORKBITS");
445 return;
446 }
447 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
448 "REVOCATION",
449 "EPOCH_DURATION",
450 &epoch_duration))
451 {
452 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
453 "REVOCATION",
454 "EPOCH_DURATION");
455 return;
456 }
457
458 if (NULL != revoke_ego)
459 {
460 if (! perform && (NULL == filename))
461 {
462 fprintf (stderr,
463 "%s",
464 _ ("No filename to store revocation certificate given.\n"));
465 return;
466 }
467 /* main code here */
468 el = GNUNET_IDENTITY_ego_lookup (cfg, revoke_ego, &ego_callback, NULL);
469 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
470 return;
471 }
472 if ((NULL != filename) && (perform))
473 {
474 size_t bread;
475 proof_of_work = GNUNET_malloc (GNUNET_REVOCATION_MAX_PROOF_SIZE);
476 if (0 < (bread = GNUNET_DISK_fn_read (filename,
477 proof_of_work,
478 GNUNET_REVOCATION_MAX_PROOF_SIZE)))
479 {
480 fprintf (stderr,
481 _ ("Failed to read revocation certificate from `%s'\n"),
482 filename);
483 return;
484 }
485 psize = GNUNET_REVOCATION_proof_get_size (proof_of_work);
486 if (bread != psize)
487 {
488 fprintf (stderr,
489 _ ("Revocation certificate corrupted in `%s'\n"),
490 filename);
491 return;
492 }
493 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
494 if (GNUNET_YES !=
495 GNUNET_REVOCATION_check_pow (proof_of_work,
496 (unsigned int) matching_bits,
497 epoch_duration))
498 {
499 struct GNUNET_REVOCATION_PowCalculationHandle *ph;
500 ph = GNUNET_REVOCATION_pow_start (proof_of_work,
501 epochs, /* Epochs */
502 matching_bits);
503
504 pow_task = GNUNET_SCHEDULER_add_now (&calculate_pow, ph);
505 GNUNET_SCHEDULER_add_shutdown (&calculate_pow_shutdown, ph);
506 return;
507 }
508 perform_revocation ();
509 return;
510 }
511 fprintf (stderr, "%s", _ ("No action specified. Nothing to do.\n"));
512}
513
514
515/**
516 * The main function of gnunet-revocation.
517 *
518 * @param argc number of arguments from the command line
519 * @param argv command line arguments
520 * @return 0 ok, 1 on error
521 */
522int
523main (int argc, char *const *argv)
524{
525 struct GNUNET_GETOPT_CommandLineOption options[] = {
526 GNUNET_GETOPT_option_string ('f',
527 "filename",
528 "NAME",
529 gettext_noop (
530 "use NAME for the name of the revocation file"),
531 &filename),
532
533 GNUNET_GETOPT_option_string (
534 'R',
535 "revoke",
536 "NAME",
537 gettext_noop (
538 "revoke the private key associated for the the private key associated with the ego NAME "),
539 &revoke_ego),
540
541 GNUNET_GETOPT_option_flag (
542 'p',
543 "perform",
544 gettext_noop (
545 "actually perform revocation, otherwise we just do the precomputation"),
546 &perform),
547
548 GNUNET_GETOPT_option_string ('t',
549 "test",
550 "KEY",
551 gettext_noop (
552 "test if the public key KEY has been revoked"),
553 &test_ego),
554 GNUNET_GETOPT_option_uint ('e',
555 "epochs",
556 "EPOCHS",
557 gettext_noop (
558 "number of epochs to calculate for"),
559 &epochs),
560
561 GNUNET_GETOPT_OPTION_END
562 };
563
564 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
565 return 2;
566
567 ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
568 argv,
569 "gnunet-revocation",
570 gettext_noop ("help text"),
571 options,
572 &run,
573 NULL))
574 ? ret
575 : 1;
576 GNUNET_free_nz ((void *) argv);
577 return ret;
578}
579
580
581/* end of gnunet-revocation.c */
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c
deleted file mode 100644
index 5fe0ade98..000000000
--- a/src/revocation/gnunet-service-revocation.c
+++ /dev/null
@@ -1,1027 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2014, 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/**
22 * @file revocation/gnunet-service-revocation.c
23 * @brief key revocation service
24 * @author Christian Grothoff
25 *
26 * The purpose of this service is to allow users to permanently revoke
27 * (compromised) keys. This is done by flooding the network with the
28 * revocation requests. To reduce the attack potential offered by such
29 * flooding, revocations must include a proof of work. We use the
30 * set service for efficiently computing the union of revocations of
31 * peers that connect.
32 *
33 * TODO:
34 * - optimization: avoid sending revocation back to peer that we got it from;
35 * - optimization: have randomized delay in sending revocations to other peers
36 * to make it rare to traverse each link twice (NSE-style)
37 */
38#include "platform.h"
39#include <math.h>
40#include "gnunet_util_lib.h"
41#include "gnunet_block_lib.h"
42#include "gnunet_constants.h"
43#include "gnunet_protocols.h"
44#include "gnunet_signatures.h"
45#include "gnunet_statistics_service.h"
46#include "gnunet_core_service.h"
47#include "gnunet_revocation_service.h"
48#include "gnunet_setu_service.h"
49#include "revocation.h"
50#include <gcrypt.h>
51
52
53/**
54 * Per-peer information.
55 */
56struct PeerEntry
57{
58 /**
59 * Queue for sending messages to this peer.
60 */
61 struct GNUNET_MQ_Handle *mq;
62
63 /**
64 * What is the identity of the peer?
65 */
66 struct GNUNET_PeerIdentity id;
67
68 /**
69 * Tasked used to trigger the set union operation.
70 */
71 struct GNUNET_SCHEDULER_Task *transmit_task;
72
73 /**
74 * Handle to active set union operation (over revocation sets).
75 */
76 struct GNUNET_SETU_OperationHandle *so;
77};
78
79
80/**
81 * Set from all revocations known to us.
82 */
83static struct GNUNET_SETU_Handle *revocation_set;
84
85/**
86 * Hash map with all revoked keys, maps the hash of the public key
87 * to the respective `struct RevokeMessage`.
88 */
89static struct GNUNET_CONTAINER_MultiHashMap *revocation_map;
90
91/**
92 * Handle to our current configuration.
93 */
94static const struct GNUNET_CONFIGURATION_Handle *cfg;
95
96/**
97 * Handle to the statistics service.
98 */
99static struct GNUNET_STATISTICS_Handle *stats;
100
101/**
102 * Handle to the core service (for flooding)
103 */
104static struct GNUNET_CORE_Handle *core_api;
105
106/**
107 * Map of all connected peers.
108 */
109static struct GNUNET_CONTAINER_MultiPeerMap *peers;
110
111/**
112 * The peer identity of this peer.
113 */
114static struct GNUNET_PeerIdentity my_identity;
115
116/**
117 * File handle for the revocation database.
118 */
119static struct GNUNET_DISK_FileHandle *revocation_db;
120
121/**
122 * Handle for us listening to incoming revocation set union requests.
123 */
124static struct GNUNET_SETU_ListenHandle *revocation_union_listen_handle;
125
126/**
127 * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits.
128 */
129static unsigned long long revocation_work_required;
130
131/**
132 * Length of an expiration expoch
133 */
134static struct GNUNET_TIME_Relative epoch_duration;
135
136/**
137 * Our application ID for set union operations. Must be the
138 * same for all (compatible) peers.
139 */
140static struct GNUNET_HashCode revocation_set_union_app_id;
141
142
143/**
144 * Create a new PeerEntry and add it to the peers multipeermap.
145 *
146 * @param peer the peer identity
147 * @return a pointer to the new PeerEntry
148 */
149static struct PeerEntry *
150new_peer_entry (const struct GNUNET_PeerIdentity *peer)
151{
152 struct PeerEntry *peer_entry;
153
154 peer_entry = GNUNET_new (struct PeerEntry);
155 peer_entry->id = *peer;
156 GNUNET_assert (GNUNET_OK ==
157 GNUNET_CONTAINER_multipeermap_put (peers,
158 &peer_entry->id,
159 peer_entry,
160 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
161 return peer_entry;
162}
163
164
165/**
166 * An revoke message has been received, check that it is well-formed.
167 *
168 * @param rm the message to verify
169 * @return #GNUNET_YES if the message is verified
170 * #GNUNET_NO if the key/signature don't verify
171 */
172static int
173verify_revoke_message (const struct RevokeMessage *rm)
174{
175 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1];
176 if (GNUNET_YES != GNUNET_REVOCATION_check_pow (pow,
177 (unsigned
178 int) revocation_work_required,
179 epoch_duration))
180 {
181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
182 "Proof of work invalid!\n");
183 GNUNET_break_op (0);
184 return GNUNET_NO;
185 }
186 return GNUNET_YES;
187}
188
189
190/**
191 * Handle client connecting to the service.
192 *
193 * @param cls NULL
194 * @param client the new client
195 * @param mq the message queue of @a client
196 * @return @a client
197 */
198static void *
199client_connect_cb (void *cls,
200 struct GNUNET_SERVICE_Client *client,
201 struct GNUNET_MQ_Handle *mq)
202{
203 return client;
204}
205
206
207/**
208 * Handle client connecting to the service.
209 *
210 * @param cls NULL
211 * @param client the new client
212 * @param app_cls must alias @a client
213 */
214static void
215client_disconnect_cb (void *cls,
216 struct GNUNET_SERVICE_Client *client,
217 void *app_cls)
218{
219 GNUNET_assert (client == app_cls);
220}
221
222
223/**
224 * Handle QUERY message from client.
225 *
226 * @param cls client who sent the message
227 * @param qm the message received
228 */
229static void
230handle_query_message (void *cls,
231 const struct QueryMessage *qm)
232{
233 struct GNUNET_SERVICE_Client *client = cls;
234 struct GNUNET_MQ_Envelope *env;
235 struct QueryResponseMessage *qrm;
236 struct GNUNET_HashCode hc;
237 int res;
238
239 GNUNET_CRYPTO_hash (&qm->key,
240 sizeof(struct GNUNET_IDENTITY_PublicKey),
241 &hc);
242 res = GNUNET_CONTAINER_multihashmap_contains (revocation_map,
243 &hc);
244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
245 (GNUNET_NO == res)
246 ? "Received revocation check for valid key `%s' from client\n"
247 : "Received revocation check for revoked key `%s' from client\n",
248 GNUNET_h2s (&hc));
249 env = GNUNET_MQ_msg (qrm,
250 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE);
251 qrm->is_valid = htonl ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES);
252 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
253 env);
254 GNUNET_SERVICE_client_continue (client);
255}
256
257
258/**
259 * Flood the given revocation message to all neighbours.
260 *
261 * @param cls the `struct RevokeMessage` to flood
262 * @param target a neighbour
263 * @param value our `struct PeerEntry` for the neighbour
264 * @return #GNUNET_OK (continue to iterate)
265 */
266static int
267do_flood (void *cls,
268 const struct GNUNET_PeerIdentity *target,
269 void *value)
270{
271 const struct RevokeMessage *rm = cls;
272 struct PeerEntry *pe = value;
273 struct GNUNET_MQ_Envelope *e;
274 struct RevokeMessage *cp;
275
276 if (NULL == pe->mq)
277 return GNUNET_OK; /* peer connected to us via SET,
278 but we have no direct CORE
279 connection for flooding */
280 e = GNUNET_MQ_msg_extra (cp,
281 htonl (rm->pow_size),
282 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
283 *cp = *rm;
284 memcpy (&cp[1], &rm[1], htonl (rm->pow_size));
285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
286 "Flooding revocation to `%s'\n",
287 GNUNET_i2s (target));
288 GNUNET_MQ_send (pe->mq,
289 e);
290 return GNUNET_OK;
291}
292
293
294/**
295 * Publicize revocation message. Stores the message locally in the
296 * database and passes it to all connected neighbours (and adds it to
297 * the set for future connections).
298 *
299 * @param rm message to publicize
300 * @return #GNUNET_OK on success, #GNUNET_NO if we encountered an error,
301 * #GNUNET_SYSERR if the message was malformed
302 */
303static int
304publicize_rm (const struct RevokeMessage *rm)
305{
306 struct RevokeMessage *cp;
307 struct GNUNET_HashCode hc;
308 struct GNUNET_SETU_Element e;
309 ssize_t pklen;
310 const struct GNUNET_IDENTITY_PublicKey *pk;
311
312 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1];
313 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
314 pklen = GNUNET_IDENTITY_key_get_length (pk);
315 if (0 > pklen)
316 {
317 GNUNET_break_op (0);
318 return GNUNET_SYSERR;
319 }
320 GNUNET_CRYPTO_hash (pk,
321 pklen,
322 &hc);
323 if (GNUNET_YES ==
324 GNUNET_CONTAINER_multihashmap_contains (revocation_map,
325 &hc))
326 {
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
328 "Duplicate revocation received from peer. Ignored.\n");
329 return GNUNET_OK;
330 }
331 if (GNUNET_OK !=
332 verify_revoke_message (rm))
333 {
334 GNUNET_break_op (0);
335 return GNUNET_SYSERR;
336 }
337 /* write to disk */
338 if (sizeof(struct RevokeMessage) !=
339 GNUNET_DISK_file_write (revocation_db,
340 rm,
341 sizeof(struct RevokeMessage)))
342 {
343 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
344 "write");
345 return GNUNET_NO;
346 }
347 if (GNUNET_OK !=
348 GNUNET_DISK_file_sync (revocation_db))
349 {
350 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
351 "sync");
352 return GNUNET_NO;
353 }
354 /* keep copy in memory */
355 cp = (struct RevokeMessage *) GNUNET_copy_message (&rm->header);
356 GNUNET_break (GNUNET_OK ==
357 GNUNET_CONTAINER_multihashmap_put (revocation_map,
358 &hc,
359 cp,
360 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
361 /* add to set for future connections */
362 e.size = htons (rm->header.size);
363 e.element_type = GNUNET_BLOCK_TYPE_REVOCATION;
364 e.data = rm;
365 if (GNUNET_OK !=
366 GNUNET_SETU_add_element (revocation_set,
367 &e,
368 NULL,
369 NULL))
370 {
371 GNUNET_break (0);
372 return GNUNET_OK;
373 }
374 else
375 {
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
377 "Added revocation info to SET\n");
378 }
379 /* flood to neighbours */
380 GNUNET_CONTAINER_multipeermap_iterate (peers,
381 &do_flood,
382 cp);
383 return GNUNET_OK;
384}
385
386
387static int
388check_revoke_message (void *cls,
389 const struct RevokeMessage *rm)
390{
391 uint16_t size;
392
393 size = ntohs (rm->header.size);
394 if (size <= sizeof(struct RevokeMessage) ||
395 (size > UINT16_MAX))
396 {
397 GNUNET_break (0);
398 return GNUNET_SYSERR;
399 }
400 return GNUNET_OK;
401
402}
403
404
405/**
406 * Handle REVOKE message from client.
407 *
408 * @param cls client who sent the message
409 * @param rm the message received
410 */
411static void
412handle_revoke_message (void *cls,
413 const struct RevokeMessage *rm)
414{
415 struct GNUNET_SERVICE_Client *client = cls;
416 struct GNUNET_MQ_Envelope *env;
417 struct RevocationResponseMessage *rrm;
418 int ret;
419
420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
421 "Received REVOKE message from client\n");
422 if (GNUNET_SYSERR == (ret = publicize_rm (rm)))
423 {
424 GNUNET_break_op (0);
425 GNUNET_SERVICE_client_drop (client);
426 return;
427 }
428 env = GNUNET_MQ_msg (rrm,
429 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE);
430 rrm->is_valid = htonl ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES);
431 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
432 env);
433 GNUNET_SERVICE_client_continue (client);
434}
435
436
437static int
438check_p2p_revoke (void *cls,
439 const struct RevokeMessage *rm)
440{
441 uint16_t size;
442
443 size = ntohs (rm->header.size);
444 if (size <= sizeof(struct RevokeMessage))
445 {
446 GNUNET_break (0);
447 return GNUNET_SYSERR;
448 }
449 return GNUNET_OK;
450
451}
452
453
454/**
455 * Core handler for flooded revocation messages.
456 *
457 * @param cls closure unused
458 * @param rm revocation message
459 */
460static void
461handle_p2p_revoke (void *cls,
462 const struct RevokeMessage *rm)
463{
464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
465 "Received REVOKE message\n");
466 GNUNET_break_op (GNUNET_SYSERR !=
467 publicize_rm (rm));
468}
469
470
471/**
472 * Callback for set operation results. Called for each element in the
473 * result set. Each element contains a revocation, which we should
474 * validate and then add to our revocation list (and set).
475 *
476 * @param cls closure
477 * @param element a result element, only valid if status is #GNUNET_SETU_STATUS_OK
478 * @param current_size current set size
479 * @param status see `enum GNUNET_SETU_Status`
480 */
481static void
482add_revocation (void *cls,
483 const struct GNUNET_SETU_Element *element,
484 uint64_t current_size,
485 enum GNUNET_SETU_Status status)
486{
487 struct PeerEntry *peer_entry = cls;
488 const struct RevokeMessage *rm;
489
490 switch (status)
491 {
492 case GNUNET_SETU_STATUS_ADD_LOCAL:
493 if (element->size != sizeof(struct RevokeMessage))
494 {
495 GNUNET_break_op (0);
496 return;
497 }
498 if (GNUNET_BLOCK_TYPE_REVOCATION != element->element_type)
499 {
500 GNUNET_STATISTICS_update (stats,
501 gettext_noop (
502 "# unsupported revocations received via set union"),
503 1,
504 GNUNET_NO);
505 return;
506 }
507 rm = element->data;
508 (void) handle_p2p_revoke (NULL,
509 rm);
510 GNUNET_STATISTICS_update (stats,
511 gettext_noop (
512 "# revocation messages received via set union"),
513 1, GNUNET_NO);
514 break;
515 case GNUNET_SETU_STATUS_FAILURE:
516 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
517 _ ("Error computing revocation set union with %s\n"),
518 GNUNET_i2s (&peer_entry->id));
519 peer_entry->so = NULL;
520 GNUNET_STATISTICS_update (stats,
521 gettext_noop ("# revocation set unions failed"),
522 1,
523 GNUNET_NO);
524 break;
525 case GNUNET_SETU_STATUS_DONE:
526 peer_entry->so = NULL;
527 GNUNET_STATISTICS_update (stats,
528 gettext_noop (
529 "# revocation set unions completed"),
530 1,
531 GNUNET_NO);
532 break;
533 default:
534 GNUNET_break (0);
535 break;
536 }
537}
538
539
540/**
541 * The timeout for performing the set union has expired,
542 * run the set operation on the revocation certificates.
543 *
544 * @param cls NULL
545 */
546static void
547transmit_task_cb (void *cls)
548{
549 struct PeerEntry *peer_entry = cls;
550
551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
552 "Starting set exchange with peer `%s'\n",
553 GNUNET_i2s (&peer_entry->id));
554 peer_entry->transmit_task = NULL;
555 GNUNET_assert (NULL == peer_entry->so);
556 peer_entry->so = GNUNET_SETU_prepare (&peer_entry->id,
557 &revocation_set_union_app_id,
558 NULL,
559 (struct GNUNET_SETU_Option[]) { { 0 } },
560 &add_revocation,
561 peer_entry);
562 if (GNUNET_OK !=
563 GNUNET_SETU_commit (peer_entry->so,
564 revocation_set))
565 {
566 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
567 _ ("SET service crashed, terminating revocation service\n"));
568 GNUNET_SCHEDULER_shutdown ();
569 return;
570 }
571}
572
573
574/**
575 * Method called whenever a peer connects. Sets up the PeerEntry and
576 * schedules the initial revocation set exchange with this peer.
577 *
578 * @param cls closure
579 * @param peer peer identity this notification is about
580 */
581static void *
582handle_core_connect (void *cls,
583 const struct GNUNET_PeerIdentity *peer,
584 struct GNUNET_MQ_Handle *mq)
585{
586 struct PeerEntry *peer_entry;
587 struct GNUNET_HashCode my_hash;
588 struct GNUNET_HashCode peer_hash;
589
590 if (0 == GNUNET_memcmp (peer,
591 &my_identity))
592 {
593 return NULL;
594 }
595
596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
597 "Peer `%s' connected to us\n",
598 GNUNET_i2s (peer));
599 GNUNET_STATISTICS_update (stats,
600 "# peers connected",
601 1,
602 GNUNET_NO);
603 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
604 peer);
605 if (NULL != peer_entry)
606 {
607 /* This can happen if "core"'s notification is a tad late
608 and CADET+SET were faster and already produced a
609 #handle_revocation_union_request() for us to deal
610 with. This should be rare, but isn't impossible. */
611 peer_entry->mq = mq;
612 return peer_entry;
613 }
614 peer_entry = new_peer_entry (peer);
615 peer_entry->mq = mq;
616 GNUNET_CRYPTO_hash (&my_identity,
617 sizeof(my_identity),
618 &my_hash);
619 GNUNET_CRYPTO_hash (peer,
620 sizeof(*peer),
621 &peer_hash);
622 if (0 < GNUNET_CRYPTO_hash_cmp (&my_hash,
623 &peer_hash))
624 {
625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
626 "Starting SET operation with peer `%s'\n",
627 GNUNET_i2s (peer));
628 peer_entry->transmit_task =
629 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
630 &transmit_task_cb,
631 peer_entry);
632 }
633 return peer_entry;
634}
635
636
637/**
638 * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels
639 * any pending transmission requests to that peer.
640 *
641 * @param cls closure
642 * @param peer peer identity this notification is about
643 * @param internal_cls our `struct PeerEntry` for this peer
644 */
645static void
646handle_core_disconnect (void *cls,
647 const struct GNUNET_PeerIdentity *peer,
648 void *internal_cls)
649{
650 struct PeerEntry *peer_entry = internal_cls;
651
652 if (0 == GNUNET_memcmp (peer,
653 &my_identity))
654 return;
655 GNUNET_assert (NULL != peer_entry);
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
657 "Peer `%s' disconnected from us\n",
658 GNUNET_i2s (peer));
659 GNUNET_assert (GNUNET_YES ==
660 GNUNET_CONTAINER_multipeermap_remove (peers,
661 peer,
662 peer_entry));
663 if (NULL != peer_entry->transmit_task)
664 {
665 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
666 peer_entry->transmit_task = NULL;
667 }
668 if (NULL != peer_entry->so)
669 {
670 GNUNET_SETU_operation_cancel (peer_entry->so);
671 peer_entry->so = NULL;
672 }
673 GNUNET_free (peer_entry);
674 GNUNET_STATISTICS_update (stats,
675 "# peers connected",
676 -1,
677 GNUNET_NO);
678}
679
680
681/**
682 * Free all values in a hash map.
683 *
684 * @param cls NULL
685 * @param key the key
686 * @param value value to free
687 * @return #GNUNET_OK (continue to iterate)
688 */
689static int
690free_entry (void *cls,
691 const struct GNUNET_HashCode *key,
692 void *value)
693{
694 GNUNET_free (value);
695 return GNUNET_OK;
696}
697
698
699/**
700 * Task run during shutdown.
701 *
702 * @param cls unused
703 */
704static void
705shutdown_task (void *cls)
706{
707 if (NULL != revocation_set)
708 {
709 GNUNET_SETU_destroy (revocation_set);
710 revocation_set = NULL;
711 }
712 if (NULL != revocation_union_listen_handle)
713 {
714 GNUNET_SETU_listen_cancel (revocation_union_listen_handle);
715 revocation_union_listen_handle = NULL;
716 }
717 if (NULL != core_api)
718 {
719 GNUNET_CORE_disconnect (core_api);
720 core_api = NULL;
721 }
722 if (NULL != stats)
723 {
724 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
725 stats = NULL;
726 }
727 if (NULL != peers)
728 {
729 GNUNET_CONTAINER_multipeermap_destroy (peers);
730 peers = NULL;
731 }
732 if (NULL != revocation_db)
733 {
734 GNUNET_DISK_file_close (revocation_db);
735 revocation_db = NULL;
736 }
737 GNUNET_CONTAINER_multihashmap_iterate (revocation_map,
738 &free_entry,
739 NULL);
740 GNUNET_CONTAINER_multihashmap_destroy (revocation_map);
741}
742
743
744/**
745 * Called on core init/fail.
746 *
747 * @param cls service closure
748 * @param identity the public identity of this peer
749 */
750static void
751core_init (void *cls,
752 const struct GNUNET_PeerIdentity *identity)
753{
754 if (NULL == identity)
755 {
756 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
757 "Connection to core FAILED!\n");
758 GNUNET_SCHEDULER_shutdown ();
759 return;
760 }
761 my_identity = *identity;
762}
763
764
765/**
766 * Called when another peer wants to do a set operation with the
767 * local peer. If a listen error occurs, the 'request' is NULL.
768 *
769 * @param cls closure
770 * @param other_peer the other peer
771 * @param context_msg message with application specific information from
772 * the other peer
773 * @param request request from the other peer (never NULL), use GNUNET_SETU_accept()
774 * to accept it, otherwise the request will be refused
775 * Note that we can't just return value from the listen callback,
776 * as it is also necessary to specify the set we want to do the
777 * operation with, which sometimes can be derived from the context
778 * message. It's necessary to specify the timeout.
779 */
780static void
781handle_revocation_union_request (void *cls,
782 const struct GNUNET_PeerIdentity *other_peer,
783 const struct GNUNET_MessageHeader *context_msg,
784 struct GNUNET_SETU_Request *request)
785{
786 struct PeerEntry *peer_entry;
787
788 if (NULL == request)
789 {
790 GNUNET_break (0);
791 return;
792 }
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
794 "Received set exchange request from peer `%s'\n",
795 GNUNET_i2s (other_peer));
796 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
797 other_peer);
798 if (NULL == peer_entry)
799 {
800 peer_entry = new_peer_entry (other_peer);
801 }
802 if (NULL != peer_entry->so)
803 {
804 GNUNET_break_op (0);
805 return;
806 }
807 peer_entry->so = GNUNET_SETU_accept (request,
808 (struct GNUNET_SETU_Option[]) { { 0 } },
809 &add_revocation,
810 peer_entry);
811 if (GNUNET_OK !=
812 GNUNET_SETU_commit (peer_entry->so,
813 revocation_set))
814 {
815 GNUNET_break (0);
816 GNUNET_SCHEDULER_shutdown ();
817 return;
818 }
819}
820
821
822/**
823 * Handle network size estimate clients.
824 *
825 * @param cls closure
826 * @param server the initialized server
827 * @param c configuration to use
828 */
829static void
830run (void *cls,
831 const struct GNUNET_CONFIGURATION_Handle *c,
832 struct GNUNET_SERVICE_Handle *service)
833{
834 struct GNUNET_MQ_MessageHandler core_handlers[] = {
835 GNUNET_MQ_hd_var_size (p2p_revoke,
836 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
837 struct RevokeMessage,
838 NULL),
839 GNUNET_MQ_handler_end ()
840 };
841 char *fn;
842 uint64_t left;
843 struct RevokeMessage *rm;
844 struct GNUNET_HashCode hc;
845 const struct GNUNET_IDENTITY_PublicKey *pk;
846
847 GNUNET_CRYPTO_hash ("revocation-set-union-application-id",
848 strlen ("revocation-set-union-application-id"),
849 &revocation_set_union_app_id);
850 if (GNUNET_OK !=
851 GNUNET_CONFIGURATION_get_value_filename (c,
852 "REVOCATION",
853 "DATABASE",
854 &fn))
855 {
856 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
857 "REVOCATION",
858 "DATABASE");
859 GNUNET_SCHEDULER_shutdown ();
860 return;
861 }
862 cfg = c;
863 revocation_map = GNUNET_CONTAINER_multihashmap_create (16,
864 GNUNET_NO);
865 if (GNUNET_OK !=
866 GNUNET_CONFIGURATION_get_value_number (cfg,
867 "REVOCATION",
868 "WORKBITS",
869 &revocation_work_required))
870 {
871 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
872 "REVOCATION",
873 "WORKBITS");
874 GNUNET_SCHEDULER_shutdown ();
875 GNUNET_free (fn);
876 return;
877 }
878 if (revocation_work_required >= sizeof(struct GNUNET_HashCode) * 8)
879 {
880 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
881 "REVOCATION",
882 "WORKBITS",
883 _ ("Value is too large.\n"));
884 GNUNET_SCHEDULER_shutdown ();
885 GNUNET_free (fn);
886 return;
887 }
888 if (GNUNET_OK !=
889 GNUNET_CONFIGURATION_get_value_time (cfg,
890 "REVOCATION",
891 "EPOCH_DURATION",
892 &epoch_duration))
893 {
894 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
895 "REVOCATION",
896 "EPOCH_DURATION");
897 GNUNET_SCHEDULER_shutdown ();
898 GNUNET_free (fn);
899 return;
900 }
901
902 revocation_set = GNUNET_SETU_create (cfg);
903 revocation_union_listen_handle
904 = GNUNET_SETU_listen (cfg,
905 &revocation_set_union_app_id,
906 &handle_revocation_union_request,
907 NULL);
908 revocation_db = GNUNET_DISK_file_open (fn,
909 GNUNET_DISK_OPEN_READWRITE
910 | GNUNET_DISK_OPEN_CREATE,
911 GNUNET_DISK_PERM_USER_READ
912 | GNUNET_DISK_PERM_USER_WRITE
913 | GNUNET_DISK_PERM_GROUP_READ
914 | GNUNET_DISK_PERM_OTHER_READ);
915 if (NULL == revocation_db)
916 {
917 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
918 "REVOCATION",
919 "DATABASE",
920 _ ("Could not open revocation database file!"));
921 GNUNET_SCHEDULER_shutdown ();
922 GNUNET_free (fn);
923 return;
924 }
925 if (GNUNET_OK !=
926 GNUNET_DISK_file_size (fn, &left, GNUNET_YES, GNUNET_YES))
927 left = 0;
928 while (left > sizeof(struct RevokeMessage))
929 {
930 rm = GNUNET_new (struct RevokeMessage);
931 if (sizeof(struct RevokeMessage) !=
932 GNUNET_DISK_file_read (revocation_db,
933 rm,
934 sizeof(struct RevokeMessage)))
935 {
936 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
937 "read",
938 fn);
939 GNUNET_free (rm);
940 GNUNET_SCHEDULER_shutdown ();
941 GNUNET_free (fn);
942 return;
943 }
944 struct GNUNET_REVOCATION_PowP *pow = (struct
945 GNUNET_REVOCATION_PowP *) &rm[1];
946 ssize_t ksize;
947 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
948 ksize = GNUNET_IDENTITY_key_get_length (pk);
949 if (0 > ksize)
950 {
951 GNUNET_break_op (0);
952 GNUNET_free (rm);
953 GNUNET_free (fn);
954 return;
955 }
956 GNUNET_CRYPTO_hash (pk,
957 ksize,
958 &hc);
959 GNUNET_break (GNUNET_OK ==
960 GNUNET_CONTAINER_multihashmap_put (revocation_map,
961 &hc,
962 rm,
963 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
964 }
965 GNUNET_free (fn);
966
967 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
968 NULL);
969 peers = GNUNET_CONTAINER_multipeermap_create (128,
970 GNUNET_YES);
971 /* Connect to core service and register core handlers */
972 core_api = GNUNET_CORE_connect (cfg, /* Main configuration */
973 NULL, /* Closure passed to functions */
974 &core_init, /* Call core_init once connected */
975 &handle_core_connect, /* Handle connects */
976 &handle_core_disconnect, /* Handle disconnects */
977 core_handlers); /* Register these handlers */
978 if (NULL == core_api)
979 {
980 GNUNET_SCHEDULER_shutdown ();
981 return;
982 }
983 stats = GNUNET_STATISTICS_create ("revocation",
984 cfg);
985}
986
987
988/**
989 * Define "main" method using service macro.
990 */
991GNUNET_SERVICE_MAIN
992 ("revocation",
993 GNUNET_SERVICE_OPTION_NONE,
994 &run,
995 &client_connect_cb,
996 &client_disconnect_cb,
997 NULL,
998 GNUNET_MQ_hd_fixed_size (query_message,
999 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY,
1000 struct QueryMessage,
1001 NULL),
1002 GNUNET_MQ_hd_var_size (revoke_message,
1003 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
1004 struct RevokeMessage,
1005 NULL),
1006 GNUNET_MQ_handler_end ());
1007
1008
1009#if defined(__linux__) && defined(__GLIBC__)
1010#include <malloc.h>
1011
1012/**
1013 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1014 */
1015void __attribute__ ((constructor))
1016GNUNET_REVOCATION_memory_init ()
1017{
1018 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1019 mallopt (M_TOP_PAD, 1 * 1024);
1020 malloc_trim (0);
1021}
1022
1023
1024#endif
1025
1026
1027/* end of gnunet-service-revocation.c */
diff --git a/src/revocation/plugin_block_revocation.c b/src/revocation/plugin_block_revocation.c
deleted file mode 100644
index da5882d59..000000000
--- a/src/revocation/plugin_block_revocation.c
+++ /dev/null
@@ -1,275 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2017 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/**
22 * @file block/plugin_block_revocation.c
23 * @brief revocation for a block plugin
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_signatures.h"
29#include "gnunet_block_plugin.h"
30#include "gnunet_block_group_lib.h"
31#include "revocation.h"
32#include "gnunet_revocation_service.h"
33
34#define DEBUG_REVOCATION GNUNET_EXTRA_LOGGING
35
36/**
37 * Number of bits we set per entry in the bloomfilter.
38 * Do not change!
39 */
40#define BLOOMFILTER_K 16
41
42
43/**
44 * How big is the BF we use for DHT blocks?
45 */
46#define REVOCATION_BF_SIZE 8
47
48
49/**
50 * Context used inside the plugin.
51 */
52struct InternalContext
53{
54 unsigned int matching_bits;
55 struct GNUNET_TIME_Relative epoch_duration;
56};
57
58
59/**
60 * Create a new block group.
61 *
62 * @param ctx block context in which the block group is created
63 * @param type type of the block for which we are creating the group
64 * @param nonce random value used to seed the group creation
65 * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh
66 * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh
67 * @param va variable arguments specific to @a type
68 * @return block group handle, NULL if block groups are not supported
69 * by this @a type of block (this is not an error)
70 */
71static struct GNUNET_BLOCK_Group *
72block_plugin_revocation_create_group (void *cls,
73 enum GNUNET_BLOCK_Type type,
74 uint32_t nonce,
75 const void *raw_data,
76 size_t raw_data_size,
77 va_list va)
78{
79 unsigned int bf_size;
80 const char *guard;
81
82 guard = va_arg (va, const char *);
83 if (0 == strcmp (guard,
84 "seen-set-size"))
85 bf_size = GNUNET_BLOCK_GROUP_compute_bloomfilter_size (va_arg (va, unsigned
86 int),
87 BLOOMFILTER_K);
88 else if (0 == strcmp (guard,
89 "filter-size"))
90 bf_size = va_arg (va, unsigned int);
91 else
92 {
93 GNUNET_break (0);
94 bf_size = REVOCATION_BF_SIZE;
95 }
96 GNUNET_break (NULL == va_arg (va, const char *));
97 return GNUNET_BLOCK_GROUP_bf_create (cls,
98 bf_size,
99 BLOOMFILTER_K,
100 type,
101 nonce,
102 raw_data,
103 raw_data_size);
104}
105
106
107/**
108 * Function called to validate a reply or a request. For
109 * request evaluation, simply pass "NULL" for the reply_block.
110 *
111 * @param cls our `struct InternalContext`
112 * @param ctx context
113 * @param type block type
114 * @param group block group to use
115 * @param eo control flags
116 * @param query original query (hash)
117 * @param xquery extrended query data (can be NULL, depending on type)
118 * @param xquery_size number of bytes in xquery
119 * @param reply_block response to validate
120 * @param reply_block_size number of bytes in reply block
121 * @return characterization of result
122 */
123static enum GNUNET_BLOCK_EvaluationResult
124block_plugin_revocation_evaluate (void *cls,
125 struct GNUNET_BLOCK_Context *ctx,
126 enum GNUNET_BLOCK_Type type,
127 struct GNUNET_BLOCK_Group *group,
128 enum GNUNET_BLOCK_EvaluationOptions eo,
129 const struct GNUNET_HashCode *query,
130 const void *xquery,
131 size_t xquery_size,
132 const void *reply_block,
133 size_t reply_block_size)
134{
135 struct InternalContext *ic = cls;
136 struct GNUNET_HashCode chash;
137 ssize_t pklen;
138 const struct RevokeMessage *rm = reply_block;
139
140 if (NULL == reply_block)
141 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
142 if (reply_block_size != sizeof(*rm))
143 {
144 GNUNET_break_op (0);
145 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
146 }
147 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1];
148 const struct GNUNET_IDENTITY_PublicKey *pk;
149 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
150 if (GNUNET_YES != GNUNET_REVOCATION_check_pow (pow,
151 ic->matching_bits,
152 ic->epoch_duration))
153 {
154 GNUNET_break_op (0);
155 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
156 }
157 pklen = GNUNET_IDENTITY_key_get_length (pk);
158 if (0 > pklen)
159 {
160 GNUNET_break_op (0);
161 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
162 }
163 GNUNET_CRYPTO_hash (pk,
164 pklen,
165 &chash);
166 if (GNUNET_YES ==
167 GNUNET_BLOCK_GROUP_bf_test_and_set (group,
168 &chash))
169 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
170 return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
171}
172
173
174/**
175 * Function called to obtain the key for a block.
176 *
177 * @param cls closure
178 * @param type block type
179 * @param block block to get the key for
180 * @param block_size number of bytes in block
181 * @param key set to the key (query) for the given block
182 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
183 * (or if extracting a key from a block of this type does not work)
184 */
185static int
186block_plugin_revocation_get_key (void *cls,
187 enum GNUNET_BLOCK_Type type,
188 const void *block,
189 size_t block_size,
190 struct GNUNET_HashCode *key)
191{
192 const struct RevokeMessage *rm = block;
193 ssize_t ksize;
194
195 if (block_size <= sizeof(*rm))
196 {
197 GNUNET_break_op (0);
198 return GNUNET_SYSERR;
199 }
200 struct GNUNET_REVOCATION_PowP *pow = (struct GNUNET_REVOCATION_PowP *) &rm[1];
201 const struct GNUNET_IDENTITY_PublicKey *pk;
202 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
203 ksize = GNUNET_IDENTITY_key_get_length (pk);
204 if (0 > ksize)
205 {
206 GNUNET_break_op (0);
207 return GNUNET_SYSERR;
208 }
209 GNUNET_CRYPTO_hash (pk,
210 ksize,
211 key);
212 return GNUNET_OK;
213}
214
215
216/**
217 * Entry point for the plugin.
218 *
219 * @param cls the configuration to use
220 */
221void *
222libgnunet_plugin_block_revocation_init (void *cls)
223{
224 static enum GNUNET_BLOCK_Type types[] = {
225 GNUNET_BLOCK_TYPE_REVOCATION,
226 GNUNET_BLOCK_TYPE_ANY /* end of list */
227 };
228 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
229 struct GNUNET_BLOCK_PluginFunctions *api;
230 struct InternalContext *ic;
231 unsigned long long matching_bits;
232 struct GNUNET_TIME_Relative epoch_duration;
233
234 if (GNUNET_OK !=
235 GNUNET_CONFIGURATION_get_value_number (cfg,
236 "REVOCATION",
237 "WORKBITS",
238 &matching_bits))
239 return NULL;
240 if (GNUNET_OK !=
241 GNUNET_CONFIGURATION_get_value_time (cfg,
242 "REVOCATION",
243 "EPOCH_DURATION",
244 &epoch_duration))
245 return NULL;
246
247 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
248 api->evaluate = &block_plugin_revocation_evaluate;
249 api->get_key = &block_plugin_revocation_get_key;
250 api->create_group = &block_plugin_revocation_create_group;
251 api->types = types;
252 ic = GNUNET_new (struct InternalContext);
253 ic->matching_bits = (unsigned int) matching_bits;
254 ic->epoch_duration = epoch_duration;
255 api->cls = ic;
256 return api;
257}
258
259
260/**
261 * Exit point from the plugin.
262 */
263void *
264libgnunet_plugin_block_revocation_done (void *cls)
265{
266 struct GNUNET_BLOCK_PluginFunctions *api = cls;
267 struct InternalContext *ic = api->cls;
268
269 GNUNET_free (ic);
270 GNUNET_free (api);
271 return NULL;
272}
273
274
275/* end of plugin_block_revocation.c */
diff --git a/src/revocation/revocation.conf.in b/src/revocation/revocation.conf.in
deleted file mode 100644
index d2d7de46e..000000000
--- a/src/revocation/revocation.conf.in
+++ /dev/null
@@ -1,19 +0,0 @@
1[revocation]
2START_ON_DEMAND = @START_ON_DEMAND@
3IMMEDIATE_START = YES
4@JAVAPORT@PORT = 2112
5HOSTNAME = localhost
6BINARY = gnunet-service-revocation
7ACCEPT_FROM = 127.0.0.1;
8ACCEPT_FROM6 = ::1;
9UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-revocation.sock
10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES
12
13# 2^25 hash operations take about 16-24h on a first-generation i7
14# (using only a single-core) with SCRYPT.
15# DO NOT CHANGE THIS VALUE, doing so will break the protocol!
16WORKBITS = 22
17EPOCH_DURATION = 365 d
18
19DATABASE = $GNUNET_DATA_HOME/revocation.dat
diff --git a/src/revocation/revocation.h b/src/revocation/revocation.h
deleted file mode 100644
index c3a9c9e6b..000000000
--- a/src/revocation/revocation.h
+++ /dev/null
@@ -1,117 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013 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/**
22 * @author Christian Grothoff
23 * @file revocation/revocation.h
24 * @brief messages for key revocation
25 */
26#ifndef REVOCATION_H
27#define REVOCATION_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_revocation_service.h"
31
32GNUNET_NETWORK_STRUCT_BEGIN
33
34/**
35 * Query key revocation status.
36 */
37struct QueryMessage
38{
39 /**
40 * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_QUERY
41 */
42 struct GNUNET_MessageHeader header;
43
44 /**
45 * For alignment.
46 */
47 uint32_t reserved GNUNET_PACKED;
48
49 /**
50 * Key to check.
51 */
52 struct GNUNET_IDENTITY_PublicKey key;
53};
54
55
56/**
57 * Key revocation response.
58 */
59struct QueryResponseMessage
60{
61 /**
62 * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE
63 */
64 struct GNUNET_MessageHeader header;
65
66 /**
67 * #GNUNET_NO if revoked, #GNUNET_YES if valid.
68 */
69 uint32_t is_valid GNUNET_PACKED;
70};
71
72
73/**
74 * Revoke key. These messages are exchanged between peers (during
75 * flooding) but also sent by the client to the service. When the
76 * client sends it to the service, the message is answered by a
77 * #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE (which is just
78 * in a `struct GNUNET_MessageHeader`.
79 */
80struct RevokeMessage
81{
82 /**
83 * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE
84 */
85 struct GNUNET_MessageHeader header;
86
87 /**
88 * Length of PoW with signature.
89 */
90 uint32_t pow_size GNUNET_PACKED;
91
92 /** Followed by the PoW **/
93};
94
95
96/**
97 * Key revocation response.
98 */
99struct RevocationResponseMessage
100{
101 /**
102 * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE
103 */
104 struct GNUNET_MessageHeader header;
105
106 /**
107 * #GNUNET_NO if revocation failed for internal reasons (e.g. disk full)
108 * #GNUNET_YES on success
109 */
110 uint32_t is_valid GNUNET_PACKED;
111};
112
113
114GNUNET_NETWORK_STRUCT_END
115
116
117#endif
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 */
diff --git a/src/revocation/test_local_revocation.py.in b/src/revocation/test_local_revocation.py.in
deleted file mode 100644
index e667c10ce..000000000
--- a/src/revocation/test_local_revocation.py.in
+++ /dev/null
@@ -1,129 +0,0 @@
1#!@PYTHONEXE@
2# This file is part of GNUnet.
3# (C) 2010, 2018 Christian Grothoff (and other contributing authors)
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# Testcase for ego revocation
21
22import sys
23import os
24import subprocess
25import re
26import shutil
27
28if os.name == 'posix':
29 config = 'gnunet-config'
30 gnunetarm = 'gnunet-arm'
31 ident = 'gnunet-identity'
32 revoc = './gnunet-revocation'
33elif os.name == 'nt':
34 config = 'gnunet-config.exe'
35 gnunetarm = 'gnunet-arm.exe'
36 ident = 'gnunet-identity.exe'
37 revoc = './gnunet-revocation.exe'
38
39TEST_CONFIGURATION = "test_revocation.conf"
40TEST_REVOCATION_EGO = "revoc_test"
41
42get_clean = subprocess.Popen([
43 config, '-c', TEST_CONFIGURATION, '-s', 'PATHS', '-o', 'GNUNET_HOME', '-f'
44],
45 stdout=subprocess.PIPE)
46cleandir, x = get_clean.communicate()
47cleandir = cleandir.decode("utf-8")
48cleandir = cleandir.rstrip('\n').rstrip('\r')
49
50if os.path.isdir(cleandir):
51 shutil.rmtree(cleandir, True)
52
53res = 0
54arm = subprocess.Popen([gnunetarm, '-s', '-c', TEST_CONFIGURATION])
55arm.communicate()
56
57try:
58 print("Creating an ego " + TEST_REVOCATION_EGO)
59 sys.stdout.flush()
60 sys.stderr.flush()
61 idc = subprocess.Popen([
62 ident, '-C', TEST_REVOCATION_EGO, '-c', TEST_CONFIGURATION
63 ])
64 idc.communicate()
65 if idc.returncode != 0:
66 raise Exception(
67 "gnunet-identity failed to create an ego `" + TEST_REVOCATION_EGO +
68 "'"
69 )
70
71 sys.stdout.flush()
72 sys.stderr.flush()
73 idd = subprocess.Popen([ident, '-d'], stdout=subprocess.PIPE)
74 rev_key, x = idd.communicate()
75 rev_key = rev_key.decode("utf-8")
76 if len(rev_key.split()) < 3:
77 raise Exception("can't get revocation key out of `" + rev_key + "'")
78 rev_key = rev_key.split()[2]
79
80 print("Testing key " + rev_key)
81 sys.stdout.flush()
82 sys.stderr.flush()
83 tst = subprocess.Popen([revoc, '-t', rev_key, '-c', TEST_CONFIGURATION],
84 stdout=subprocess.PIPE)
85 output_not_revoked, x = tst.communicate()
86 output_not_revoked = output_not_revoked.decode("utf-8")
87 if tst.returncode != 0:
88 raise Exception(
89 "gnunet-revocation failed to test a key - " + str(tst.returncode) +
90 ": " + output_not_revoked
91 )
92 if 'valid' not in output_not_revoked:
93 res = 1
94 print("Key was not valid")
95 else:
96 print("Key was valid")
97
98 print("Revoking key " + rev_key)
99 sys.stdout.flush()
100 sys.stderr.flush()
101 rev = subprocess.Popen([
102 revoc, '-R', TEST_REVOCATION_EGO, '-p', '-c', TEST_CONFIGURATION
103 ])
104 rev.communicate()
105 if rev.returncode != 0:
106 raise Exception("gnunet-revocation failed to revoke a key")
107
108 print("Testing revoked key " + rev_key)
109 sys.stdout.flush()
110 sys.stderr.flush()
111 tst = subprocess.Popen([revoc, '-t', rev_key, '-c', TEST_CONFIGURATION],
112 stdout=subprocess.PIPE)
113 output_revoked, x = tst.communicate()
114 output_revoked = output_revoked.decode("utf-8")
115 if tst.returncode != 0:
116 raise Exception("gnunet-revocation failed to test a revoked key")
117 if 'revoked' not in output_revoked:
118 res = 1
119 print("Key was not revoked")
120 else:
121 print("Key was revoked")
122
123finally:
124 arm = subprocess.Popen([gnunetarm, '-e', '-c', TEST_CONFIGURATION])
125 arm.communicate()
126 if os.path.isdir(cleandir):
127 shutil.rmtree(cleandir, True)
128
129sys.exit(res)
diff --git a/src/revocation/test_revocation.c b/src/revocation/test_revocation.c
deleted file mode 100644
index c6457016f..000000000
--- a/src/revocation/test_revocation.c
+++ /dev/null
@@ -1,419 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 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/test_revocation.c
22 * @brief base testcase for revocation exchange
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_core_service.h"
28#include "gnunet_identity_service.h"
29#include "gnunet_revocation_service.h"
30#include "gnunet_testbed_service.h"
31
32#define NUM_TEST_PEERS 2
33
34struct TestPeer
35{
36 struct GNUNET_TESTBED_Peer *p;
37 struct GNUNET_TESTBED_Operation *identity_op;
38 struct GNUNET_TESTBED_Operation *core_op;
39 struct GNUNET_IDENTITY_Handle *idh;
40 const struct GNUNET_CONFIGURATION_Handle *cfg;
41 const struct GNUNET_IDENTITY_PrivateKey *privkey;
42 struct GNUNET_IDENTITY_PublicKey pubkey;
43 struct GNUNET_CRYPTO_EcdsaSignature sig;
44 struct GNUNET_IDENTITY_Operation *create_id_op;
45 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
46 struct GNUNET_REVOCATION_Handle *revok_handle;
47 struct GNUNET_CORE_Handle *ch;
48 struct GNUNET_REVOCATION_PowCalculationHandle *pow;
49};
50
51static struct TestPeer testpeers[2];
52
53/**
54 * Return value from main, set to 0 on success.
55 */
56static int ok;
57
58
59static void
60do_shutdown (void *cls)
61{
62 for (unsigned int c = 0; c < NUM_TEST_PEERS; c++)
63 {
64 if (NULL != testpeers[c].create_id_op)
65 {
66 GNUNET_IDENTITY_cancel (testpeers[c].create_id_op);
67 testpeers[c].create_id_op = NULL;
68 }
69 if (NULL != testpeers[c].ego_lookup)
70 {
71 GNUNET_IDENTITY_ego_lookup_cancel (testpeers[c].ego_lookup);
72 testpeers[c].ego_lookup = NULL;
73 }
74 if (NULL != testpeers[c].revok_handle)
75 {
76 GNUNET_REVOCATION_revoke_cancel (testpeers[c].revok_handle);
77 testpeers[c].revok_handle = NULL;
78 }
79 if (NULL != testpeers[c].identity_op)
80 {
81 GNUNET_TESTBED_operation_done (testpeers[c].identity_op);
82 testpeers[c].identity_op = NULL;
83 }
84 if (NULL != testpeers[c].core_op)
85 {
86 GNUNET_TESTBED_operation_done (testpeers[c].core_op);
87 testpeers[c].core_op = NULL;
88 }
89 }
90}
91
92
93static void
94check_revocation (void *cls);
95
96
97static void
98revocation_remote_cb (void *cls, int is_valid)
99{
100 static int repeat = 0;
101
102 if (GNUNET_NO == is_valid)
103 {
104 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Local revocation successful\n");
105 ok = 0;
106 GNUNET_SCHEDULER_shutdown ();
107 return;
108 }
109 if (repeat < 10)
110 {
111 repeat++;
112 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
113 &check_revocation,
114 NULL);
115 return;
116 }
117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Flooding of revocation failed\n");
118 ok = 2;
119 GNUNET_SCHEDULER_shutdown ();
120}
121
122
123static void
124check_revocation (void *cls)
125{
126 GNUNET_REVOCATION_query (testpeers[0].cfg,
127 &testpeers[1].pubkey,
128 &revocation_remote_cb,
129 NULL);
130}
131
132
133static void
134revocation_cb (void *cls, enum GNUNET_GenericReturnValue is_valid)
135{
136 testpeers[1].revok_handle = NULL;
137 if (GNUNET_NO == is_valid)
138 {
139 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Revocation successful\n");
140 check_revocation (NULL);
141 }
142}
143
144
145static struct GNUNET_REVOCATION_PowP *proof_of_work;
146
147static void
148ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
149{
150 static int completed = 0;
151 const struct GNUNET_IDENTITY_PrivateKey *privkey;
152
153 if ((NULL != ego) && (cls == &testpeers[0]))
154 {
155 testpeers[0].ego_lookup = NULL;
156 testpeers[0].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
157 GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[0].pubkey);
158 completed++;
159 }
160 if ((NULL != ego) && (cls == &testpeers[1]))
161 {
162 testpeers[1].ego_lookup = NULL;
163 testpeers[1].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
164 GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[1].pubkey);
165 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Calculating proof of work...\n");
166 privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
167 proof_of_work = GNUNET_malloc (GNUNET_REVOCATION_MAX_PROOF_SIZE);
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);
173 int res =
174 GNUNET_REVOCATION_pow_round (testpeers[1].pow);
175 while (GNUNET_OK != res)
176 {
177 res =
178 GNUNET_REVOCATION_pow_round (testpeers[1].pow);
179 }
180 fprintf (stderr, "Done calculating proof of work\n");
181 completed++;
182 }
183 if (2 == completed)
184 {
185 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Egos retrieved\n");
186 testpeers[1].revok_handle = GNUNET_REVOCATION_revoke (testpeers[1].cfg,
187 proof_of_work,
188 &revocation_cb,
189 NULL);
190 GNUNET_REVOCATION_pow_stop (testpeers[1].pow);
191 }
192}
193
194
195static void
196identity_create_cb (void *cls,
197 const struct GNUNET_IDENTITY_PrivateKey *pk,
198 const char *emsg)
199{
200 static int completed = 0;
201
202 if ((NULL == emsg) && (cls == &testpeers[0]))
203 {
204 testpeers[0].create_id_op = NULL;
205 completed++;
206 }
207 if ((NULL == emsg) && (cls == &testpeers[1]))
208 {
209 testpeers[1].create_id_op = NULL;
210 completed++;
211 }
212 if (2 != completed)
213 return;
214 fprintf (stderr, "Identities created\n");
215 testpeers[0].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[0].cfg,
216 "client",
217 &ego_cb,
218 &testpeers[0]);
219 testpeers[1].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[1].cfg,
220 "toberevoked",
221 &ego_cb,
222 &testpeers[1]);
223}
224
225
226static void
227identity_completion_cb (void *cls,
228 struct GNUNET_TESTBED_Operation *op,
229 void *ca_result,
230 const char *emsg)
231{
232 static int completed = 0;
233
234 completed++;
235 if (NUM_TEST_PEERS != completed)
236 return;
237 fprintf (stderr, "All peers connected @ IDENTITY ...\n");
238 testpeers[0].create_id_op = GNUNET_IDENTITY_create (testpeers[0].idh,
239 "client",
240 NULL,
241 GNUNET_IDENTITY_TYPE_ECDSA,
242 &identity_create_cb,
243 &testpeers[0]);
244 testpeers[1].create_id_op = GNUNET_IDENTITY_create (testpeers[1].idh,
245 "toberevoked",
246 NULL,
247 GNUNET_IDENTITY_TYPE_ECDSA,
248 &identity_create_cb,
249 &testpeers[1]);
250}
251
252
253static void *
254identity_connect_adapter (void *cls,
255 const struct GNUNET_CONFIGURATION_Handle *cfg)
256{
257 struct TestPeer *me = cls;
258
259 me->cfg = cfg;
260 me->idh = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
261 if (NULL == me->idh)
262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create IDENTITY handle \n");
263 return me->idh;
264}
265
266
267static void
268identity_disconnect_adapter (void *cls, void *op_result)
269{
270 struct TestPeer *me = cls;
271
272 GNUNET_IDENTITY_disconnect (me->idh);
273 me->idh = NULL;
274}
275
276
277static void *
278connect_cb (void *cls,
279 const struct GNUNET_PeerIdentity *peer,
280 struct GNUNET_MQ_Handle *mq)
281{
282 static int connects = 0;
283
284 connects++;
285 if (NUM_TEST_PEERS * NUM_TEST_PEERS == connects)
286 {
287 fprintf (stderr, "All peers connected @ CORE ...\n");
288
289 /* Connect to identity service */
290 testpeers[0].identity_op =
291 GNUNET_TESTBED_service_connect (NULL,
292 testpeers[0].p,
293 "identity",
294 &identity_completion_cb,
295 NULL,
296 &identity_connect_adapter,
297 &identity_disconnect_adapter,
298 &testpeers[0]);
299 testpeers[1].identity_op =
300 GNUNET_TESTBED_service_connect (NULL,
301 testpeers[1].p,
302 "identity",
303 *identity_completion_cb,
304 NULL,
305 &identity_connect_adapter,
306 &identity_disconnect_adapter,
307 &testpeers[1]);
308 }
309 return NULL;
310}
311
312
313static void
314core_completion_cb (void *cls,
315 struct GNUNET_TESTBED_Operation *op,
316 void *ca_result,
317 const char *emsg)
318{
319 static int completed = 0;
320
321 completed++;
322 if (NUM_TEST_PEERS == completed)
323 {
324 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to CORE\n");
325 }
326}
327
328
329static void *
330core_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
331{
332 struct TestPeer *me = cls;
333
334 me->cfg = cfg;
335 me->ch = GNUNET_CORE_connect (cfg, me, NULL, &connect_cb, NULL, NULL);
336 if (NULL == me->ch)
337 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create CORE handle \n");
338 return me->ch;
339}
340
341
342static void
343core_disconnect_adapter (void *cls, void *op_result)
344{
345 struct TestPeer *me = cls;
346
347 GNUNET_CORE_disconnect (me->ch);
348 me->ch = NULL;
349}
350
351
352static void
353test_connection (void *cls,
354 struct GNUNET_TESTBED_RunHandle *h,
355 unsigned int num_peers,
356 struct GNUNET_TESTBED_Peer **peers,
357 unsigned int links_succeeded,
358 unsigned int links_failed)
359{
360 unsigned int c;
361
362 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
363 if (NUM_TEST_PEERS != num_peers)
364 {
365 ok = 4;
366 fprintf (stderr,
367 "Only %u out of %u peers were started ...\n",
368 num_peers,
369 NUM_TEST_PEERS);
370 GNUNET_SCHEDULER_shutdown ();
371 return;
372 }
373 /* We are generating a CLIQUE */
374 if (NUM_TEST_PEERS * (NUM_TEST_PEERS - 1) == links_succeeded)
375 {
376 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
377 "Testbed connected peers, initializing test\n");
378 for (c = 0; c < num_peers; c++)
379 {
380 testpeers[c].p = peers[c];
381 testpeers[c].core_op =
382 GNUNET_TESTBED_service_connect (NULL,
383 testpeers[c].p,
384 "core",
385 &core_completion_cb,
386 NULL,
387 &core_connect_adapter,
388 &core_disconnect_adapter,
389 &testpeers[c]);
390 }
391 }
392 else
393 {
394 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testbed failed to connect peers\n");
395 ok = 5;
396 GNUNET_SCHEDULER_shutdown ();
397 return;
398 }
399}
400
401
402int
403main (int argc, char *argv[])
404{
405 ok = 1;
406 /* Connecting initial topology */
407 (void) GNUNET_TESTBED_test_run ("test-revocation",
408 "test_revocation.conf",
409 NUM_TEST_PEERS,
410 0,
411 NULL,
412 NULL,
413 &test_connection,
414 NULL);
415 return ok;
416}
417
418
419/* end of test_revocation.c */
diff --git a/src/revocation/test_revocation.conf b/src/revocation/test_revocation.conf
deleted file mode 100644
index 66e2cdcc9..000000000
--- a/src/revocation/test_revocation.conf
+++ /dev/null
@@ -1,31 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2
3[paths]
4GNUNET_HOME=$GNUNET_TMP/test-revocation-service
5SERVICEHOME=$GNUNET_TMP/test-revocation-service
6
7[revocation]
8WORKBITS = 3
9IMMEDIATE_START = YES
10EPOCH_DURATION = 365 d
11
12[identity]
13# Directory where we store information about our egos
14EGODIR = $GNUNET_HOME/identity/egos/
15SUBSYSTEM_CFG = $SERVICEHOME/s.conf
16
17[nat]
18RETURN_LOCAL_ADDRESSES = YES
19
20[transport]
21PLUGINS = tcp
22
23[peerinfo]
24USE_INCLUDED_HELLOS = NO
25
26[testbed]
27OVERLAY_TOPOLOGY = CLIQUE
28SETUP_TIMEOUT = 10 s
29OPERATION_TIMEOUT = 5 s
30CACHE_SIZE = 0
31