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.am120
-rw-r--r--src/revocation/gnunet-revocation-tvg.c229
-rw-r--r--src/revocation/gnunet-revocation.c581
-rw-r--r--src/revocation/gnunet-service-revocation.c1064
-rw-r--r--src/revocation/meson.build63
-rw-r--r--src/revocation/plugin_block_revocation.c308
-rw-r--r--src/revocation/revocation.conf.in19
-rw-r--r--src/revocation/revocation.h124
-rw-r--r--src/revocation/revocation_api.c764
-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
-rw-r--r--src/revocation/test_revocation_testvectors.c297
14 files changed, 0 insertions, 4153 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 3ab6887dd..000000000
--- a/src/revocation/Makefile.am
+++ /dev/null
@@ -1,120 +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
21plugin_LTLIBRARIES = \
22 libgnunet_plugin_block_revocation.la
23
24libgnunet_plugin_block_revocation_la_SOURCES = \
25 plugin_block_revocation.c
26libgnunet_plugin_block_revocation_la_LIBADD = \
27 libgnunetrevocation.la \
28 $(top_builddir)/src/lib/block/libgnunetblockgroup.la \
29 $(top_builddir)/src/lib/block/libgnunetblock.la \
30 $(top_builddir)/src/lib/util/libgnunetutil.la \
31 $(top_builddir)/src/service/identity/libgnunetidentity.la \
32 $(LTLIBINTL)
33libgnunet_plugin_block_revocation_la_LDFLAGS = \
34 $(GN_PLUGIN_LDFLAGS)
35
36
37gnunet_revocation_SOURCES = \
38 gnunet-revocation.c
39gnunet_revocation_LDADD = \
40 libgnunetrevocation.la \
41 $(top_builddir)/src/service/identity/libgnunetidentity.la \
42 $(top_builddir)/src/lib/util/libgnunetutil.la \
43 $(GN_LIBINTL)
44
45gnunet_revocation_tvg_SOURCES = \
46 gnunet-revocation-tvg.c
47gnunet_revocation_tvg_LDADD = \
48 libgnunetrevocation.la \
49 $(top_builddir)/src/service/identity/libgnunetidentity.la \
50 $(top_builddir)/src/lib/util/libgnunetutil.la \
51 $(GN_LIBINTL)
52
53test_revocation_lsd0001testvectors_SOURCES = \
54 test_revocation_testvectors.c
55test_revocation_lsd0001testvectors_LDADD = \
56 $(top_builddir)/src/service/testing/libgnunettesting.la \
57 $(top_builddir)/src/service/identity/libgnunetidentity.la \
58 libgnunetrevocation.la \
59 $(top_builddir)/src/lib/util/libgnunetutil.la
60
61lib_LTLIBRARIES = libgnunetrevocation.la
62
63libgnunetrevocation_la_SOURCES = \
64 revocation_api.c revocation.h
65libgnunetrevocation_la_LIBADD = \
66 $(top_builddir)/src/lib/util/libgnunetutil.la \
67 $(top_builddir)/src/service/identity/libgnunetidentity.la \
68 $(LIBGCRYPT_LIBS) \
69 $(GN_LIBINTL) $(XLIB) -lgcrypt
70libgnunetrevocation_la_LDFLAGS = \
71 $(GN_LIB_LDFLAGS) \
72 -version-info 0:0:0
73
74libexec_PROGRAMS = \
75 gnunet-service-revocation
76
77noinst_PROGRAMS = \
78 gnunet-revocation-tvg
79
80gnunet_service_revocation_SOURCES = \
81 gnunet-service-revocation.c
82gnunet_service_revocation_LDADD = \
83 libgnunetrevocation.la \
84 $(top_builddir)/src/service/core/libgnunetcore.la \
85 $(top_builddir)/src/service/setu/libgnunetsetu.la \
86 $(top_builddir)/src/service/statistics/libgnunetstatistics.la \
87 $(top_builddir)/src/service/identity/libgnunetidentity.la \
88 $(top_builddir)/src/lib/util/libgnunetutil.la \
89 -lm \
90 $(GN_LIBINTL)
91
92test_revocation_SOURCES = \
93 test_revocation.c
94test_revocation_LDADD = \
95 $(top_builddir)/src/service/identity/libgnunetidentity.la \
96 libgnunetrevocation.la \
97 $(top_builddir)/src//core/libgnunetcore.la \
98 $(top_builddir)/src/lib/util/libgnunetutil.la \
99 $(top_builddir)/src/testbed/libgnunettestbed.la
100
101check_PROGRAMS = \
102 #test_revocation \
103 #test_revocation_lsd0001testvectors
104
105check_SCRIPTS = \
106 #test_local_revocation.py
107
108if ENABLE_TEST_RUN
109 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
110 TESTS = \
111 $(check_SCRIPTS) \
112 $(check_PROGRAMS)
113endif
114
115test_local_revocation.py: test_local_revocation.py.in Makefile
116 $(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
117 chmod +x test_local_revocation.py
118
119EXTRA_DIST = test_revocation.conf \
120 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 b59b7ba62..000000000
--- a/src/revocation/gnunet-revocation-tvg.c
+++ /dev/null
@@ -1,229 +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_testing_lib.h"
31#include "revocation.h"
32#include <inttypes.h>
33
34#define TEST_EPOCHS 2
35#define TEST_DIFFICULTY 5
36
37static char*d_pkey =
38 "6fea32c05af58bfa979553d188605fd57d8bf9cc263b78d5f7478c07b998ed70";
39
40static char *d_edkey =
41 "5af7020ee19160328832352bbc6a68a8d71a7cbe1b929969a7c66d415a0d8f65";
42
43int
44parsehex (char *src, char *dst, size_t dstlen, int invert)
45{
46 char *line = src;
47 char *data = line;
48 int off;
49 int read_byte;
50 int data_len = 0;
51
52 while (sscanf (data, " %02x%n", &read_byte, &off) == 1)
53 {
54 if (invert)
55 dst[dstlen - 1 - data_len++] = read_byte;
56 else
57 dst[data_len++] = read_byte;
58 data += off;
59 }
60 return data_len;
61}
62
63
64static void
65print_bytes_ (void *buf,
66 size_t buf_len,
67 int fold,
68 int in_be)
69{
70 int i;
71
72 for (i = 0; i < buf_len; i++)
73 {
74 if (0 != i)
75 {
76 if ((0 != fold) && (i % fold == 0))
77 printf ("\n ");
78 else
79 printf (" ");
80 }
81 else
82 {
83 printf (" ");
84 }
85 if (in_be)
86 printf ("%02x", ((unsigned char*) buf)[buf_len - 1 - i]);
87 else
88 printf ("%02x", ((unsigned char*) buf)[i]);
89 }
90 printf ("\n");
91}
92
93
94static void
95print_bytes (void *buf,
96 size_t buf_len,
97 int fold)
98{
99 print_bytes_ (buf, buf_len, fold, 0);
100}
101
102
103static void
104run_with_key (struct GNUNET_CRYPTO_PrivateKey *id_priv)
105{
106 struct GNUNET_CRYPTO_PublicKey id_pub;
107 struct GNUNET_REVOCATION_PowP *pow;
108 struct GNUNET_REVOCATION_PowCalculationHandle *ph;
109 struct GNUNET_TIME_Relative exp;
110 char ztld[128];
111 ssize_t key_len;
112
113 GNUNET_CRYPTO_key_get_public (id_priv,
114 &id_pub);
115 GNUNET_STRINGS_data_to_string (&id_pub,
116 GNUNET_CRYPTO_public_key_get_length (
117 &id_pub),
118 ztld,
119 sizeof (ztld));
120 fprintf (stdout, "\n");
121 fprintf (stdout, "Zone identifier (ztype|zkey):\n");
122 key_len = GNUNET_CRYPTO_public_key_get_length (&id_pub);
123 GNUNET_assert (0 < key_len);
124 print_bytes (&id_pub, key_len, 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/**
168 * Main function that will be run.
169 *
170 * @param cls closure
171 * @param args remaining command-line arguments
172 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
173 * @param cfg configuration
174 */
175static void
176run (void *cls,
177 char *const *args,
178 const char *cfgfile,
179 const struct GNUNET_CONFIGURATION_Handle *cfg)
180{
181 struct GNUNET_CRYPTO_PrivateKey id_priv;
182
183 id_priv.type = htonl (GNUNET_PUBLIC_KEY_TYPE_ECDSA);
184 parsehex (d_pkey,(char*) &id_priv.ecdsa_key, sizeof (id_priv.ecdsa_key), 1);
185
186 fprintf (stdout, "Zone private key (d, big-endian):\n");
187 print_bytes_ (&id_priv.ecdsa_key, sizeof(id_priv.ecdsa_key), 8, 1);
188 run_with_key (&id_priv);
189 printf ("\n");
190 id_priv.type = htonl (GNUNET_PUBLIC_KEY_TYPE_EDDSA);
191 parsehex (d_edkey,(char*) &id_priv.eddsa_key, sizeof (id_priv.eddsa_key), 0);
192
193 fprintf (stdout, "Zone private key (d):\n");
194 print_bytes (&id_priv.eddsa_key, sizeof(id_priv.eddsa_key), 8);
195 run_with_key (&id_priv);
196}
197
198
199/**
200 * The main function of the test vector generation tool.
201 *
202 * @param argc number of arguments from the command line
203 * @param argv command line arguments
204 * @return 0 ok, 1 on error
205 */
206int
207main (int argc,
208 char *const *argv)
209{
210 const struct GNUNET_GETOPT_CommandLineOption options[] = {
211 GNUNET_GETOPT_OPTION_END
212 };
213
214 GNUNET_assert (GNUNET_OK ==
215 GNUNET_log_setup ("gnunet-revocation-tvg",
216 "INFO",
217 NULL));
218 if (GNUNET_OK !=
219 GNUNET_PROGRAM_run (argc, argv,
220 "gnunet-revocation-tvg",
221 "Generate test vectors for revocation",
222 options,
223 &run, NULL))
224 return 1;
225 return 0;
226}
227
228
229/* 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 9667e7655..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_CRYPTO_PublicKey key;
327 const struct GNUNET_CRYPTO_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_CRYPTO_public_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_CRYPTO_PublicKey pk;
415 size_t psize;
416
417 cfg = c;
418 if (NULL != test_ego)
419 {
420 if (GNUNET_OK !=
421 GNUNET_CRYPTO_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 3755b87e5..000000000
--- a/src/revocation/gnunet-service-revocation.c
+++ /dev/null
@@ -1,1064 +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
224static int
225check_query_message (void *cls,
226 const struct QueryMessage *qm)
227{
228 uint16_t size;
229
230 size = ntohs (qm->header.size);
231 if (size <= sizeof(struct RevokeMessage) ||
232 (size > UINT16_MAX))
233 {
234 GNUNET_break (0);
235 return GNUNET_SYSERR;
236 }
237 return GNUNET_OK;
238
239}
240
241
242/**
243 * Handle QUERY message from client.
244 *
245 * @param cls client who sent the message
246 * @param qm the message received
247 */
248static void
249handle_query_message (void *cls,
250 const struct QueryMessage *qm)
251{
252 struct GNUNET_SERVICE_Client *client = cls;
253 struct GNUNET_CRYPTO_PublicKey zone;
254 struct GNUNET_MQ_Envelope *env;
255 struct QueryResponseMessage *qrm;
256 struct GNUNET_HashCode hc;
257 int res;
258 size_t key_len;
259 size_t read;
260
261 key_len = ntohl (qm->key_len);
262 if ((GNUNET_SYSERR ==
263 GNUNET_CRYPTO_read_public_key_from_buffer (&qm[1], key_len,
264 &zone, &read)) ||
265 (read != key_len))
266 {
267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
268 "Unable to parse query public key\n");
269 GNUNET_SERVICE_client_drop (client);
270 return;
271 }
272 GNUNET_CRYPTO_hash (&qm[1],
273 key_len,
274 &hc);
275 res = GNUNET_CONTAINER_multihashmap_contains (revocation_map,
276 &hc);
277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
278 (GNUNET_NO == res)
279 ? "Received revocation check for valid key `%s' from client\n"
280 : "Received revocation check for revoked key `%s' from client\n",
281 GNUNET_h2s (&hc));
282 env = GNUNET_MQ_msg (qrm,
283 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE);
284 qrm->is_valid = htonl ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES);
285 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
286 env);
287 GNUNET_SERVICE_client_continue (client);
288}
289
290
291/**
292 * Flood the given revocation message to all neighbours.
293 *
294 * @param cls the `struct RevokeMessage` to flood
295 * @param target a neighbour
296 * @param value our `struct PeerEntry` for the neighbour
297 * @return #GNUNET_OK (continue to iterate)
298 */
299static enum GNUNET_GenericReturnValue
300do_flood (void *cls,
301 const struct GNUNET_PeerIdentity *target,
302 void *value)
303{
304 const struct RevokeMessage *rm = cls;
305 struct PeerEntry *pe = value;
306 struct GNUNET_MQ_Envelope *e;
307 struct RevokeMessage *cp;
308
309 if (NULL == pe->mq)
310 return GNUNET_OK; /* peer connected to us via SET,
311 but we have no direct CORE
312 connection for flooding */
313 e = GNUNET_MQ_msg_extra (cp,
314 htonl (rm->pow_size),
315 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
316 *cp = *rm;
317 memcpy (&cp[1],
318 &rm[1],
319 htonl (rm->pow_size));
320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
321 "Flooding revocation to `%s'\n",
322 GNUNET_i2s (target));
323 GNUNET_MQ_send (pe->mq,
324 e);
325 return GNUNET_OK;
326}
327
328
329/**
330 * Publicize revocation message. Stores the message locally in the
331 * database and passes it to all connected neighbours (and adds it to
332 * the set for future connections).
333 *
334 * @param rm message to publicize
335 * @return #GNUNET_OK on success, #GNUNET_NO if we encountered an error,
336 * #GNUNET_SYSERR if the message was malformed
337 */
338static enum GNUNET_GenericReturnValue
339publicize_rm (const struct RevokeMessage *rm)
340{
341 struct RevokeMessage *cp;
342 struct GNUNET_HashCode hc;
343 struct GNUNET_SETU_Element e;
344 ssize_t pklen;
345 const struct GNUNET_REVOCATION_PowP *pow
346 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
347 const struct GNUNET_CRYPTO_PublicKey *pk
348 = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
349
350 /** FIXME yeah this works, but should we have a key length somewhere? */
351 pklen = GNUNET_CRYPTO_public_key_get_length (pk);
352 if (0 > pklen)
353 {
354 GNUNET_break_op (0);
355 return GNUNET_SYSERR;
356 }
357 GNUNET_CRYPTO_hash (pk,
358 pklen,
359 &hc);
360 if (GNUNET_YES ==
361 GNUNET_CONTAINER_multihashmap_contains (revocation_map,
362 &hc))
363 {
364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
365 "Duplicate revocation received from peer. Ignored.\n");
366 return GNUNET_OK;
367 }
368 if (GNUNET_OK !=
369 verify_revoke_message (rm))
370 {
371 GNUNET_break_op (0);
372 return GNUNET_SYSERR;
373 }
374 /* write to disk */
375 if (sizeof(struct RevokeMessage) !=
376 GNUNET_DISK_file_write (revocation_db,
377 rm,
378 sizeof(struct RevokeMessage)))
379 {
380 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
381 "write");
382 return GNUNET_NO;
383 }
384 if (GNUNET_OK !=
385 GNUNET_DISK_file_sync (revocation_db))
386 {
387 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
388 "sync");
389 return GNUNET_NO;
390 }
391 /* keep copy in memory */
392 cp = (struct RevokeMessage *) GNUNET_copy_message (&rm->header);
393 GNUNET_break (GNUNET_OK ==
394 GNUNET_CONTAINER_multihashmap_put (revocation_map,
395 &hc,
396 cp,
397 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
398 /* add to set for future connections */
399 e.size = htons (rm->header.size);
400 e.element_type = GNUNET_BLOCK_TYPE_REVOCATION;
401 e.data = rm;
402 if (GNUNET_OK !=
403 GNUNET_SETU_add_element (revocation_set,
404 &e,
405 NULL,
406 NULL))
407 {
408 GNUNET_break (0);
409 return GNUNET_OK;
410 }
411 else
412 {
413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
414 "Added revocation info to SET\n");
415 }
416 /* flood to neighbours */
417 GNUNET_CONTAINER_multipeermap_iterate (peers,
418 &do_flood,
419 cp);
420 return GNUNET_OK;
421}
422
423
424static int
425check_revoke_message (void *cls,
426 const struct RevokeMessage *rm)
427{
428 uint16_t size;
429
430 size = ntohs (rm->header.size);
431 if (size <= sizeof(struct RevokeMessage) ||
432 (size > UINT16_MAX))
433 {
434 GNUNET_break (0);
435 return GNUNET_SYSERR;
436 }
437 return GNUNET_OK;
438
439}
440
441
442/**
443 * Handle REVOKE message from client.
444 *
445 * @param cls client who sent the message
446 * @param rm the message received
447 */
448static void
449handle_revoke_message (void *cls,
450 const struct RevokeMessage *rm)
451{
452 struct GNUNET_SERVICE_Client *client = cls;
453 struct GNUNET_MQ_Envelope *env;
454 struct RevocationResponseMessage *rrm;
455 int ret;
456
457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
458 "Received REVOKE message from client\n");
459 if (GNUNET_SYSERR == (ret = publicize_rm (rm)))
460 {
461 GNUNET_break_op (0);
462 GNUNET_SERVICE_client_drop (client);
463 return;
464 }
465 env = GNUNET_MQ_msg (rrm,
466 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE);
467 rrm->is_valid = htonl ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES);
468 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
469 env);
470 GNUNET_SERVICE_client_continue (client);
471}
472
473
474static int
475check_p2p_revoke (void *cls,
476 const struct RevokeMessage *rm)
477{
478 uint16_t size;
479
480 size = ntohs (rm->header.size);
481 if (size <= sizeof(struct RevokeMessage))
482 {
483 GNUNET_break (0);
484 return GNUNET_SYSERR;
485 }
486 return GNUNET_OK;
487
488}
489
490
491/**
492 * Core handler for flooded revocation messages.
493 *
494 * @param cls closure unused
495 * @param rm revocation message
496 */
497static void
498handle_p2p_revoke (void *cls,
499 const struct RevokeMessage *rm)
500{
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502 "Received REVOKE message\n");
503 GNUNET_break_op (GNUNET_SYSERR !=
504 publicize_rm (rm));
505}
506
507
508/**
509 * Callback for set operation results. Called for each element in the
510 * result set. Each element contains a revocation, which we should
511 * validate and then add to our revocation list (and set).
512 *
513 * @param cls closure
514 * @param element a result element, only valid if status is #GNUNET_SETU_STATUS_OK
515 * @param current_size current set size
516 * @param status see `enum GNUNET_SETU_Status`
517 */
518static void
519add_revocation (void *cls,
520 const struct GNUNET_SETU_Element *element,
521 uint64_t current_size,
522 enum GNUNET_SETU_Status status)
523{
524 struct PeerEntry *peer_entry = cls;
525 const struct RevokeMessage *rm;
526
527 switch (status)
528 {
529 case GNUNET_SETU_STATUS_ADD_LOCAL:
530 if (element->size != sizeof(struct RevokeMessage))
531 {
532 GNUNET_break_op (0);
533 return;
534 }
535 if (GNUNET_BLOCK_TYPE_REVOCATION != element->element_type)
536 {
537 GNUNET_STATISTICS_update (stats,
538 gettext_noop (
539 "# unsupported revocations received via set union"),
540 1,
541 GNUNET_NO);
542 return;
543 }
544 rm = element->data;
545 (void) handle_p2p_revoke (NULL,
546 rm);
547 GNUNET_STATISTICS_update (stats,
548 gettext_noop (
549 "# revocation messages received via set union"),
550 1, GNUNET_NO);
551 break;
552 case GNUNET_SETU_STATUS_FAILURE:
553 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
554 _ ("Error computing revocation set union with %s\n"),
555 GNUNET_i2s (&peer_entry->id));
556 peer_entry->so = NULL;
557 GNUNET_STATISTICS_update (stats,
558 gettext_noop ("# revocation set unions failed"),
559 1,
560 GNUNET_NO);
561 break;
562 case GNUNET_SETU_STATUS_DONE:
563 peer_entry->so = NULL;
564 GNUNET_STATISTICS_update (stats,
565 gettext_noop (
566 "# revocation set unions completed"),
567 1,
568 GNUNET_NO);
569 break;
570 default:
571 GNUNET_break (0);
572 break;
573 }
574}
575
576
577/**
578 * The timeout for performing the set union has expired,
579 * run the set operation on the revocation certificates.
580 *
581 * @param cls NULL
582 */
583static void
584transmit_task_cb (void *cls)
585{
586 struct PeerEntry *peer_entry = cls;
587
588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
589 "Starting set exchange with peer `%s'\n",
590 GNUNET_i2s (&peer_entry->id));
591 peer_entry->transmit_task = NULL;
592 GNUNET_assert (NULL == peer_entry->so);
593 peer_entry->so = GNUNET_SETU_prepare (&peer_entry->id,
594 &revocation_set_union_app_id,
595 NULL,
596 (struct GNUNET_SETU_Option[]) { { 0 } },
597 &add_revocation,
598 peer_entry);
599 if (GNUNET_OK !=
600 GNUNET_SETU_commit (peer_entry->so,
601 revocation_set))
602 {
603 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
604 _ ("SET service crashed, terminating revocation service\n"));
605 GNUNET_SCHEDULER_shutdown ();
606 return;
607 }
608}
609
610
611/**
612 * Method called whenever a peer connects. Sets up the PeerEntry and
613 * schedules the initial revocation set exchange with this peer.
614 *
615 * @param cls closure
616 * @param peer peer identity this notification is about
617 */
618static void *
619handle_core_connect (void *cls,
620 const struct GNUNET_PeerIdentity *peer,
621 struct GNUNET_MQ_Handle *mq)
622{
623 struct PeerEntry *peer_entry;
624 struct GNUNET_HashCode my_hash;
625 struct GNUNET_HashCode peer_hash;
626
627 if (0 == GNUNET_memcmp (peer,
628 &my_identity))
629 {
630 return NULL;
631 }
632
633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
634 "Peer `%s' connected to us\n",
635 GNUNET_i2s (peer));
636 GNUNET_STATISTICS_update (stats,
637 "# peers connected",
638 1,
639 GNUNET_NO);
640 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
641 peer);
642 if (NULL != peer_entry)
643 {
644 /* This can happen if "core"'s notification is a tad late
645 and CADET+SET were faster and already produced a
646 #handle_revocation_union_request() for us to deal
647 with. This should be rare, but isn't impossible. */
648 peer_entry->mq = mq;
649 return peer_entry;
650 }
651 peer_entry = new_peer_entry (peer);
652 peer_entry->mq = mq;
653 GNUNET_CRYPTO_hash (&my_identity,
654 sizeof(my_identity),
655 &my_hash);
656 GNUNET_CRYPTO_hash (peer,
657 sizeof(*peer),
658 &peer_hash);
659 if (0 < GNUNET_CRYPTO_hash_cmp (&my_hash,
660 &peer_hash))
661 {
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
663 "Starting SET operation with peer `%s'\n",
664 GNUNET_i2s (peer));
665 peer_entry->transmit_task =
666 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
667 &transmit_task_cb,
668 peer_entry);
669 }
670 return peer_entry;
671}
672
673
674/**
675 * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels
676 * any pending transmission requests to that peer.
677 *
678 * @param cls closure
679 * @param peer peer identity this notification is about
680 * @param internal_cls our `struct PeerEntry` for this peer
681 */
682static void
683handle_core_disconnect (void *cls,
684 const struct GNUNET_PeerIdentity *peer,
685 void *internal_cls)
686{
687 struct PeerEntry *peer_entry = internal_cls;
688
689 if (0 == GNUNET_memcmp (peer,
690 &my_identity))
691 return;
692 GNUNET_assert (NULL != peer_entry);
693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
694 "Peer `%s' disconnected from us\n",
695 GNUNET_i2s (peer));
696 GNUNET_assert (GNUNET_YES ==
697 GNUNET_CONTAINER_multipeermap_remove (peers,
698 peer,
699 peer_entry));
700 if (NULL != peer_entry->transmit_task)
701 {
702 GNUNET_SCHEDULER_cancel (peer_entry->transmit_task);
703 peer_entry->transmit_task = NULL;
704 }
705 if (NULL != peer_entry->so)
706 {
707 GNUNET_SETU_operation_cancel (peer_entry->so);
708 peer_entry->so = NULL;
709 }
710 GNUNET_free (peer_entry);
711 GNUNET_STATISTICS_update (stats,
712 "# peers connected",
713 -1,
714 GNUNET_NO);
715}
716
717
718/**
719 * Free all values in a hash map.
720 *
721 * @param cls NULL
722 * @param key the key
723 * @param value value to free
724 * @return #GNUNET_OK (continue to iterate)
725 */
726static int
727free_entry (void *cls,
728 const struct GNUNET_HashCode *key,
729 void *value)
730{
731 GNUNET_free (value);
732 return GNUNET_OK;
733}
734
735
736/**
737 * Task run during shutdown.
738 *
739 * @param cls unused
740 */
741static void
742shutdown_task (void *cls)
743{
744 if (NULL != revocation_set)
745 {
746 GNUNET_SETU_destroy (revocation_set);
747 revocation_set = NULL;
748 }
749 if (NULL != revocation_union_listen_handle)
750 {
751 GNUNET_SETU_listen_cancel (revocation_union_listen_handle);
752 revocation_union_listen_handle = NULL;
753 }
754 if (NULL != core_api)
755 {
756 GNUNET_CORE_disconnect (core_api);
757 core_api = NULL;
758 }
759 if (NULL != stats)
760 {
761 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
762 stats = NULL;
763 }
764 if (NULL != peers)
765 {
766 GNUNET_CONTAINER_multipeermap_destroy (peers);
767 peers = NULL;
768 }
769 if (NULL != revocation_db)
770 {
771 GNUNET_DISK_file_close (revocation_db);
772 revocation_db = NULL;
773 }
774 GNUNET_CONTAINER_multihashmap_iterate (revocation_map,
775 &free_entry,
776 NULL);
777 GNUNET_CONTAINER_multihashmap_destroy (revocation_map);
778}
779
780
781/**
782 * Called on core init/fail.
783 *
784 * @param cls service closure
785 * @param identity the public identity of this peer
786 */
787static void
788core_init (void *cls,
789 const struct GNUNET_PeerIdentity *identity)
790{
791 if (NULL == identity)
792 {
793 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
794 "Connection to core FAILED!\n");
795 GNUNET_SCHEDULER_shutdown ();
796 return;
797 }
798 my_identity = *identity;
799}
800
801
802/**
803 * Called when another peer wants to do a set operation with the
804 * local peer. If a listen error occurs, the 'request' is NULL.
805 *
806 * @param cls closure
807 * @param other_peer the other peer
808 * @param context_msg message with application specific information from
809 * the other peer
810 * @param request request from the other peer (never NULL), use GNUNET_SETU_accept()
811 * to accept it, otherwise the request will be refused
812 * Note that we can't just return value from the listen callback,
813 * as it is also necessary to specify the set we want to do the
814 * operation with, which sometimes can be derived from the context
815 * message. It's necessary to specify the timeout.
816 */
817static void
818handle_revocation_union_request (void *cls,
819 const struct GNUNET_PeerIdentity *other_peer,
820 const struct GNUNET_MessageHeader *context_msg,
821 struct GNUNET_SETU_Request *request)
822{
823 struct PeerEntry *peer_entry;
824
825 if (NULL == request)
826 {
827 GNUNET_break (0);
828 return;
829 }
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "Received set exchange request from peer `%s'\n",
832 GNUNET_i2s (other_peer));
833 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
834 other_peer);
835 if (NULL == peer_entry)
836 {
837 peer_entry = new_peer_entry (other_peer);
838 }
839 if (NULL != peer_entry->so)
840 {
841 GNUNET_break_op (0);
842 return;
843 }
844 peer_entry->so = GNUNET_SETU_accept (request,
845 (struct GNUNET_SETU_Option[]) { { 0 } },
846 &add_revocation,
847 peer_entry);
848 if (GNUNET_OK !=
849 GNUNET_SETU_commit (peer_entry->so,
850 revocation_set))
851 {
852 GNUNET_break (0);
853 GNUNET_SCHEDULER_shutdown ();
854 return;
855 }
856}
857
858
859/**
860 * Handle network size estimate clients.
861 *
862 * @param cls closure
863 * @param server the initialized server
864 * @param c configuration to use
865 */
866static void
867run (void *cls,
868 const struct GNUNET_CONFIGURATION_Handle *c,
869 struct GNUNET_SERVICE_Handle *service)
870{
871 struct GNUNET_MQ_MessageHandler core_handlers[] = {
872 GNUNET_MQ_hd_var_size (p2p_revoke,
873 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
874 struct RevokeMessage,
875 NULL),
876 GNUNET_MQ_handler_end ()
877 };
878 char *fn;
879 uint64_t left;
880 struct RevokeMessage *rm;
881 struct GNUNET_HashCode hc;
882 const struct GNUNET_CRYPTO_PublicKey *pk;
883
884 GNUNET_CRYPTO_hash ("revocation-set-union-application-id",
885 strlen ("revocation-set-union-application-id"),
886 &revocation_set_union_app_id);
887 if (GNUNET_OK !=
888 GNUNET_CONFIGURATION_get_value_filename (c,
889 "REVOCATION",
890 "DATABASE",
891 &fn))
892 {
893 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
894 "REVOCATION",
895 "DATABASE");
896 GNUNET_SCHEDULER_shutdown ();
897 return;
898 }
899 cfg = c;
900 revocation_map = GNUNET_CONTAINER_multihashmap_create (16,
901 GNUNET_NO);
902 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
903 NULL);
904 if (GNUNET_OK !=
905 GNUNET_CONFIGURATION_get_value_number (cfg,
906 "REVOCATION",
907 "WORKBITS",
908 &revocation_work_required))
909 {
910 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
911 "REVOCATION",
912 "WORKBITS");
913 GNUNET_SCHEDULER_shutdown ();
914 GNUNET_free (fn);
915 return;
916 }
917 if (revocation_work_required >= sizeof(struct GNUNET_HashCode) * 8)
918 {
919 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
920 "REVOCATION",
921 "WORKBITS",
922 _ ("Value is too large.\n"));
923 GNUNET_SCHEDULER_shutdown ();
924 GNUNET_free (fn);
925 return;
926 }
927 if (GNUNET_OK !=
928 GNUNET_CONFIGURATION_get_value_time (cfg,
929 "REVOCATION",
930 "EPOCH_DURATION",
931 &epoch_duration))
932 {
933 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
934 "REVOCATION",
935 "EPOCH_DURATION");
936 GNUNET_SCHEDULER_shutdown ();
937 GNUNET_free (fn);
938 return;
939 }
940
941 revocation_set = GNUNET_SETU_create (cfg);
942 revocation_union_listen_handle
943 = GNUNET_SETU_listen (cfg,
944 &revocation_set_union_app_id,
945 &handle_revocation_union_request,
946 NULL);
947 revocation_db = GNUNET_DISK_file_open (fn,
948 GNUNET_DISK_OPEN_READWRITE
949 | GNUNET_DISK_OPEN_CREATE,
950 GNUNET_DISK_PERM_USER_READ
951 | GNUNET_DISK_PERM_USER_WRITE
952 | GNUNET_DISK_PERM_GROUP_READ
953 | GNUNET_DISK_PERM_OTHER_READ);
954 if (NULL == revocation_db)
955 {
956 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
957 "REVOCATION",
958 "DATABASE",
959 _ ("Could not open revocation database file!"));
960 GNUNET_SCHEDULER_shutdown ();
961 GNUNET_free (fn);
962 return;
963 }
964 if (GNUNET_OK !=
965 GNUNET_DISK_file_size (fn, &left, GNUNET_YES, GNUNET_YES))
966 left = 0;
967 while (left > sizeof(struct RevokeMessage))
968 {
969 rm = GNUNET_new (struct RevokeMessage);
970 if (sizeof(struct RevokeMessage) !=
971 GNUNET_DISK_file_read (revocation_db,
972 rm,
973 sizeof(struct RevokeMessage)))
974 {
975 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
976 "read",
977 fn);
978 GNUNET_free (rm);
979 GNUNET_SCHEDULER_shutdown ();
980 GNUNET_free (fn);
981 return;
982 }
983 struct GNUNET_REVOCATION_PowP *pow = (struct
984 GNUNET_REVOCATION_PowP *) &rm[1];
985 ssize_t ksize;
986 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
987 ksize = GNUNET_CRYPTO_public_key_get_length (pk);
988 if (0 > ksize)
989 {
990 GNUNET_break_op (0);
991 GNUNET_free (rm);
992 GNUNET_free (fn);
993 return;
994 }
995 GNUNET_CRYPTO_hash (pk,
996 ksize,
997 &hc);
998 GNUNET_break (GNUNET_OK ==
999 GNUNET_CONTAINER_multihashmap_put (revocation_map,
1000 &hc,
1001 rm,
1002 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1003 }
1004 GNUNET_free (fn);
1005
1006 peers = GNUNET_CONTAINER_multipeermap_create (128,
1007 GNUNET_YES);
1008 /* Connect to core service and register core handlers */
1009 core_api = GNUNET_CORE_connect (cfg, /* Main configuration */
1010 NULL, /* Closure passed to functions */
1011 &core_init, /* Call core_init once connected */
1012 &handle_core_connect, /* Handle connects */
1013 &handle_core_disconnect, /* Handle disconnects */
1014 core_handlers); /* Register these handlers */
1015 if (NULL == core_api)
1016 {
1017 GNUNET_SCHEDULER_shutdown ();
1018 return;
1019 }
1020 stats = GNUNET_STATISTICS_create ("revocation",
1021 cfg);
1022}
1023
1024
1025/**
1026 * Define "main" method using service macro.
1027 */
1028GNUNET_SERVICE_MAIN
1029 ("revocation",
1030 GNUNET_SERVICE_OPTION_NONE,
1031 &run,
1032 &client_connect_cb,
1033 &client_disconnect_cb,
1034 NULL,
1035 GNUNET_MQ_hd_var_size (query_message,
1036 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY,
1037 struct QueryMessage,
1038 NULL),
1039 GNUNET_MQ_hd_var_size (revoke_message,
1040 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE,
1041 struct RevokeMessage,
1042 NULL),
1043 GNUNET_MQ_handler_end ());
1044
1045
1046#if defined(__linux__) && defined(__GLIBC__)
1047#include <malloc.h>
1048
1049/**
1050 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
1051 */
1052void __attribute__ ((constructor))
1053GNUNET_REVOCATION_memory_init ()
1054{
1055 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1056 mallopt (M_TOP_PAD, 1 * 1024);
1057 malloc_trim (0);
1058}
1059
1060
1061#endif
1062
1063
1064/* end of gnunet-service-revocation.c */
diff --git a/src/revocation/meson.build b/src/revocation/meson.build
deleted file mode 100644
index 9a526af36..000000000
--- a/src/revocation/meson.build
+++ /dev/null
@@ -1,63 +0,0 @@
1libgnunetrevocation_src = ['revocation_api.c']
2
3gnunetservicerevocation_src = ['gnunet-service-revocation.c']
4
5configure_file(input : 'revocation.conf.in',
6 output : 'revocation.conf',
7 configuration : cdata,
8 install: true,
9 install_dir: pkgcfgdir)
10
11
12if get_option('monolith')
13 foreach p : libgnunetrevocation_src + gnunetservicerevocation_src
14 gnunet_src += 'revocation/' + p
15 endforeach
16 subdir_done()
17endif
18
19libgnunetrevocation = library('gnunetrevocation',
20 libgnunetrevocation_src,
21 soversion: '0',
22 version: '0.0.0',
23 dependencies: [libgnunetutil_dep, libgnunetidentity_dep],
24 include_directories: [incdir, configuration_inc],
25 install: true,
26 install_dir: get_option('libdir'))
27libgnunetrevocation_dep = declare_dependency(link_with : libgnunetrevocation)
28pkg.generate(libgnunetrevocation, url: 'https://www.gnunet.org',
29 description : 'Provides API to perform key revocation in GNUnet')
30
31shared_module('gnunet_plugin_block_revocation',
32 ['plugin_block_revocation.c'],
33 dependencies: [libgnunetutil_dep,
34 libgnunetidentity_dep,
35 libgnunetrevocation_dep,
36 libgnunetblock_dep],
37 include_directories: [incdir, configuration_inc],
38 install: true,
39 install_dir: get_option('libdir')/'gnunet')
40
41executable ('gnunet-revocation',
42 ['gnunet-revocation.c'],
43 dependencies: [libgnunetrevocation_dep,
44 libgnunetutil_dep,
45 libgnunetstatistics_dep,
46 libgnunetcore_dep,
47 libgnunetsetu_dep,
48 libgnunetidentity_dep],
49 include_directories: [incdir, configuration_inc],
50 install: true,
51 install_dir: get_option('bindir'))
52executable ('gnunet-service-revocation',
53 gnunetservicerevocation_src,
54 dependencies: [libgnunetrevocation_dep,
55 libgnunetutil_dep,
56 libgnunetstatistics_dep,
57 libgnunetcore_dep,
58 libgnunetsetu_dep,
59 libgnunetidentity_dep],
60 include_directories: [incdir, configuration_inc],
61 install: true,
62 install_dir: get_option('libdir')/'gnunet'/'libexec')
63
diff --git a/src/revocation/plugin_block_revocation.c b/src/revocation/plugin_block_revocation.c
deleted file mode 100644
index 9686f23ff..000000000
--- a/src/revocation/plugin_block_revocation.c
+++ /dev/null
@@ -1,308 +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_CRYPTO_PublicKey pk;
98 size_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 if (GNUNET_SYSERR ==
118 GNUNET_CRYPTO_read_public_key_from_buffer (&pow[1],
119 left,
120 &pk,
121 &pklen))
122 {
123 GNUNET_break_op (0);
124 return GNUNET_NO;
125 }
126 if (0 == pklen)
127 {
128 GNUNET_break_op (0);
129 return GNUNET_NO;
130 }
131 if (GNUNET_YES !=
132 GNUNET_REVOCATION_check_pow (pow,
133 ic->matching_bits,
134 ic->epoch_duration))
135 {
136 GNUNET_break_op (0);
137 return GNUNET_NO;
138 }
139 return GNUNET_OK;
140}
141
142
143/**
144 * Function called to validate a reply to a request. Note that it is assumed
145 * that the reply has already been matched to the key (and signatures checked)
146 * as it would be done with the GetKeyFunction and the
147 * BlockEvaluationFunction.
148 *
149 * @param cls closure
150 * @param type block type
151 * @param group which block group to use for evaluation
152 * @param query original query (hash)
153 * @param xquery extrended query data (can be NULL, depending on type)
154 * @param xquery_size number of bytes in @a xquery
155 * @param reply_block response to validate
156 * @param reply_block_size number of bytes in @a reply_block
157 * @return characterization of result
158 */
159static enum GNUNET_BLOCK_ReplyEvaluationResult
160block_plugin_revocation_check_reply (
161 void *cls,
162 enum GNUNET_BLOCK_Type type,
163 struct GNUNET_BLOCK_Group *group,
164 const struct GNUNET_HashCode *query,
165 const void *xquery,
166 size_t xquery_size,
167 const void *reply_block,
168 size_t reply_block_size)
169{
170 (void) cls;
171 (void) group;
172 (void) query;
173 (void) xquery;
174 (void) xquery_size;
175 (void) reply_block;
176 (void) reply_block_size;
177 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
178 {
179 GNUNET_break (0);
180 return GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED;
181 }
182 return GNUNET_BLOCK_REPLY_OK_LAST;
183}
184
185
186/**
187 * Function called to obtain the key for a block.
188 *
189 * @param cls closure
190 * @param type block type
191 * @param block block to get the key for
192 * @param block_size number of bytes in block
193 * @param key set to the key (query) for the given block
194 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported
195 * (or if extracting a key from a block of this type does not work)
196 */
197static enum GNUNET_GenericReturnValue
198block_plugin_revocation_get_key (void *cls,
199 enum GNUNET_BLOCK_Type type,
200 const void *block,
201 size_t block_size,
202 struct GNUNET_HashCode *key)
203{
204 const struct RevokeMessage *rm = block;
205 const struct GNUNET_REVOCATION_PowP *pow
206 = (const struct GNUNET_REVOCATION_PowP *) &rm[1];
207 struct GNUNET_CRYPTO_PublicKey pk;
208 size_t pklen;
209 size_t left;
210
211 if (GNUNET_BLOCK_TYPE_REVOCATION != type)
212 {
213 GNUNET_break (0);
214 return GNUNET_SYSERR;
215 }
216 if (block_size < sizeof(*rm) + sizeof(*pow))
217 {
218 GNUNET_break_op (0);
219 return GNUNET_NO;
220 }
221 if (block_size != sizeof(*rm) + ntohl (rm->pow_size))
222 {
223 GNUNET_break_op (0);
224 return GNUNET_NO;
225 }
226 left = block_size - sizeof (*rm) - sizeof (*pow);
227 if (GNUNET_SYSERR == GNUNET_CRYPTO_read_public_key_from_buffer (&pow[1],
228 left,
229 &pk,
230 &pklen))
231 {
232 GNUNET_break_op (0);
233 return GNUNET_NO;
234 }
235 if (0 == pklen)
236 {
237 GNUNET_break_op (0);
238 return GNUNET_NO;
239 }
240 GNUNET_CRYPTO_hash (&pow[1],
241 pklen,
242 key);
243 return GNUNET_OK;
244}
245
246
247/**
248 * Entry point for the plugin.
249 *
250 * @param cls the configuration to use
251 */
252void *
253libgnunet_plugin_block_revocation_init (void *cls)
254{
255 static const enum GNUNET_BLOCK_Type types[] = {
256 GNUNET_BLOCK_TYPE_REVOCATION,
257 GNUNET_BLOCK_TYPE_ANY /* end of list */
258 };
259 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
260 struct GNUNET_BLOCK_PluginFunctions *api;
261 struct InternalContext *ic;
262 unsigned long long matching_bits;
263 struct GNUNET_TIME_Relative epoch_duration;
264
265 if (GNUNET_OK !=
266 GNUNET_CONFIGURATION_get_value_number (cfg,
267 "REVOCATION",
268 "WORKBITS",
269 &matching_bits))
270 return NULL;
271 if (GNUNET_OK !=
272 GNUNET_CONFIGURATION_get_value_time (cfg,
273 "REVOCATION",
274 "EPOCH_DURATION",
275 &epoch_duration))
276 return NULL;
277
278 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
279 api->get_key = &block_plugin_revocation_get_key;
280 api->check_query = &block_plugin_revocation_check_query;
281 api->check_block = &block_plugin_revocation_check_block;
282 api->check_reply = &block_plugin_revocation_check_reply;
283 api->create_group = NULL;
284 api->types = types;
285 ic = GNUNET_new (struct InternalContext);
286 ic->matching_bits = (unsigned int) matching_bits;
287 ic->epoch_duration = epoch_duration;
288 api->cls = ic;
289 return api;
290}
291
292
293/**
294 * Exit point from the plugin.
295 */
296void *
297libgnunet_plugin_block_revocation_done (void *cls)
298{
299 struct GNUNET_BLOCK_PluginFunctions *api = cls;
300 struct InternalContext *ic = api->cls;
301
302 GNUNET_free (ic);
303 GNUNET_free (api);
304 return NULL;
305}
306
307
308/* 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 90b8c7da0..000000000
--- a/src/revocation/revocation.h
+++ /dev/null
@@ -1,124 +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 * Key length.
46 */
47 uint32_t key_len GNUNET_PACKED;
48
49 /**
50 * Followed by the public key to check.
51 */
52};
53
54
55/**
56 * Key revocation response.
57 */
58struct QueryResponseMessage
59{
60 /**
61 * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE
62 */
63 struct GNUNET_MessageHeader header;
64
65 /**
66 * #GNUNET_NO if revoked, #GNUNET_YES if valid.
67 */
68 uint32_t is_valid GNUNET_PACKED;
69};
70
71
72/**
73 * Revoke key. These messages are exchanged between peers (during
74 * flooding) but also sent by the client to the service. When the
75 * client sends it to the service, the message is answered by a
76 * #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE (which is just
77 * in a `struct GNUNET_MessageHeader`.
78 */
79struct RevokeMessage
80{
81 /**
82 * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE
83 */
84 struct GNUNET_MessageHeader header;
85
86 /**
87 * Length of PoW with signature.
88 */
89 uint32_t pow_size GNUNET_PACKED;
90
91 /** Followed by the PoW **/
92};
93
94
95/**
96 * Key revocation response.
97 */
98struct RevocationResponseMessage
99{
100 /**
101 * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE
102 */
103 struct GNUNET_MessageHeader header;
104
105 /**
106 * #GNUNET_NO if revocation failed for internal reasons (e.g. disk full)
107 * #GNUNET_YES on success
108 */
109 uint32_t is_valid GNUNET_PACKED;
110};
111
112
113GNUNET_NETWORK_STRUCT_END
114
115/**
116 * Create the revocation metadata to sign for a revocation message
117 *
118 * @param pow the PoW to sign
119 * @return the signature purpose
120 */
121struct GNUNET_REVOCATION_SignaturePurposePS *
122REV_create_signature_message (const struct GNUNET_REVOCATION_PowP *pow);
123
124#endif
diff --git a/src/revocation/revocation_api.c b/src/revocation/revocation_api.c
deleted file mode 100644
index 3b7d83710..000000000
--- a/src/revocation/revocation_api.c
+++ /dev/null
@@ -1,764 +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_CRYPTO_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 size_t key_len;
179
180 q->mq = GNUNET_CLIENT_connect (cfg,
181 "revocation",
182 handlers,
183 &query_mq_error_handler,
184 q);
185 if (NULL == q->mq)
186 {
187 GNUNET_free (q);
188 return NULL;
189 }
190 q->func = func;
191 q->func_cls = func_cls;
192 key_len = GNUNET_CRYPTO_public_key_get_length (key);
193 env = GNUNET_MQ_msg_extra (qm, key_len,
194 GNUNET_MESSAGE_TYPE_REVOCATION_QUERY);
195 GNUNET_CRYPTO_write_public_key_to_buffer (key, &qm[1], key_len);
196 qm->key_len = htonl (key_len);
197 GNUNET_MQ_send (q->mq,
198 env);
199 return q;
200}
201
202
203/**
204 * Cancel key revocation check.
205 *
206 * @param q query to cancel
207 */
208void
209GNUNET_REVOCATION_query_cancel (struct GNUNET_REVOCATION_Query *q)
210{
211 if (NULL != q->mq)
212 {
213 GNUNET_MQ_destroy (q->mq);
214 q->mq = NULL;
215 }
216 GNUNET_free (q);
217}
218
219
220/**
221 * Handle for the key revocation operation.
222 */
223struct GNUNET_REVOCATION_Handle
224{
225 /**
226 * Message queue to the service.
227 */
228 struct GNUNET_MQ_Handle *mq;
229
230 /**
231 * Function to call once we are done.
232 */
233 GNUNET_REVOCATION_Callback func;
234
235 /**
236 * Closure for @e func.
237 */
238 void *func_cls;
239};
240
241
242/**
243 * Generic error handler, called with the appropriate
244 * error code and the same closure specified at the creation of
245 * the message queue.
246 * Not every message queue implementation supports an error handler.
247 *
248 * @param cls closure with the `struct GNUNET_NSE_Handle *`
249 * @param error error code
250 */
251static void
252revocation_mq_error_handler (void *cls,
253 enum GNUNET_MQ_Error error)
254{
255 struct GNUNET_REVOCATION_Handle *h = cls;
256
257 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
258 "Revocation MQ error\n");
259 h->func (h->func_cls,
260 GNUNET_SYSERR);
261 GNUNET_REVOCATION_revoke_cancel (h);
262}
263
264
265/**
266 * Handle response to our revocation query.
267 *
268 * @param cls our `struct GNUNET_REVOCATION_Handle` handle
269 * @param rrm response we got
270 */
271static void
272handle_revocation_response (void *cls,
273 const struct RevocationResponseMessage *rrm)
274{
275 struct GNUNET_REVOCATION_Handle *h = cls;
276
277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
278 "Revocation transmission result: %d\n",
279 (uint32_t) ntohl (rrm->is_valid));
280 h->func (h->func_cls,
281 ntohl (rrm->is_valid));
282 GNUNET_REVOCATION_revoke_cancel (h);
283}
284
285
286/**
287 * Perform key revocation.
288 *
289 * @param cfg the configuration to use
290 * @param key public key of the key to revoke
291 * @param sig signature to use on the revocation (should have been
292 * created using #GNUNET_REVOCATION_sign_revocation).
293 * @param ts revocation timestamp
294 * @param pow proof of work to use (should have been created by
295 * iteratively calling #GNUNET_REVOCATION_check_pow)
296 * @param func function to call with the result of the check
297 * (called with `is_valid` being #GNUNET_NO if
298 * the revocation worked).
299 * @param func_cls closure to pass to @a func
300 * @return handle to use in #GNUNET_REVOCATION_revoke_cancel to stop REVOCATION from invoking the callback
301 */
302struct GNUNET_REVOCATION_Handle *
303GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg,
304 const struct GNUNET_REVOCATION_PowP *pow,
305 GNUNET_REVOCATION_Callback func,
306 void *func_cls)
307{
308 struct GNUNET_REVOCATION_Handle *h
309 = GNUNET_new (struct GNUNET_REVOCATION_Handle);
310 struct GNUNET_MQ_MessageHandler handlers[] = {
311 GNUNET_MQ_hd_fixed_size (revocation_response,
312 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE,
313 struct RevocationResponseMessage,
314 h),
315 GNUNET_MQ_handler_end ()
316 };
317 unsigned long long matching_bits;
318 struct GNUNET_TIME_Relative epoch_duration;
319 struct RevokeMessage *rm;
320 struct GNUNET_MQ_Envelope *env;
321
322 if ((GNUNET_OK !=
323 GNUNET_CONFIGURATION_get_value_number (cfg,
324 "REVOCATION",
325 "WORKBITS",
326 &matching_bits)))
327 {
328 GNUNET_break (0);
329 GNUNET_free (h);
330 return NULL;
331 }
332 if ((GNUNET_OK !=
333 GNUNET_CONFIGURATION_get_value_time (cfg,
334 "REVOCATION",
335 "EPOCH_DURATION",
336 &epoch_duration)))
337 {
338 GNUNET_break (0);
339 GNUNET_free (h);
340 return NULL;
341 }
342 if (GNUNET_YES != GNUNET_REVOCATION_check_pow (pow,
343 (unsigned int) matching_bits,
344 epoch_duration))
345 {
346 GNUNET_break (0);
347 GNUNET_free (h);
348 return NULL;
349 }
350
351
352 h->mq = GNUNET_CLIENT_connect (cfg,
353 "revocation",
354 handlers,
355 &revocation_mq_error_handler,
356 h);
357 if (NULL == h->mq)
358 {
359 GNUNET_free (h);
360 return NULL;
361 }
362 h->func = func;
363 h->func_cls = func_cls;
364 size_t extra_len = GNUNET_REVOCATION_proof_get_size (pow);
365 env = GNUNET_MQ_msg_extra (rm,
366 extra_len,
367 GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE);
368 rm->pow_size = htonl (extra_len);
369 memcpy (&rm[1], pow, extra_len);
370 GNUNET_MQ_send (h->mq,
371 env);
372 return h;
373}
374
375
376void
377GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h)
378{
379 if (NULL != h->mq)
380 {
381 GNUNET_MQ_destroy (h->mq);
382 h->mq = NULL;
383 }
384 GNUNET_free (h);
385}
386
387
388/**
389 * Calculate the average zeros in the pows.
390 *
391 * @param ph the PowHandle
392 * @return the average number of zeros.
393 */
394static unsigned int
395calculate_score (const struct GNUNET_REVOCATION_PowCalculationHandle *ph)
396{
397 double sum = 0.0;
398 for (unsigned int j = 0; j<POW_COUNT; j++)
399 sum += ph->best[j].bits;
400 double avg = sum / POW_COUNT;
401 return avg;
402}
403
404
405struct GNUNET_REVOCATION_SignaturePurposePS *
406REV_create_signature_message (const struct GNUNET_REVOCATION_PowP *pow)
407{
408 struct GNUNET_REVOCATION_SignaturePurposePS *spurp;
409 const struct GNUNET_CRYPTO_PublicKey *pk;
410 size_t ksize;
411
412 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
413 ksize = GNUNET_CRYPTO_public_key_get_length (pk);
414 spurp = GNUNET_malloc (sizeof (*spurp) + ksize);
415 spurp->timestamp = pow->timestamp;
416 spurp->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_REVOCATION);
417 spurp->purpose.size = htonl (sizeof(*spurp) + ksize);
418 GNUNET_CRYPTO_write_public_key_to_buffer (pk,
419 (char*) &spurp[1],
420 ksize);
421 return spurp;
422}
423
424
425enum GNUNET_GenericReturnValue
426check_signature_identity (const struct GNUNET_REVOCATION_PowP *pow,
427 const struct GNUNET_CRYPTO_PublicKey *key)
428{
429 struct GNUNET_REVOCATION_SignaturePurposePS *spurp;
430 unsigned char *sig;
431 size_t ksize;
432 int ret;
433
434 ksize = GNUNET_CRYPTO_public_key_get_length (key);
435 spurp = REV_create_signature_message (pow);
436 sig = ((unsigned char*) &pow[1] + ksize);
437 ret =
438 GNUNET_CRYPTO_signature_verify_raw_ (
439 GNUNET_SIGNATURE_PURPOSE_GNS_REVOCATION,
440 &spurp->purpose,
441 sig,
442 key);
443 GNUNET_free (spurp);
444 return ret == GNUNET_OK ? GNUNET_OK : GNUNET_SYSERR;
445}
446
447
448enum GNUNET_GenericReturnValue
449check_signature (const struct GNUNET_REVOCATION_PowP *pow)
450{
451 const struct GNUNET_CRYPTO_PublicKey *pk;
452
453 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
454 return check_signature_identity (pow, pk);
455}
456
457
458/**
459 * Check if the given proof-of-work is valid.
460 *
461 * @param pow proof of work
462 * @param difficulty how many bits must match (configuration) LSD0001: D
463 * @param epoch_duration length of single epoch in configuration
464 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
465 */
466enum GNUNET_GenericReturnValue
467GNUNET_REVOCATION_check_pow (const struct GNUNET_REVOCATION_PowP *pow,
468 unsigned int difficulty,
469 struct GNUNET_TIME_Relative epoch_duration)
470{
471 char buf[sizeof(struct GNUNET_CRYPTO_PublicKey)
472 + sizeof (struct GNUNET_TIME_AbsoluteNBO)
473 + sizeof (uint64_t)] GNUNET_ALIGN;
474 struct GNUNET_HashCode result;
475 struct GNUNET_TIME_Absolute ts;
476 struct GNUNET_TIME_Absolute exp;
477 struct GNUNET_TIME_Relative ttl;
478 struct GNUNET_TIME_Relative buffer;
479 /* LSD0001: D' */
480 unsigned int score = 0;
481 unsigned int tmp_score = 0;
482 unsigned int epochs;
483 uint64_t pow_val;
484 ssize_t pklen;
485 const struct GNUNET_CRYPTO_PublicKey *pk;
486
487 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
488
489 /**
490 * Check if signature valid
491 */
492 if (GNUNET_OK != check_signature (pow))
493 {
494 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
495 "Proof of work signature invalid!\n");
496 return GNUNET_SYSERR;
497 }
498
499 /**
500 * First, check if PoW set is strictly monotically increasing
501 */
502 for (unsigned int i = 0; i < POW_COUNT - 1; i++)
503 {
504 if (GNUNET_ntohll (pow->pow[i]) >= GNUNET_ntohll (pow->pow[i + 1]))
505 return GNUNET_NO;
506 }
507 GNUNET_memcpy (&buf[sizeof(uint64_t)],
508 &pow->timestamp,
509 sizeof (uint64_t));
510 pklen = GNUNET_CRYPTO_public_key_get_length (pk);
511 if (0 > pklen)
512 {
513 GNUNET_break (0);
514 return GNUNET_NO;
515 }
516 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
517 pk,
518 pklen);
519 for (unsigned int i = 0; i < POW_COUNT; i++)
520 {
521 pow_val = GNUNET_ntohll (pow->pow[i]);
522 GNUNET_memcpy (buf, &pow->pow[i], sizeof(uint64_t));
523 GNUNET_CRYPTO_pow_hash (&salt,
524 buf,
525 sizeof(buf),
526 &result);
527 tmp_score = GNUNET_CRYPTO_hash_count_leading_zeros (&result);
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Score %u with %" PRIu64 " (#%u)\n",
530 tmp_score, pow_val, i);
531
532 score += tmp_score;
533
534 }
535 score = score / POW_COUNT;
536 if (score < difficulty)
537 return GNUNET_NO;
538 /* LSD0001: (D'-D+1) */
539 epochs = score - difficulty + 1;
540
541 /**
542 * Check expiration
543 */
544 ts = GNUNET_TIME_absolute_ntoh (pow->timestamp);
545 ttl = GNUNET_TIME_relative_multiply (epoch_duration,
546 epochs);
547 /**
548 * Extend by 10% for unsynchronized clocks
549 */
550 buffer = GNUNET_TIME_relative_divide (epoch_duration,
551 10);
552 exp = GNUNET_TIME_absolute_add (ts, ttl);
553 exp = GNUNET_TIME_absolute_add (exp,
554 buffer);
555
556 if (0 != GNUNET_TIME_absolute_get_remaining (ts).rel_value_us)
557 return GNUNET_NO; /* Not yet valid. */
558 /* Revert to actual start time */
559 ts = GNUNET_TIME_absolute_add (ts,
560 buffer);
561
562 if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us)
563 return GNUNET_NO; /* expired */
564 return GNUNET_YES;
565}
566
567
568enum GNUNET_GenericReturnValue
569sign_pow_identity (const struct GNUNET_CRYPTO_PrivateKey *key,
570 struct GNUNET_REVOCATION_PowP *pow)
571{
572 struct GNUNET_TIME_Absolute ts = GNUNET_TIME_absolute_get ();
573 struct GNUNET_REVOCATION_SignaturePurposePS *rp;
574 const struct GNUNET_CRYPTO_PublicKey *pk;
575 size_t ksize;
576 char *sig;
577
578 /**
579 * Predate the validity period to prevent rejections due to
580 * unsynchronized clocks
581 */
582 ts = GNUNET_TIME_absolute_subtract (ts,
583 GNUNET_TIME_UNIT_WEEKS);
584 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
585 ksize = GNUNET_CRYPTO_public_key_get_length (pk);
586 pow->timestamp = GNUNET_TIME_absolute_hton (ts);
587 rp = REV_create_signature_message (pow);
588 sig = ((char*) &pow[1]) + ksize;
589 int result = GNUNET_CRYPTO_sign_raw_ (key,
590 &rp->purpose,
591 (void*) sig);
592 GNUNET_free (rp);
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_CRYPTO_PrivateKey *key,
602 struct GNUNET_REVOCATION_PowP *pow)
603{
604 struct GNUNET_CRYPTO_PublicKey *pk;
605
606 pk = (struct GNUNET_CRYPTO_PublicKey *) &pow[1];
607 GNUNET_CRYPTO_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_CRYPTO_PrivateKey *key,
620 struct GNUNET_REVOCATION_PowP *pow)
621{
622 GNUNET_assert (GNUNET_OK == sign_pow (key, pow));
623}
624
625
626struct GNUNET_REVOCATION_PowCalculationHandle*
627GNUNET_REVOCATION_pow_start (struct GNUNET_REVOCATION_PowP *pow,
628 int epochs,
629 unsigned int difficulty)
630{
631 struct GNUNET_REVOCATION_PowCalculationHandle *pc;
632 struct GNUNET_TIME_Relative ttl;
633
634
635 pc = GNUNET_new (struct GNUNET_REVOCATION_PowCalculationHandle);
636 pc->pow = pow;
637 ttl = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
638 epochs);
639 pc->pow->ttl = GNUNET_TIME_relative_hton (ttl);
640 pc->current_pow = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
641 UINT64_MAX);
642 pc->difficulty = difficulty;
643 pc->epochs = epochs;
644 return pc;
645}
646
647
648/**
649 * Comparison function for quicksort
650 *
651 * @param a left element
652 * @param b right element
653 * @return a-b
654 */
655static int
656cmp_pow_value (const void *a, const void *b)
657{
658 return (GNUNET_ntohll (*(uint64_t*) a) - GNUNET_ntohll (*(uint64_t*) b));
659}
660
661
662/**
663 * Calculate a key revocation valid for broadcasting for a number
664 * of epochs.
665 *
666 * @param pc handle to the PoW, initially called with NULL.
667 * @param epochs number of epochs for which the revocation must be valid.
668 * @param pow current pow value to try
669 * @param difficulty current base difficulty to achieve
670 * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not
671 */
672enum GNUNET_GenericReturnValue
673GNUNET_REVOCATION_pow_round (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
674{
675 char buf[sizeof(struct GNUNET_CRYPTO_PublicKey)
676 + sizeof (uint64_t)
677 + sizeof (uint64_t)] GNUNET_ALIGN;
678 struct GNUNET_HashCode result;
679 const struct GNUNET_CRYPTO_PublicKey *pk;
680 unsigned int zeros;
681 int ret;
682 uint64_t pow_nbo;
683 ssize_t ksize;
684
685 pc->current_pow++;
686 pk = (const struct GNUNET_CRYPTO_PublicKey *) &(pc->pow[1]);
687
688 /**
689 * Do not try duplicates
690 */
691 for (unsigned int i = 0; i < POW_COUNT; i++)
692 if (pc->current_pow == pc->best[i].pow)
693 return GNUNET_NO;
694 pow_nbo = GNUNET_htonll (pc->current_pow);
695 GNUNET_memcpy (buf, &pow_nbo, sizeof(uint64_t));
696 GNUNET_memcpy (&buf[sizeof(uint64_t)],
697 &pc->pow->timestamp,
698 sizeof (uint64_t));
699 ksize = GNUNET_CRYPTO_public_key_get_length (pk);
700 GNUNET_assert (0 < ksize);
701 GNUNET_memcpy (&buf[sizeof(uint64_t) * 2],
702 pk,
703 ksize);
704 GNUNET_CRYPTO_pow_hash (&salt,
705 buf,
706 sizeof(buf),
707 &result);
708 zeros = GNUNET_CRYPTO_hash_count_leading_zeros (&result);
709 for (unsigned int i = 0; i < POW_COUNT; i++)
710 {
711 if (pc->best[i].bits < zeros)
712 {
713 pc->best[i].bits = zeros;
714 pc->best[i].pow = pc->current_pow;
715 pc->pow->pow[i] = pow_nbo;
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
717 "New best score %u with %" PRIu64 " (#%u)\n",
718 zeros, pc->current_pow, i);
719
720 break;
721 }
722 }
723 ret = calculate_score (pc) >= pc->difficulty + pc->epochs ? GNUNET_YES :
724 GNUNET_NO;
725 if (GNUNET_YES == ret)
726 {
727 /* Sort POWs) */
728 qsort (pc->pow->pow, POW_COUNT, sizeof (uint64_t), &cmp_pow_value);
729 }
730 return ret;
731}
732
733
734/**
735 * Stop a PoW calculation
736 *
737 * @param pc the calculation to clean up
738 * @return #GNUNET_YES if pow valid, #GNUNET_NO if pow was set but is not
739 * valid
740 */
741void
742GNUNET_REVOCATION_pow_stop (struct GNUNET_REVOCATION_PowCalculationHandle *pc)
743{
744 GNUNET_free (pc);
745}
746
747
748size_t
749GNUNET_REVOCATION_proof_get_size (const struct GNUNET_REVOCATION_PowP *pow)
750{
751 size_t size;
752 size_t ksize;
753 const struct GNUNET_CRYPTO_PublicKey *pk;
754
755 size = sizeof (struct GNUNET_REVOCATION_PowP);
756 pk = (const struct GNUNET_CRYPTO_PublicKey *) &pow[1];
757 ksize = GNUNET_CRYPTO_public_key_get_length (pk);
758 size += ksize;
759 size += GNUNET_CRYPTO_signature_get_raw_length_by_type (pk->type);
760 return size;
761}
762
763
764/* 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 0fc3ac7e5..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_CRYPTO_PrivateKey *privkey;
42 struct GNUNET_CRYPTO_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_CRYPTO_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_CRYPTO_PrivateKey *pk,
198 enum GNUNET_ErrorCode ec)
199{
200 static int completed = 0;
201
202 if ((GNUNET_EC_NONE == ec) && (cls == &testpeers[0]))
203 {
204 testpeers[0].create_id_op = NULL;
205 completed++;
206 }
207 if ((GNUNET_EC_NONE == ec) && (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_PUBLIC_KEY_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_PUBLIC_KEY_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
diff --git a/src/revocation/test_revocation_testvectors.c b/src/revocation/test_revocation_testvectors.c
deleted file mode 100644
index a669e1b7e..000000000
--- a/src/revocation/test_revocation_testvectors.c
+++ /dev/null
@@ -1,297 +0,0 @@
1#include "platform.h"
2#include "gnunet_util_lib.h"
3#include "gnunet_revocation_service.h"
4#include "gnunet_gnsrecord_lib.h"
5#include <inttypes.h>
6
7int res;
8
9struct RevocationTv
10{
11 char *d;
12 char *zid;
13 char *ztld;
14 char *m;
15 char *proof;
16 int diff;
17 int epochs;
18};
19
20struct RevocationTv rtvs[] = {
21 {
22 .d =
23 "6f ea 32 c0 5a f5 8b fa"
24 "97 95 53 d1 88 60 5f d5"
25 "7d 8b f9 cc 26 3b 78 d5"
26 "f7 47 8c 07 b9 98 ed 70",
27 .zid =
28 "00 01 00 00 2c a2 23 e8"
29 "79 ec c4 bb de b5 da 17"
30 "31 92 81 d6 3b 2e 3b 69"
31 "55 f1 c3 77 5c 80 4a 98"
32 "d5 f8 dd aa",
33 .ztld =
34 "000G001CM8HYGYFCRJXXXDET2WRS50EP7CQ3PTANY71QEQ409ACDBY6XN8",
35 .m =
36 "00 00 00 34 00 00 00 03"
37 "00 05 fe b4 6d 86 5c 1c"
38 "00 01 00 00 2c a2 23 e8"
39 "79 ec c4 bb de b5 da 17"
40 "31 92 81 d6 3b 2e 3b 69"
41 "55 f1 c3 77 5c 80 4a 98"
42 "d5 f8 dd aa",
43 .proof =
44 "00 05 ff 1c 56 e4 b2 68"
45 "00 00 39 5d 18 27 c0 00"
46 "38 0b 54 aa 70 16 ac a2"
47 "38 0b 54 aa 70 16 ad 62"
48 "38 0b 54 aa 70 16 af 3e"
49 "38 0b 54 aa 70 16 af 93"
50 "38 0b 54 aa 70 16 b0 bf"
51 "38 0b 54 aa 70 16 b0 ee"
52 "38 0b 54 aa 70 16 b1 c9"
53 "38 0b 54 aa 70 16 b1 e5"
54 "38 0b 54 aa 70 16 b2 78"
55 "38 0b 54 aa 70 16 b2 b2"
56 "38 0b 54 aa 70 16 b2 d6"
57 "38 0b 54 aa 70 16 b2 e4"
58 "38 0b 54 aa 70 16 b3 2c"
59 "38 0b 54 aa 70 16 b3 5a"
60 "38 0b 54 aa 70 16 b3 9d"
61 "38 0b 54 aa 70 16 b3 c0"
62 "38 0b 54 aa 70 16 b3 dd"
63 "38 0b 54 aa 70 16 b3 f4"
64 "38 0b 54 aa 70 16 b4 42"
65 "38 0b 54 aa 70 16 b4 76"
66 "38 0b 54 aa 70 16 b4 8c"
67 "38 0b 54 aa 70 16 b4 a4"
68 "38 0b 54 aa 70 16 b4 c9"
69 "38 0b 54 aa 70 16 b4 f0"
70 "38 0b 54 aa 70 16 b4 f7"
71 "38 0b 54 aa 70 16 b5 79"
72 "38 0b 54 aa 70 16 b6 34"
73 "38 0b 54 aa 70 16 b6 8e"
74 "38 0b 54 aa 70 16 b7 b4"
75 "38 0b 54 aa 70 16 b8 7e"
76 "38 0b 54 aa 70 16 b8 f8"
77 "38 0b 54 aa 70 16 b9 2a"
78 "00 01 00 00 2c a2 23 e8"
79 "79 ec c4 bb de b5 da 17"
80 "31 92 81 d6 3b 2e 3b 69"
81 "55 f1 c3 77 5c 80 4a 98"
82 "d5 f8 dd aa 08 ca ff de"
83 "3c 6d f1 45 f7 e0 79 81"
84 "15 37 b2 b0 42 2d 5e 1f"
85 "b2 01 97 81 ec a2 61 d1"
86 "f9 d8 ea 81 0a bc 2f 33"
87 "47 7f 04 e3 64 81 11 be"
88 "71 c2 48 82 1a d6 04 f4"
89 "94 e7 4d 0b f5 11 d2 c1"
90 "62 77 2e 81",
91 .diff = 5,
92 .epochs = 2
93 },
94 {
95 .d =
96 "5a f7 02 0e e1 91 60 32"
97 "88 32 35 2b bc 6a 68 a8"
98 "d7 1a 7c be 1b 92 99 69"
99 "a7 c6 6d 41 5a 0d 8f 65",
100 .zid =
101 "00 01 00 14 3c f4 b9 24"
102 "03 20 22 f0 dc 50 58 14"
103 "53 b8 5d 93 b0 47 b6 3d"
104 "44 6c 58 45 cb 48 44 5d"
105 "db 96 68 8f",
106 .ztld =
107 "000G051WYJWJ80S04BRDRM2R2H9VGQCKP13VCFA4DHC4BJT88HEXQ5K8HW",
108 .diff = 5,
109 .epochs = 2,
110 .m =
111 "00 00 00 34 00 00 00 03"
112 "00 05 ff 1c 57 35 42 bd"
113 "00 01 00 14 3c f4 b9 24"
114 "03 20 22 f0 dc 50 58 14"
115 "53 b8 5d 93 b0 47 b6 3d"
116 "44 6c 58 45 cb 48 44 5d"
117 "db 96 68 8f",
118 .proof =
119 "00 05 ff 1c 57 35 42 bd"
120 "00 00 39 5d 18 27 c0 00"
121 "58 4c 93 3c b0 99 2a 08"
122 "58 4c 93 3c b0 99 2d f7"
123 "58 4c 93 3c b0 99 2e 21"
124 "58 4c 93 3c b0 99 2e 2a"
125 "58 4c 93 3c b0 99 2e 53"
126 "58 4c 93 3c b0 99 2e 8e"
127 "58 4c 93 3c b0 99 2f 13"
128 "58 4c 93 3c b0 99 2f 2d"
129 "58 4c 93 3c b0 99 2f 3c"
130 "58 4c 93 3c b0 99 2f 41"
131 "58 4c 93 3c b0 99 2f fd"
132 "58 4c 93 3c b0 99 30 33"
133 "58 4c 93 3c b0 99 30 82"
134 "58 4c 93 3c b0 99 30 a2"
135 "58 4c 93 3c b0 99 30 e1"
136 "58 4c 93 3c b0 99 31 ce"
137 "58 4c 93 3c b0 99 31 de"
138 "58 4c 93 3c b0 99 32 12"
139 "58 4c 93 3c b0 99 32 4e"
140 "58 4c 93 3c b0 99 32 9f"
141 "58 4c 93 3c b0 99 33 31"
142 "58 4c 93 3c b0 99 33 87"
143 "58 4c 93 3c b0 99 33 8c"
144 "58 4c 93 3c b0 99 33 e5"
145 "58 4c 93 3c b0 99 33 f3"
146 "58 4c 93 3c b0 99 34 26"
147 "58 4c 93 3c b0 99 34 30"
148 "58 4c 93 3c b0 99 34 68"
149 "58 4c 93 3c b0 99 34 88"
150 "58 4c 93 3c b0 99 34 8a"
151 "58 4c 93 3c b0 99 35 4c"
152 "58 4c 93 3c b0 99 35 bd"
153 "00 01 00 14 3c f4 b9 24"
154 "03 20 22 f0 dc 50 58 14"
155 "53 b8 5d 93 b0 47 b6 3d"
156 "44 6c 58 45 cb 48 44 5d"
157 "db 96 68 8f 04 ae 26 f7"
158 "63 56 5a b7 aa ab 01 71"
159 "72 4f 3c a8 bc c5 1a 98"
160 "b7 d4 c9 2e a3 3c d9 34"
161 "4c a8 b6 3e 04 53 3a bf"
162 "1a 3c 05 49 16 b3 68 2c"
163 "5c a8 cb 4d d0 f8 4c 3b"
164 "77 48 7a ac 6e ce 38 48"
165 "0b a9 d5 00"
166 },
167 { .d = NULL }
168};
169
170static void
171print_bytes_ (void *buf,
172 size_t buf_len,
173 int fold,
174 int in_be)
175{
176 int i;
177
178 for (i = 0; i < buf_len; i++)
179 {
180 if (0 != i)
181 {
182 if ((0 != fold) && (i % fold == 0))
183 printf ("\n ");
184 else
185 printf (" ");
186 }
187 else
188 {
189 printf (" ");
190 }
191 if (in_be)
192 printf ("%02x", ((unsigned char*) buf)[buf_len - 1 - i]);
193 else
194 printf ("%02x", ((unsigned char*) buf)[i]);
195 }
196 printf ("\n");
197}
198
199
200static void
201print_bytes (void *buf,
202 size_t buf_len,
203 int fold)
204{
205 print_bytes_ (buf, buf_len, fold, 0);
206}
207
208
209int
210parsehex (char *src, char *dst, size_t dstlen, int invert)
211{
212 int off;
213 int read_byte;
214 int data_len = 0;
215 char data[strlen (src) + 1];
216 char *pos = data;
217 int i = 0;
218 int j = 0;
219
220 for (i = 0; i < strlen (src); i++)
221 {
222 if ((src[i] == ' ') || (src[i] == '\n'))
223 continue;
224 data[j++] = src[i];
225 }
226
227 while (sscanf (pos, " %02x%n", &read_byte, &off) == 1)
228 {
229 if (invert)
230 dst[dstlen - 1 - data_len++] = read_byte;
231 else
232 dst[data_len++] = read_byte;
233 pos += off;
234 }
235 return data_len;
236}
237
238
239int
240main ()
241{
242 struct GNUNET_CRYPTO_PrivateKey priv;
243 struct GNUNET_CRYPTO_PublicKey pub;
244 struct GNUNET_CRYPTO_PublicKey pub_parsed;
245 struct GNUNET_TIME_Relative exprel;
246 struct GNUNET_REVOCATION_PowP *pow;
247 char m[8096];
248 char ztld[128];
249 res = 0;
250
251 for (int i = 0; NULL != rtvs[i].d; i++)
252 {
253 printf ("Revocation test vector #%d\n", i);
254 parsehex (rtvs[i].zid,(char*) &pub_parsed, 36, 0);
255 parsehex (rtvs[i].d,(char*) &priv.ecdsa_key, sizeof (priv.ecdsa_key),
256 (GNUNET_GNSRECORD_TYPE_PKEY == ntohl (pub_parsed.type)) ? 1 : 0);
257 priv.type = pub_parsed.type;
258 GNUNET_CRYPTO_key_get_public (&priv, &pub);
259 if (0 != memcmp (&pub, &pub_parsed, GNUNET_CRYPTO_public_key_get_length (
260 &pub)))
261 {
262 printf ("Wrong pubkey.\n");
263 print_bytes (&pub, 36, 8);
264 print_bytes (&pub_parsed, 36, 8);
265 res = 1;
266 break;
267 }
268 GNUNET_STRINGS_data_to_string (&pub,
269 GNUNET_CRYPTO_public_key_get_length (
270 &pub),
271 ztld,
272 sizeof (ztld));
273 if (0 != strcmp (ztld, rtvs[i].ztld))
274 {
275 printf ("Wrong zTLD: expected %s, got %s\n", rtvs[i].ztld, ztld);
276 res = 1;
277 break;
278 }
279 pow = GNUNET_malloc (GNUNET_REVOCATION_MAX_PROOF_SIZE);
280 parsehex (rtvs[i].proof, (char*) pow, 0, 0);
281 // parsehex (rtvs[i].m, (char*) message, 0, 0);
282
283 exprel = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
284 rtvs[i].epochs);
285 if (GNUNET_OK != GNUNET_REVOCATION_check_pow (pow, rtvs[i].diff,
286 exprel))
287 {
288 printf ("FAIL: Revocation PoW invalid\n");
289 res = 1;
290 break;
291 }
292 printf ("Good.\n");
293 }
294
295finish:
296 return res;
297}