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.c196
-rw-r--r--src/revocation/gnunet-revocation.c581
-rw-r--r--src/revocation/gnunet-service-revocation.c1032
-rw-r--r--src/revocation/plugin_block_revocation.c297
-rw-r--r--src/revocation/revocation.conf.in19
-rw-r--r--src/revocation/revocation.h125
-rw-r--r--src/revocation/revocation_api.c773
-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, 3719 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 a34a6bc98..000000000
--- a/src/revocation/gnunet-revocation-tvg.c
+++ /dev/null
@@ -1,196 +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 "revocation.h"
33#include <inttypes.h>
34
35#define TEST_EPOCHS 2
36#define TEST_DIFFICULTY 5
37
38static char* d_pkey =
39"6fea32c05af58bfa979553d188605fd57d8bf9cc263b78d5f7478c07b998ed70";
40
41int parsehex(char *src, char *dst, size_t dstlen, int invert)
42{
43 char *line = src;
44 char *data = line;
45 int off;
46 int read_byte;
47 int data_len = 0;
48
49 while (sscanf(data, " %02x%n", &read_byte, &off) == 1) {
50 if (invert)
51 dst[dstlen - 1 - data_len++] = read_byte;
52 else
53 dst[data_len++] = read_byte;
54 data += off;
55 }
56 return data_len;
57}
58
59
60static void
61print_bytes_ (void *buf,
62 size_t buf_len,
63 int fold,
64 int in_be)
65{
66 int i;
67
68 for (i = 0; i < buf_len; i++)
69 {
70 if ((0 != i) && (0 != fold) && (i % fold == 0))
71 printf ("\n");
72 if (in_be)
73 printf ("%02x", ((unsigned char*) buf)[buf_len - 1 - i]);
74 else
75 printf ("%02x", ((unsigned char*) buf)[i]);
76 }
77 printf ("\n");
78}
79
80static void
81print_bytes (void *buf,
82 size_t buf_len,
83 int fold)
84{
85 print_bytes_ (buf, buf_len, fold, 0);
86}
87
88
89
90/**
91 * Main function that will be run.
92 *
93 * @param cls closure
94 * @param args remaining command-line arguments
95 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
96 * @param cfg configuration
97 */
98static void
99run (void *cls,
100 char *const *args,
101 const char *cfgfile,
102 const struct GNUNET_CONFIGURATION_Handle *cfg)
103{
104 struct GNUNET_IDENTITY_PrivateKey id_priv;
105 struct GNUNET_IDENTITY_PublicKey id_pub;
106 struct GNUNET_REVOCATION_PowP *pow;
107 struct GNUNET_REVOCATION_PowCalculationHandle *ph;
108 struct GNUNET_TIME_Relative exp;
109 char ztld[128];
110
111 id_priv.type = htonl (GNUNET_IDENTITY_TYPE_ECDSA);
112 GNUNET_CRYPTO_ecdsa_key_create (&id_priv.ecdsa_key);
113 parsehex(d_pkey,(char*)&id_priv.ecdsa_key, sizeof (id_priv.ecdsa_key), 1);
114 GNUNET_IDENTITY_key_get_public (&id_priv,
115 &id_pub);
116 GNUNET_STRINGS_data_to_string (&id_pub,
117 GNUNET_IDENTITY_key_get_length (&id_pub),
118 ztld,
119 sizeof (ztld));
120 fprintf (stdout, "Zone private key (d, big-endian scalar):\n");
121 print_bytes_ (&id_priv.ecdsa_key, sizeof(id_priv.ecdsa_key), 8, 1);
122 fprintf (stdout, "\n");
123 fprintf (stdout, "Zone identifier (ztype|zkey):\n");
124 print_bytes (&id_pub, GNUNET_IDENTITY_key_get_length (&id_pub), 8);
125 fprintf (stdout, "\n");
126 fprintf (stdout, "Encoded zone identifier (zkl = zTLD):\n");
127 fprintf (stdout, "%s\n", ztld);
128 fprintf (stdout, "\n");
129 pow = GNUNET_malloc (GNUNET_REVOCATION_MAX_PROOF_SIZE);
130 GNUNET_REVOCATION_pow_init (&id_priv,
131 pow);
132 ph = GNUNET_REVOCATION_pow_start (pow,
133 TEST_EPOCHS,
134 TEST_DIFFICULTY);
135 fprintf (stdout, "Difficulty (%d base difficulty + %d epochs): %d\n\n",
136 TEST_DIFFICULTY,
137 TEST_EPOCHS,
138 TEST_DIFFICULTY + TEST_EPOCHS);
139 uint64_t pow_passes = 0;
140 while (GNUNET_YES != GNUNET_REVOCATION_pow_round (ph))
141 {
142 pow_passes++;
143 }
144 struct GNUNET_REVOCATION_SignaturePurposePS *purp;
145 purp = REV_create_signature_message (pow);
146 fprintf (stdout, "Signed message:\n");
147 print_bytes (purp,
148 ntohl (purp->purpose.size),
149 8);
150 printf ("\n");
151 GNUNET_free (purp);
152
153 exp = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
154 TEST_EPOCHS);
155 GNUNET_assert (GNUNET_OK == GNUNET_REVOCATION_check_pow (pow,
156 TEST_DIFFICULTY,
157 exp));
158 fprintf (stdout, "Proof:\n");
159 print_bytes (pow,
160 GNUNET_REVOCATION_proof_get_size (pow),
161 8);
162 GNUNET_free (ph);
163}
164
165
166/**
167 * The main function of the test vector generation tool.
168 *
169 * @param argc number of arguments from the command line
170 * @param argv command line arguments
171 * @return 0 ok, 1 on error
172 */
173int
174main (int argc,
175 char *const *argv)
176{
177 const struct GNUNET_GETOPT_CommandLineOption options[] = {
178 GNUNET_GETOPT_OPTION_END
179 };
180
181 GNUNET_assert (GNUNET_OK ==
182 GNUNET_log_setup ("gnunet-revocation-tvg",
183 "INFO",
184 NULL));
185 if (GNUNET_OK !=
186 GNUNET_PROGRAM_run (argc, argv,
187 "gnunet-revocation-tvg",
188 "Generate test vectors for revocation",
189 options,
190 &run, NULL))
191 return 1;
192 return 0;
193}
194
195
196/* 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 4494ade83..000000000
--- a/src/revocation/gnunet-service-revocation.c
+++ /dev/null
@@ -1,1032 +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 enum GNUNET_GenericReturnValue
173verify_revoke_message (const struct RevokeMessage *rm)
174{
175 const struct GNUNET_REVOCATION_PowP *pow
176 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
177
178 if (GNUNET_YES !=
179 GNUNET_REVOCATION_check_pow (pow,
180 (unsigned int) revocation_work_required,
181 epoch_duration))
182 {
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "Proof of work invalid!\n");
185 GNUNET_break_op (0);
186 return GNUNET_NO;
187 }
188 return GNUNET_YES;
189}
190
191
192/**
193 * Handle client connecting to the service.
194 *
195 * @param cls NULL
196 * @param client the new client
197 * @param mq the message queue of @a client
198 * @return @a client
199 */
200static void *
201client_connect_cb (void *cls,
202 struct GNUNET_SERVICE_Client *client,
203 struct GNUNET_MQ_Handle *mq)
204{
205 return client;
206}
207
208
209/**
210 * Handle client connecting to the service.
211 *
212 * @param cls NULL
213 * @param client the new client
214 * @param app_cls must alias @a client
215 */
216static void
217client_disconnect_cb (void *cls,
218 struct GNUNET_SERVICE_Client *client,
219 void *app_cls)
220{
221 GNUNET_assert (client == app_cls);
222}
223
224
225/**
226 * Handle QUERY message from client.
227 *
228 * @param cls client who sent the message
229 * @param qm the message received
230 */
231static void
232handle_query_message (void *cls,
233 const struct QueryMessage *qm)
234{
235 struct GNUNET_SERVICE_Client *client = cls;
236 struct GNUNET_MQ_Envelope *env;
237 struct QueryResponseMessage *qrm;
238 struct GNUNET_HashCode hc;
239 int res;
240
241 GNUNET_CRYPTO_hash (&qm->key,
242 sizeof(struct GNUNET_IDENTITY_PublicKey),
243 &hc);
244 res = GNUNET_CONTAINER_multihashmap_contains (revocation_map,
245 &hc);
246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
247 (GNUNET_NO == res)
248 ? "Received revocation check for valid key `%s' from client\n"
249 : "Received revocation check for revoked key `%s' from client\n",
250 GNUNET_h2s (&hc));
251 env = GNUNET_MQ_msg (qrm,
252 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE);
253 qrm->is_valid = htonl ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES);
254 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
255 env);
256 GNUNET_SERVICE_client_continue (client);
257}
258
259
260/**
261 * Flood the given revocation message to all neighbours.
262 *
263 * @param cls the `struct RevokeMessage` to flood
264 * @param target a neighbour
265 * @param value our `struct PeerEntry` for the neighbour
266 * @return #GNUNET_OK (continue to iterate)
267 */
268static enum GNUNET_GenericReturnValue
269do_flood (void *cls,
270 const struct GNUNET_PeerIdentity *target,
271 void *value)
272{
273 const struct RevokeMessage *rm = cls;
274 struct PeerEntry *pe = value;
275 struct GNUNET_MQ_Envelope *e;
276 struct RevokeMessage *cp;
277
278 if (NULL == pe->mq)
279 return GNUNET_OK; /* peer connected to us via SET,
280 but we have no direct CORE
281 connection for flooding */
282 e = GNUNET_MQ_msg_extra (cp,
283 htonl (rm->pow_size),
284 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
285 *cp = *rm;
286 memcpy (&cp[1],
287 &rm[1],
288 htonl (rm->pow_size));
289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
290 "Flooding revocation to `%s'\n",
291 GNUNET_i2s (target));
292 GNUNET_MQ_send (pe->mq,
293 e);
294 return GNUNET_OK;
295}
296
297
298/**
299 * Publicize revocation message. Stores the message locally in the
300 * database and passes it to all connected neighbours (and adds it to
301 * the set for future connections).
302 *
303 * @param rm message to publicize
304 * @return #GNUNET_OK on success, #GNUNET_NO if we encountered an error,
305 * #GNUNET_SYSERR if the message was malformed
306 */
307static enum GNUNET_GenericReturnValue
308publicize_rm (const struct RevokeMessage *rm)
309{
310 struct RevokeMessage *cp;
311 struct GNUNET_HashCode hc;
312 struct GNUNET_SETU_Element e;
313 ssize_t pklen;
314 const struct GNUNET_REVOCATION_PowP *pow
315 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
316 const struct GNUNET_IDENTITY_PublicKey *pk
317 = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
318
319 pklen = GNUNET_IDENTITY_key_get_length (pk);
320 if (0 > pklen)
321 {
322 GNUNET_break_op (0);
323 return GNUNET_SYSERR;
324 }
325 GNUNET_CRYPTO_hash (pk,
326 pklen,
327 &hc);
328 if (GNUNET_YES ==
329 GNUNET_CONTAINER_multihashmap_contains (revocation_map,
330 &hc))
331 {
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
333 "Duplicate revocation received from peer. Ignored.\n");
334 return GNUNET_OK;
335 }
336 if (GNUNET_OK !=
337 verify_revoke_message (rm))
338 {
339 GNUNET_break_op (0);
340 return GNUNET_SYSERR;
341 }
342 /* write to disk */
343 if (sizeof(struct RevokeMessage) !=
344 GNUNET_DISK_file_write (revocation_db,
345 rm,
346 sizeof(struct RevokeMessage)))
347 {
348 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
349 "write");
350 return GNUNET_NO;
351 }
352 if (GNUNET_OK !=
353 GNUNET_DISK_file_sync (revocation_db))
354 {
355 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
356 "sync");
357 return GNUNET_NO;
358 }
359 /* keep copy in memory */
360 cp = (struct RevokeMessage *) GNUNET_copy_message (&rm->header);
361 GNUNET_break (GNUNET_OK ==
362 GNUNET_CONTAINER_multihashmap_put (revocation_map,
363 &hc,
364 cp,
365 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
366 /* add to set for future connections */
367 e.size = htons (rm->header.size);
368 e.element_type = GNUNET_BLOCK_TYPE_REVOCATION;
369 e.data = rm;
370 if (GNUNET_OK !=
371 GNUNET_SETU_add_element (revocation_set,
372 &e,
373 NULL,
374 NULL))
375 {
376 GNUNET_break (0);
377 return GNUNET_OK;
378 }
379 else
380 {
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
382 "Added revocation info to SET\n");
383 }
384 /* flood to neighbours */
385 GNUNET_CONTAINER_multipeermap_iterate (peers,
386 &do_flood,
387 cp);
388 return GNUNET_OK;
389}
390
391
392static int
393check_revoke_message (void *cls,
394 const struct RevokeMessage *rm)
395{
396 uint16_t size;
397
398 size = ntohs (rm->header.size);
399 if (size <= sizeof(struct RevokeMessage) ||
400 (size > UINT16_MAX))
401 {
402 GNUNET_break (0);
403 return GNUNET_SYSERR;
404 }
405 return GNUNET_OK;
406
407}
408
409
410/**
411 * Handle REVOKE message from client.
412 *
413 * @param cls client who sent the message
414 * @param rm the message received
415 */
416static void
417handle_revoke_message (void *cls,
418 const struct RevokeMessage *rm)
419{
420 struct GNUNET_SERVICE_Client *client = cls;
421 struct GNUNET_MQ_Envelope *env;
422 struct RevocationResponseMessage *rrm;
423 int ret;
424
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
426 "Received REVOKE message from client\n");
427 if (GNUNET_SYSERR == (ret = publicize_rm (rm)))
428 {
429 GNUNET_break_op (0);
430 GNUNET_SERVICE_client_drop (client);
431 return;
432 }
433 env = GNUNET_MQ_msg (rrm,
434 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE);
435 rrm->is_valid = htonl ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES);
436 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
437 env);
438 GNUNET_SERVICE_client_continue (client);
439}
440
441
442static int
443check_p2p_revoke (void *cls,
444 const struct RevokeMessage *rm)
445{
446 uint16_t size;
447
448 size = ntohs (rm->header.size);
449 if (size <= sizeof(struct RevokeMessage))
450 {
451 GNUNET_break (0);
452 return GNUNET_SYSERR;
453 }
454 return GNUNET_OK;
455
456}
457
458
459/**
460 * Core handler for flooded revocation messages.
461 *
462 * @param cls closure unused
463 * @param rm revocation message
464 */
465static void
466handle_p2p_revoke (void *cls,
467 const struct RevokeMessage *rm)
468{
469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
470 "Received REVOKE message\n");
471 GNUNET_break_op (GNUNET_SYSERR !=
472 publicize_rm (rm));
473}
474
475
476/**
477 * Callback for set operation results. Called for each element in the
478 * result set. Each element contains a revocation, which we should
479 * validate and then add to our revocation list (and set).
480 *
481 * @param cls closure
482 * @param element a result element, only valid if status is #GNUNET_SETU_STATUS_OK
483 * @param current_size current set size
484 * @param status see `enum GNUNET_SETU_Status`
485 */
486static void
487add_revocation (void *cls,
488 const struct GNUNET_SETU_Element *element,
489 uint64_t current_size,
490 enum GNUNET_SETU_Status status)
491{
492 struct PeerEntry *peer_entry = cls;
493 const struct RevokeMessage *rm;
494
495 switch (status)
496 {
497 case GNUNET_SETU_STATUS_ADD_LOCAL:
498 if (element->size != sizeof(struct RevokeMessage))
499 {
500 GNUNET_break_op (0);
501 return;
502 }
503 if (GNUNET_BLOCK_TYPE_REVOCATION != element->element_type)
504 {
505 GNUNET_STATISTICS_update (stats,
506 gettext_noop (
507 "# unsupported revocations received via set union"),
508 1,
509 GNUNET_NO);
510 return;
511 }
512 rm = element->data;
513 (void) handle_p2p_revoke (NULL,
514 rm);
515 GNUNET_STATISTICS_update (stats,
516 gettext_noop (
517 "# revocation messages received via set union"),
518 1, GNUNET_NO);
519 break;
520 case GNUNET_SETU_STATUS_FAILURE:
521 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
522 _ ("Error computing revocation set union with %s\n"),
523 GNUNET_i2s (&peer_entry->id));
524 peer_entry->so = NULL;
525 GNUNET_STATISTICS_update (stats,
526 gettext_noop ("# revocation set unions failed"),
527 1,
528 GNUNET_NO);
529 break;
530 case GNUNET_SETU_STATUS_DONE:
531 peer_entry->so = NULL;
532 GNUNET_STATISTICS_update (stats,
533 gettext_noop (
534 "# revocation set unions completed"),
535 1,
536 GNUNET_NO);
537 break;
538 default:
539 GNUNET_break (0);
540 break;
541 }
542}
543
544
545/**
546 * The timeout for performing the set union has expired,
547 * run the set operation on the revocation certificates.
548 *
549 * @param cls NULL
550 */
551static void
552transmit_task_cb (void *cls)
553{
554 struct PeerEntry *peer_entry = cls;
555
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557 "Starting set exchange with peer `%s'\n",
558 GNUNET_i2s (&peer_entry->id));
559 peer_entry->transmit_task = NULL;
560 GNUNET_assert (NULL == peer_entry->so);
561 peer_entry->so = GNUNET_SETU_prepare (&peer_entry->id,
562 &revocation_set_union_app_id,
563 NULL,
564 (struct GNUNET_SETU_Option[]) { { 0 } },
565 &add_revocation,
566 peer_entry);
567 if (GNUNET_OK !=
568 GNUNET_SETU_commit (peer_entry->so,
569 revocation_set))
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
572 _ ("SET service crashed, terminating revocation service\n"));
573 GNUNET_SCHEDULER_shutdown ();
574 return;
575 }
576}
577
578
579/**
580 * Method called whenever a peer connects. Sets up the PeerEntry and
581 * schedules the initial revocation set exchange with this peer.
582 *
583 * @param cls closure
584 * @param peer peer identity this notification is about
585 */
586static void *
587handle_core_connect (void *cls,
588 const struct GNUNET_PeerIdentity *peer,
589 struct GNUNET_MQ_Handle *mq)
590{
591 struct PeerEntry *peer_entry;
592 struct GNUNET_HashCode my_hash;
593 struct GNUNET_HashCode peer_hash;
594
595 if (0 == GNUNET_memcmp (peer,
596 &my_identity))
597 {
598 return NULL;
599 }
600
601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
602 "Peer `%s' connected to us\n",
603 GNUNET_i2s (peer));
604 GNUNET_STATISTICS_update (stats,
605 "# peers connected",
606 1,
607 GNUNET_NO);
608 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
609 peer);
610 if (NULL != peer_entry)
611 {
612 /* This can happen if "core"'s notification is a tad late
613 and CADET+SET were faster and already produced a
614 #handle_revocation_union_request() for us to deal
615 with. This should be rare, but isn't impossible. */
616 peer_entry->mq = mq;
617 return peer_entry;
618 }
619 peer_entry = new_peer_entry (peer);
620 peer_entry->mq = mq;
621 GNUNET_CRYPTO_hash (&my_identity,
622 sizeof(my_identity),
623 &my_hash);
624 GNUNET_CRYPTO_hash (peer,
625 sizeof(*peer),
626 &peer_hash);
627 if (0 < GNUNET_CRYPTO_hash_cmp (&my_hash,
628 &peer_hash))
629 {
630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
631 "Starting SET operation with peer `%s'\n",
632 GNUNET_i2s (peer));
633 peer_entry->transmit_task =
634 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
635 &transmit_task_cb,
636 peer_entry);
637 }
638 return peer_entry;
639}
640
641
642/**
643 * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels
644 * any pending transmission requests to that peer.
645 *
646 * @param cls closure
647 * @param peer peer identity this notification is about
648 * @param internal_cls our `struct PeerEntry` for this peer
649 */
650static void
651handle_core_disconnect (void *cls,
652 const struct GNUNET_PeerIdentity *peer,
653 void *internal_cls)
654{
655 struct PeerEntry *peer_entry = internal_cls;
656
657 if (0 == GNUNET_memcmp (peer,
658 &my_identity))
659 return;
660 GNUNET_assert (NULL != peer_entry);
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Peer `%s' disconnected from us\n",
663 GNUNET_i2s (peer));
664 GNUNET_assert (GNUNET_YES ==
665 GNUNET_CONTAINER_multipeermap_remove (peers,
666 peer,
667 peer_entry));
668 if (NULL != peer_entry->transmit_task)
669 {
670 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
671 peer_entry->transmit_task = NULL;
672 }
673 if (NULL != peer_entry->so)
674 {
675 GNUNET_SETU_operation_cancel (peer_entry->so);
676 peer_entry->so = NULL;
677 }
678 GNUNET_free (peer_entry);
679 GNUNET_STATISTICS_update (stats,
680 "# peers connected",
681 -1,
682 GNUNET_NO);
683}
684
685
686/**
687 * Free all values in a hash map.
688 *
689 * @param cls NULL
690 * @param key the key
691 * @param value value to free
692 * @return #GNUNET_OK (continue to iterate)
693 */
694static int
695free_entry (void *cls,
696 const struct GNUNET_HashCode *key,
697 void *value)
698{
699 GNUNET_free (value);
700 return GNUNET_OK;
701}
702
703
704/**
705 * Task run during shutdown.
706 *
707 * @param cls unused
708 */
709static void
710shutdown_task (void *cls)
711{
712 if (NULL != revocation_set)
713 {
714 GNUNET_SETU_destroy (revocation_set);
715 revocation_set = NULL;
716 }
717 if (NULL != revocation_union_listen_handle)
718 {
719 GNUNET_SETU_listen_cancel (revocation_union_listen_handle);
720 revocation_union_listen_handle = NULL;
721 }
722 if (NULL != core_api)
723 {
724 GNUNET_CORE_disconnect (core_api);
725 core_api = NULL;
726 }
727 if (NULL != stats)
728 {
729 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
730 stats = NULL;
731 }
732 if (NULL != peers)
733 {
734 GNUNET_CONTAINER_multipeermap_destroy (peers);
735 peers = NULL;
736 }
737 if (NULL != revocation_db)
738 {
739 GNUNET_DISK_file_close (revocation_db);
740 revocation_db = NULL;
741 }
742 GNUNET_CONTAINER_multihashmap_iterate (revocation_map,
743 &free_entry,
744 NULL);
745 GNUNET_CONTAINER_multihashmap_destroy (revocation_map);
746}
747
748
749/**
750 * Called on core init/fail.
751 *
752 * @param cls service closure
753 * @param identity the public identity of this peer
754 */
755static void
756core_init (void *cls,
757 const struct GNUNET_PeerIdentity *identity)
758{
759 if (NULL == identity)
760 {
761 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
762 "Connection to core FAILED!\n");
763 GNUNET_SCHEDULER_shutdown ();
764 return;
765 }
766 my_identity = *identity;
767}
768
769
770/**
771 * Called when another peer wants to do a set operation with the
772 * local peer. If a listen error occurs, the 'request' is NULL.
773 *
774 * @param cls closure
775 * @param other_peer the other peer
776 * @param context_msg message with application specific information from
777 * the other peer
778 * @param request request from the other peer (never NULL), use GNUNET_SETU_accept()
779 * to accept it, otherwise the request will be refused
780 * Note that we can't just return value from the listen callback,
781 * as it is also necessary to specify the set we want to do the
782 * operation with, which sometimes can be derived from the context
783 * message. It's necessary to specify the timeout.
784 */
785static void
786handle_revocation_union_request (void *cls,
787 const struct GNUNET_PeerIdentity *other_peer,
788 const struct GNUNET_MessageHeader *context_msg,
789 struct GNUNET_SETU_Request *request)
790{
791 struct PeerEntry *peer_entry;
792
793 if (NULL == request)
794 {
795 GNUNET_break (0);
796 return;
797 }
798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
799 "Received set exchange request from peer `%s'\n",
800 GNUNET_i2s (other_peer));
801 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
802 other_peer);
803 if (NULL == peer_entry)
804 {
805 peer_entry = new_peer_entry (other_peer);
806 }
807 if (NULL != peer_entry->so)
808 {
809 GNUNET_break_op (0);
810 return;
811 }
812 peer_entry->so = GNUNET_SETU_accept (request,
813 (struct GNUNET_SETU_Option[]) { { 0 } },
814 &add_revocation,
815 peer_entry);
816 if (GNUNET_OK !=
817 GNUNET_SETU_commit (peer_entry->so,
818 revocation_set))
819 {
820 GNUNET_break (0);
821 GNUNET_SCHEDULER_shutdown ();
822 return;
823 }
824}
825
826
827/**
828 * Handle network size estimate clients.
829 *
830 * @param cls closure
831 * @param server the initialized server
832 * @param c configuration to use
833 */
834static void
835run (void *cls,
836 const struct GNUNET_CONFIGURATION_Handle *c,
837 struct GNUNET_SERVICE_Handle *service)
838{
839 struct GNUNET_MQ_MessageHandler core_handlers[] = {
840 GNUNET_MQ_hd_var_size (p2p_revoke,
841 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
842 struct RevokeMessage,
843 NULL),
844 GNUNET_MQ_handler_end ()
845 };
846 char *fn;
847 uint64_t left;
848 struct RevokeMessage *rm;
849 struct GNUNET_HashCode hc;
850 const struct GNUNET_IDENTITY_PublicKey *pk;
851
852 GNUNET_CRYPTO_hash ("revocation-set-union-application-id",
853 strlen ("revocation-set-union-application-id"),
854 &revocation_set_union_app_id);
855 if (GNUNET_OK !=
856 GNUNET_CONFIGURATION_get_value_filename (c,
857 "REVOCATION",
858 "DATABASE",
859 &fn))
860 {
861 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
862 "REVOCATION",
863 "DATABASE");
864 GNUNET_SCHEDULER_shutdown ();
865 return;
866 }
867 cfg = c;
868 revocation_map = GNUNET_CONTAINER_multihashmap_create (16,
869 GNUNET_NO);
870 if (GNUNET_OK !=
871 GNUNET_CONFIGURATION_get_value_number (cfg,
872 "REVOCATION",
873 "WORKBITS",
874 &revocation_work_required))
875 {
876 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
877 "REVOCATION",
878 "WORKBITS");
879 GNUNET_SCHEDULER_shutdown ();
880 GNUNET_free (fn);
881 return;
882 }
883 if (revocation_work_required >= sizeof(struct GNUNET_HashCode) * 8)
884 {
885 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
886 "REVOCATION",
887 "WORKBITS",
888 _ ("Value is too large.\n"));
889 GNUNET_SCHEDULER_shutdown ();
890 GNUNET_free (fn);
891 return;
892 }
893 if (GNUNET_OK !=
894 GNUNET_CONFIGURATION_get_value_time (cfg,
895 "REVOCATION",
896 "EPOCH_DURATION",
897 &epoch_duration))
898 {
899 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
900 "REVOCATION",
901 "EPOCH_DURATION");
902 GNUNET_SCHEDULER_shutdown ();
903 GNUNET_free (fn);
904 return;
905 }
906
907 revocation_set = GNUNET_SETU_create (cfg);
908 revocation_union_listen_handle
909 = GNUNET_SETU_listen (cfg,
910 &revocation_set_union_app_id,
911 &handle_revocation_union_request,
912 NULL);
913 revocation_db = GNUNET_DISK_file_open (fn,
914 GNUNET_DISK_OPEN_READWRITE
915 | GNUNET_DISK_OPEN_CREATE,
916 GNUNET_DISK_PERM_USER_READ
917 | GNUNET_DISK_PERM_USER_WRITE
918 | GNUNET_DISK_PERM_GROUP_READ
919 | GNUNET_DISK_PERM_OTHER_READ);
920 if (NULL == revocation_db)
921 {
922 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
923 "REVOCATION",
924 "DATABASE",
925 _ ("Could not open revocation database file!"));
926 GNUNET_SCHEDULER_shutdown ();
927 GNUNET_free (fn);
928 return;
929 }
930 if (GNUNET_OK !=
931 GNUNET_DISK_file_size (fn, &left, GNUNET_YES, GNUNET_YES))
932 left = 0;
933 while (left > sizeof(struct RevokeMessage))
934 {
935 rm = GNUNET_new (struct RevokeMessage);
936 if (sizeof(struct RevokeMessage) !=
937 GNUNET_DISK_file_read (revocation_db,
938 rm,
939 sizeof(struct RevokeMessage)))
940 {
941 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
942 "read",
943 fn);
944 GNUNET_free (rm);
945 GNUNET_SCHEDULER_shutdown ();
946 GNUNET_free (fn);
947 return;
948 }
949 struct GNUNET_REVOCATION_PowP *pow = (struct
950 GNUNET_REVOCATION_PowP *) &rm[1];
951 ssize_t ksize;
952 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
953 ksize = GNUNET_IDENTITY_key_get_length (pk);
954 if (0 > ksize)
955 {
956 GNUNET_break_op (0);
957 GNUNET_free (rm);
958 GNUNET_free (fn);
959 return;
960 }
961 GNUNET_CRYPTO_hash (pk,
962 ksize,
963 &hc);
964 GNUNET_break (GNUNET_OK ==
965 GNUNET_CONTAINER_multihashmap_put (revocation_map,
966 &hc,
967 rm,
968 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
969 }
970 GNUNET_free (fn);
971
972 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
973 NULL);
974 peers = GNUNET_CONTAINER_multipeermap_create (128,
975 GNUNET_YES);
976 /* Connect to core service and register core handlers */
977 core_api = GNUNET_CORE_connect (cfg, /* Main configuration */
978 NULL, /* Closure passed to functions */
979 &core_init, /* Call core_init once connected */
980 &handle_core_connect, /* Handle connects */
981 &handle_core_disconnect, /* Handle disconnects */
982 core_handlers); /* Register these handlers */
983 if (NULL == core_api)
984 {
985 GNUNET_SCHEDULER_shutdown ();
986 return;
987 }
988 stats = GNUNET_STATISTICS_create ("revocation",
989 cfg);
990}
991
992
993/**
994 * Define "main" method using service macro.
995 */
996GNUNET_SERVICE_MAIN
997 ("revocation",
998 GNUNET_SERVICE_OPTION_NONE,
999 &run,
1000 &client_connect_cb,
1001 &client_disconnect_cb,
1002 NULL,
1003 GNUNET_MQ_hd_fixed_size (query_message,
1004 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY,
1005 struct QueryMessage,
1006 NULL),
1007 GNUNET_MQ_hd_var_size (revoke_message,
1008 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
1009 struct RevokeMessage,
1010 NULL),
1011 GNUNET_MQ_handler_end ());
1012
1013
1014#if defined(__linux__) && defined(__GLIBC__)
1015#include <malloc.h>
1016
1017/**
1018 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1019 */
1020void __attribute__ ((constructor))
1021GNUNET_REVOCATION_memory_init ()
1022{
1023 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1024 mallopt (M_TOP_PAD, 1 * 1024);
1025 malloc_trim (0);
1026}
1027
1028
1029#endif
1030
1031
1032/* 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 12ec555e4..000000000
--- a/src/revocation/plugin_block_revocation.c
+++ /dev/null
@@ -1,297 +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 * Context used inside the plugin.
38 */
39struct InternalContext
40{
41 unsigned int matching_bits;
42 struct GNUNET_TIME_Relative epoch_duration;
43};
44
45
46/**
47 * Function called to validate a query.
48 *
49 * @param cls closure
50 * @param ctx block context
51 * @param type block type
52 * @param query original query (hash)
53 * @param xquery extrended query data (can be NULL, depending on type)
54 * @param xquery_size number of bytes in @a xquery
55 * @return #GNUNET_OK if the query is fine, #GNUNET_NO if not
56 */
57static enum GNUNET_GenericReturnValue
58block_plugin_revocation_check_query (void *cls,
59 enum GNUNET_BLOCK_Type type,
60 const struct GNUNET_HashCode *query,
61 const void *xquery,
62 size_t xquery_size)
63{
64 (void) cls;
65 (void) query;
66 (void) xquery;
67 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
68 {
69 GNUNET_break (0);
70 return GNUNET_SYSERR;
71 }
72 if (0 != xquery_size)
73 return GNUNET_NO;
74 return GNUNET_OK;
75}
76
77
78/**
79 * Function called to validate a block for storage.
80 *
81 * @param cls closure
82 * @param type block type
83 * @param block block data to validate
84 * @param block_size number of bytes in @a block
85 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
86 */
87static enum GNUNET_GenericReturnValue
88block_plugin_revocation_check_block (void *cls,
89 enum GNUNET_BLOCK_Type type,
90 const void *block,
91 size_t block_size)
92{
93 struct InternalContext *ic = cls;
94 const struct RevokeMessage *rm = block;
95 const struct GNUNET_REVOCATION_PowP *pow
96 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
97 struct GNUNET_IDENTITY_PublicKey pk;
98 ssize_t pklen;
99 size_t left;
100
101 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
102 {
103 GNUNET_break (0);
104 return GNUNET_SYSERR;
105 }
106 if (block_size < sizeof(*rm) + sizeof(*pow))
107 {
108 GNUNET_break_op (0);
109 return GNUNET_NO;
110 }
111 if (block_size != sizeof(*rm) + ntohl (rm->pow_size))
112 {
113 GNUNET_break_op (0);
114 return GNUNET_NO;
115 }
116 left = block_size - sizeof (*rm) - sizeof (*pow);
117 pklen = GNUNET_IDENTITY_read_key_from_buffer (&pk,
118 &pow[1],
119 left);
120 if (0 > pklen)
121 {
122 GNUNET_break_op (0);
123 return GNUNET_NO;
124 }
125 if (GNUNET_YES !=
126 GNUNET_REVOCATION_check_pow (pow,
127 ic->matching_bits,
128 ic->epoch_duration))
129 {
130 GNUNET_break_op (0);
131 return GNUNET_NO;
132 }
133 return GNUNET_OK;
134}
135
136
137/**
138 * Function called to validate a reply to a request. Note that it is assumed
139 * that the reply has already been matched to the key (and signatures checked)
140 * as it would be done with the GetKeyFunction and the
141 * BlockEvaluationFunction.
142 *
143 * @param cls closure
144 * @param type block type
145 * @param group which block group to use for evaluation
146 * @param query original query (hash)
147 * @param xquery extrended query data (can be NULL, depending on type)
148 * @param xquery_size number of bytes in @a xquery
149 * @param reply_block response to validate
150 * @param reply_block_size number of bytes in @a reply_block
151 * @return characterization of result
152 */
153static enum GNUNET_BLOCK_ReplyEvaluationResult
154block_plugin_revocation_check_reply (
155 void *cls,
156 enum GNUNET_BLOCK_Type type,
157 struct GNUNET_BLOCK_Group *group,
158 const struct GNUNET_HashCode *query,
159 const void *xquery,
160 size_t xquery_size,
161 const void *reply_block,
162 size_t reply_block_size)
163{
164 (void) cls;
165 (void) group;
166 (void) query;
167 (void) xquery;
168 (void) xquery_size;
169 (void) reply_block;
170 (void) reply_block_size;
171 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
172 {
173 GNUNET_break (0);
174 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
175 }
176 return GNUNET_BLOCK_REPLY_OK_LAST;
177}
178
179
180/**
181 * Function called to obtain the key for a block.
182 *
183 * @param cls closure
184 * @param type block type
185 * @param block block to get the key for
186 * @param block_size number of bytes in block
187 * @param key set to the key (query) for the given block
188 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
189 * (or if extracting a key from a block of this type does not work)
190 */
191static enum GNUNET_GenericReturnValue
192block_plugin_revocation_get_key (void *cls,
193 enum GNUNET_BLOCK_Type type,
194 const void *block,
195 size_t block_size,
196 struct GNUNET_HashCode *key)
197{
198 const struct RevokeMessage *rm = block;
199 const struct GNUNET_REVOCATION_PowP *pow
200 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
201 struct GNUNET_IDENTITY_PublicKey pk;
202 ssize_t pklen;
203 size_t left;
204
205 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
206 {
207 GNUNET_break (0);
208 return GNUNET_SYSERR;
209 }
210 if (block_size < sizeof(*rm) + sizeof(*pow))
211 {
212 GNUNET_break_op (0);
213 return GNUNET_NO;
214 }
215 if (block_size != sizeof(*rm) + ntohl (rm->pow_size))
216 {
217 GNUNET_break_op (0);
218 return GNUNET_NO;
219 }
220 left = block_size - sizeof (*rm) - sizeof (*pow);
221 pklen = GNUNET_IDENTITY_read_key_from_buffer (&pk,
222 &pow[1],
223 left);
224 if (0 > pklen)
225 {
226 GNUNET_break_op (0);
227 return GNUNET_NO;
228 }
229 GNUNET_CRYPTO_hash (&pow[1],
230 pklen,
231 key);
232 return GNUNET_OK;
233}
234
235
236/**
237 * Entry point for the plugin.
238 *
239 * @param cls the configuration to use
240 */
241void *
242libgnunet_plugin_block_revocation_init (void *cls)
243{
244 static const enum GNUNET_BLOCK_Type types[] = {
245 GNUNET_BLOCK_TYPE_REVOCATION,
246 GNUNET_BLOCK_TYPE_ANY /* end of list */
247 };
248 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
249 struct GNUNET_BLOCK_PluginFunctions *api;
250 struct InternalContext *ic;
251 unsigned long long matching_bits;
252 struct GNUNET_TIME_Relative epoch_duration;
253
254 if (GNUNET_OK !=
255 GNUNET_CONFIGURATION_get_value_number (cfg,
256 "REVOCATION",
257 "WORKBITS",
258 &matching_bits))
259 return NULL;
260 if (GNUNET_OK !=
261 GNUNET_CONFIGURATION_get_value_time (cfg,
262 "REVOCATION",
263 "EPOCH_DURATION",
264 &epoch_duration))
265 return NULL;
266
267 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
268 api->get_key = &block_plugin_revocation_get_key;
269 api->check_query = &block_plugin_revocation_check_query;
270 api->check_block = &block_plugin_revocation_check_block;
271 api->check_reply = &block_plugin_revocation_check_reply;
272 api->create_group = NULL;
273 api->types = types;
274 ic = GNUNET_new (struct InternalContext);
275 ic->matching_bits = (unsigned int) matching_bits;
276 ic->epoch_duration = epoch_duration;
277 api->cls = ic;
278 return api;
279}
280
281
282/**
283 * Exit point from the plugin.
284 */
285void *
286libgnunet_plugin_block_revocation_done (void *cls)
287{
288 struct GNUNET_BLOCK_PluginFunctions *api = cls;
289 struct InternalContext *ic = api->cls;
290
291 GNUNET_free (ic);
292 GNUNET_free (api);
293 return NULL;
294}
295
296
297/* 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 490abf180..000000000
--- a/src/revocation/revocation.h
+++ /dev/null
@@ -1,125 +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 * Create the revocation metadata to sign for a revocation message
118 *
119 * @param pow the PoW to sign
120 * @return the signature purpose
121 */
122struct GNUNET_REVOCATION_SignaturePurposePS *
123REV_create_signature_message (const struct GNUNET_REVOCATION_PowP *pow);
124
125#endif
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
deleted file mode 100644
index b8c458e4f..000000000
--- a/src/revocation/revocation_api.c
+++ /dev/null
@@ -1,773 +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 zeros.
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 * Calculate the average zeros in the pows.
393 *
394 * @param ph the PowHandle
395 * @return the average number of zeros.
396 */
397static unsigned int
398calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph)
399{
400 double sum = 0.0;
401 for (unsigned int j = 0; j<POW_COUNT; j++)
402 sum += ph->best[j].bits;
403 double avg = sum / POW_COUNT;
404 return avg;
405}
406
407struct GNUNET_REVOCATION_SignaturePurposePS *
408REV_create_signature_message (const struct GNUNET_REVOCATION_PowP *pow)
409{
410 struct GNUNET_REVOCATION_SignaturePurposePS *spurp;
411 const struct GNUNET_IDENTITY_PublicKey *pk;
412 size_t ksize;
413
414 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
415 ksize = GNUNET_IDENTITY_key_get_length (pk);
416 spurp = GNUNET_malloc (sizeof (*spurp) + ksize);
417 spurp->timestamp = pow->timestamp;
418 spurp->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION);
419 spurp->purpose.size = htonl (sizeof(*spurp) + ksize);
420 GNUNET_IDENTITY_write_key_to_buffer (pk,
421 (char*) &spurp[1],
422 ksize);
423 return spurp;
424}
425
426enum GNUNET_GenericReturnValue
427check_signature_identity (const struct GNUNET_REVOCATION_PowP *pow,
428 const struct GNUNET_IDENTITY_PublicKey *key)
429{
430 struct GNUNET_REVOCATION_SignaturePurposePS *spurp;
431 unsigned char *sig;
432 size_t ksize;
433
434 ksize = GNUNET_IDENTITY_key_get_length (key);
435 spurp = REV_create_signature_message (pow);
436 sig = ((unsigned char*) &pow[1] + ksize);
437 if (GNUNET_OK !=
438 GNUNET_IDENTITY_signature_verify_raw_ (GNUNET_SIGNATURE_PURPOSE_REVOCATION,
439 &spurp->purpose,
440 sig,
441 key))
442 {
443 return GNUNET_SYSERR;
444 }
445 return GNUNET_OK;
446}
447
448
449enum GNUNET_GenericReturnValue
450check_signature (const struct GNUNET_REVOCATION_PowP *pow)
451{
452 const struct GNUNET_IDENTITY_PublicKey *pk;
453
454 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
455 return check_signature_identity (pow, pk);
456}
457
458
459/**
460 * Check if the given proof-of-work is valid.
461 *
462 * @param pow proof of work
463 * @param difficulty how many bits must match (configuration) LSD0001: D
464 * @param epoch_duration length of single epoch in configuration
465 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
466 */
467enum GNUNET_GenericReturnValue
468GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
469 unsigned int difficulty,
470 struct GNUNET_TIME_Relative epoch_duration)
471{
472 char buf[sizeof(struct GNUNET_IDENTITY_PublicKey)
473 + sizeof (struct GNUNET_TIME_AbsoluteNBO)
474 + sizeof (uint64_t)] GNUNET_ALIGN;
475 struct GNUNET_HashCode result;
476 struct GNUNET_TIME_Absolute ts;
477 struct GNUNET_TIME_Absolute exp;
478 struct GNUNET_TIME_Relative ttl;
479 struct GNUNET_TIME_Relative buffer;
480 /* LSD0001: D' */
481 unsigned int score = 0;
482 unsigned int tmp_score = 0;
483 unsigned int epochs;
484 uint64_t pow_val;
485 ssize_t pklen;
486 const struct GNUNET_IDENTITY_PublicKey *pk;
487
488 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
489
490 /**
491 * Check if signature valid
492 */
493 if (GNUNET_OK != check_signature (pow))
494 {
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
496 "Proof of work signature invalid!\n");
497 return GNUNET_SYSERR;
498 }
499
500 /**
501 * First, check if PoW set is strictly monotically increasing
502 */
503 for (unsigned int i = 0; i < POW_COUNT - 1; i++)
504 {
505 if (GNUNET_ntohll (pow->pow[i]) >= GNUNET_ntohll (pow->pow[i + 1]))
506 return GNUNET_NO;
507 }
508 GNUNET_memcpy (&buf[sizeof(uint64_t)],
509 &pow->timestamp,
510 sizeof (uint64_t));
511 pklen = GNUNET_IDENTITY_key_get_length (pk);
512 if (0 > pklen)
513 {
514 GNUNET_break (0);
515 return GNUNET_NO;
516 }
517 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
518 pk,
519 pklen);
520 for (unsigned int i = 0; i < POW_COUNT; i++)
521 {
522 pow_val = GNUNET_ntohll (pow->pow[i]);
523 GNUNET_memcpy (buf, &pow->pow[i], sizeof(uint64_t));
524 GNUNET_CRYPTO_pow_hash (&salt,
525 buf,
526 sizeof(buf),
527 &result);
528 tmp_score = GNUNET_CRYPTO_hash_count_leading_zeros (&result);
529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
530 "Score %u with %" PRIu64 " (#%u)\n",
531 tmp_score, pow_val, i);
532
533 score += tmp_score;
534
535 }
536 score = score / POW_COUNT;
537 if (score < difficulty)
538 return GNUNET_NO;
539 /* LSD0001: (D'-D+1) */
540 epochs = score - difficulty + 1;
541
542 /**
543 * Check expiration
544 */
545 ts = GNUNET_TIME_absolute_ntoh (pow->timestamp);
546 ttl = GNUNET_TIME_relative_multiply (epoch_duration,
547 epochs);
548 /**
549 * Extend by 10% for unsynchronized clocks
550 */
551 buffer = GNUNET_TIME_relative_divide (epoch_duration,
552 10);
553 exp = GNUNET_TIME_absolute_add (ts, ttl);
554 exp = GNUNET_TIME_absolute_add (exp,
555 buffer);
556
557 if (0 != GNUNET_TIME_absolute_get_remaining (ts).rel_value_us)
558 return GNUNET_NO; /* Not yet valid. */
559 /* Revert to actual start time */
560 ts = GNUNET_TIME_absolute_add (ts,
561 buffer);
562
563 if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
564 return GNUNET_NO; /* expired */
565 return GNUNET_YES;
566}
567
568
569enum GNUNET_GenericReturnValue
570sign_pow_identity (const struct GNUNET_IDENTITY_PrivateKey *key,
571 struct GNUNET_REVOCATION_PowP *pow)
572{
573 struct GNUNET_TIME_Absolute ts = GNUNET_TIME_absolute_get ();
574 struct GNUNET_REVOCATION_SignaturePurposePS *rp;
575 const struct GNUNET_IDENTITY_PublicKey *pk;
576 size_t ksize;
577 char *sig;
578
579 /**
580 * Predate the validity period to prevent rejections due to
581 * unsynchronized clocks
582 */
583 ts = GNUNET_TIME_absolute_subtract (ts,
584 GNUNET_TIME_UNIT_WEEKS);
585 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
586 ksize = GNUNET_IDENTITY_key_get_length (pk);
587 pow->timestamp = GNUNET_TIME_absolute_hton (ts);
588 rp = REV_create_signature_message (pow);
589 sig = ((char*) &pow[1]) + ksize;
590 int result = GNUNET_IDENTITY_sign_raw_ (key,
591 &rp->purpose,
592 (void*) sig);
593 if (result == GNUNET_SYSERR)
594 return GNUNET_NO;
595 else
596 return result;
597}
598
599
600enum GNUNET_GenericReturnValue
601sign_pow (const struct GNUNET_IDENTITY_PrivateKey *key,
602 struct GNUNET_REVOCATION_PowP *pow)
603{
604 struct GNUNET_IDENTITY_PublicKey *pk;
605
606 pk = (struct GNUNET_IDENTITY_PublicKey *) &pow[1];
607 GNUNET_IDENTITY_key_get_public (key, pk);
608 return sign_pow_identity (key, pow);
609}
610
611
612/**
613 * Initializes a fresh PoW computation.
614 *
615 * @param key the key to calculate the PoW for.
616 * @param[out] pow starting point for PoW calculation (not yet valid)
617 */
618void
619GNUNET_REVOCATION_pow_init (const struct GNUNET_IDENTITY_PrivateKey *key,
620 struct GNUNET_REVOCATION_PowP *pow)
621{
622 GNUNET_assert (GNUNET_OK == sign_pow (key, pow));
623}
624
625
626/**
627 * Starts a proof-of-work calculation given the pow object as well as
628 * target epochs and difficulty.
629 *
630 * @param pow the PoW to based calculations on.
631 * @param epochs the number of epochs for which the PoW must be valid.
632 * @param difficulty the base difficulty of the PoW.
633 * @return a handle for use in PoW rounds
634 */
635struct GNUNET_REVOCATION_PowCalculationHandle*
636GNUNET_REVOCATION_pow_start (struct GNUNET_REVOCATION_PowP *pow,
637 int epochs,
638 unsigned int difficulty)
639{
640 struct GNUNET_REVOCATION_PowCalculationHandle *pc;
641 struct GNUNET_TIME_Relative ttl;
642
643
644 pc = GNUNET_new (struct GNUNET_REVOCATION_PowCalculationHandle);
645 pc->pow = pow;
646 ttl = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
647 epochs);
648 pc->pow->ttl = GNUNET_TIME_relative_hton (ttl);
649 pc->current_pow = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
650 UINT64_MAX);
651 pc->difficulty = difficulty;
652 pc->epochs = epochs;
653 return pc;
654}
655
656
657/**
658 * Comparison function for quicksort
659 *
660 * @param a left element
661 * @param b right element
662 * @return a-b
663 */
664static int
665cmp_pow_value (const void *a, const void *b)
666{
667 return (GNUNET_ntohll (*(uint64_t*) a) - GNUNET_ntohll (*(uint64_t*) b));
668}
669
670
671/**
672 * Calculate a key revocation valid for broadcasting for a number
673 * of epochs.
674 *
675 * @param pc handle to the PoW, initially called with NULL.
676 * @param epochs number of epochs for which the revocation must be valid.
677 * @param pow current pow value to try
678 * @param difficulty current base difficulty to achieve
679 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
680 */
681enum GNUNET_GenericReturnValue
682GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
683{
684 char buf[sizeof(struct GNUNET_IDENTITY_PublicKey)
685 + sizeof (uint64_t)
686 + sizeof (uint64_t)] GNUNET_ALIGN;
687 struct GNUNET_HashCode result;
688 const struct GNUNET_IDENTITY_PublicKey *pk;
689 unsigned int zeros;
690 int ret;
691 uint64_t pow_nbo;
692 ssize_t ksize;
693
694 pc->current_pow++;
695 pk = (const struct GNUNET_IDENTITY_PublicKey *) &(pc->pow[1]);
696
697 /**
698 * Do not try duplicates
699 */
700 for (unsigned int i = 0; i < POW_COUNT; i++)
701 if (pc->current_pow == pc->best[i].pow)
702 return GNUNET_NO;
703 pow_nbo = GNUNET_htonll (pc->current_pow);
704 GNUNET_memcpy (buf, &pow_nbo, sizeof(uint64_t));
705 GNUNET_memcpy (&buf[sizeof(uint64_t)],
706 &pc->pow->timestamp,
707 sizeof (uint64_t));
708 ksize = GNUNET_IDENTITY_key_get_length (pk);
709 GNUNET_assert (0 < ksize);
710 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
711 pk,
712 ksize);
713 GNUNET_CRYPTO_pow_hash (&salt,
714 buf,
715 sizeof(buf),
716 &result);
717 zeros = GNUNET_CRYPTO_hash_count_leading_zeros (&result);
718 for (unsigned int i = 0; i < POW_COUNT; i++)
719 {
720 if (pc->best[i].bits < zeros)
721 {
722 pc->best[i].bits = zeros;
723 pc->best[i].pow = pc->current_pow;
724 pc->pow->pow[i] = pow_nbo;
725 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
726 "New best score %u with %" PRIu64 " (#%u)\n",
727 zeros, pc->current_pow, i);
728
729 break;
730 }
731 }
732 ret = calculate_score (pc) >= pc->difficulty + pc->epochs ? GNUNET_YES :
733 GNUNET_NO;
734 if (GNUNET_YES == ret)
735 {
736 /* Sort POWs) */
737 qsort (pc->pow->pow, POW_COUNT, sizeof (uint64_t), &cmp_pow_value);
738 }
739 return ret;
740}
741
742
743/**
744 * Stop a PoW calculation
745 *
746 * @param pc the calculation to clean up
747 * @return #GNUNET_YES if pow valid, #GNUNET_NO if pow was set but is not
748 * valid
749 */
750void
751GNUNET_REVOCATION_pow_stop (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
752{
753 GNUNET_free (pc);
754}
755
756
757size_t
758GNUNET_REVOCATION_proof_get_size (const struct GNUNET_REVOCATION_PowP *pow)
759{
760 size_t size;
761 size_t ksize;
762 const struct GNUNET_IDENTITY_PublicKey *pk;
763
764 size = sizeof (struct GNUNET_REVOCATION_PowP);
765 pk = (const struct GNUNET_IDENTITY_PublicKey *) &pow[1];
766 ksize = GNUNET_IDENTITY_key_get_length (pk);
767 size += ksize;
768 size += GNUNET_IDENTITY_signature_get_raw_length_by_type (pk->type);
769 return size;
770}
771
772
773/* 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