aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--configure.ac34
-rw-r--r--src/Makefile.am6
-rw-r--r--src/escrow/.gitignore1
-rw-r--r--src/escrow/Makefile.am113
-rw-r--r--src/escrow/escrow.h244
-rw-r--r--src/escrow/escrow_api.c478
-rw-r--r--src/escrow/escrow_plugin_helper.c361
-rw-r--r--src/escrow/escrow_plugin_helper.h108
-rw-r--r--src/escrow/gnunet-escrow.c535
-rw-r--r--src/escrow/plugin_escrow_anastasis.c274
-rw-r--r--src/escrow/plugin_escrow_gns.c1449
-rw-r--r--src/escrow/plugin_escrow_plaintext.c584
-rw-r--r--src/escrow/plugin_gnsrecord_escrow.c173
-rwxr-xr-xsrc/escrow/test_gns_escrow.sh47
-rwxr-xr-xsrc/escrow/test_plaintext_escrow.sh47
-rw-r--r--src/include/gnunet_crypto_lib.h17
-rw-r--r--src/include/gnunet_escrow_lib.h417
-rw-r--r--src/include/gnunet_escrow_plugin.h210
-rw-r--r--src/include/gnunet_gnsrecord_lib.h5
-rw-r--r--src/include/gnunet_reclaim_plugin.h1
-rw-r--r--src/util/crypto_ecc.c35
22 files changed, 5140 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index b337cc058..90c692de8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,3 +72,7 @@ cmake/
72build 72build
73CMakeLists.txt 73CMakeLists.txt
74CMakeFiles.txt 74CMakeFiles.txt
75
76.vscode/settings.json
77src/gnsrecord/gnunet-gnsrecord-tvg
78src/revocation/gnunet-revocation-tvg
diff --git a/configure.ac b/configure.ac
index e492242a6..4dacfa8ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -790,6 +790,34 @@ AC_ARG_WITH(jansson,
790AS_IF([test "x$jansson" != x1], 790AS_IF([test "x$jansson" != x1],
791 [AC_MSG_ERROR([GNUnet requires libjansson])]) 791 [AC_MSG_ERROR([GNUnet requires libjansson])])
792 792
793# check for sss (Shamir Secret Sharing) library
794sss=0
795AC_MSG_CHECKING(for sss)
796AC_ARG_WITH(sss,
797 [ --with-sss=PREFIX (base of sss installation)],
798 [AC_MSG_RESULT([$with_sss])
799 AS_CASE([$with_sss],
800 [no],[],
801 [yes],[
802 CHECK_LIBHEADER(SSS, sss, sss_create_shares, sss.h, sss=1,)
803 ],[
804 LDFLAGS="-L$with_sss/lib $LDFLAGS"
805 CPPFLAGS="-I$with_sss/include $CPPFLAGS"
806 AC_CHECK_HEADERS(sss.h,
807 AC_CHECK_LIB([sss], [sss_create_shares],
808 EXT_LIB_PATH="-L$with_sss/lib $EXT_LIB_PATH"
809 sss=1))
810 ])
811 ],
812 [AC_MSG_RESULT([--with-sss not specified])
813 CHECK_LIBHEADER(SSS, sss, sss_create_shares, sss.h,sss=1,)])
814AM_CONDITIONAL(HAVE_SSS, [test "$sss" = 1])
815AS_IF([test "$sss" = 1],
816 [AC_DEFINE([HAVE_SSS],[1],[Have sss library])
817 sss_msg="yes"],
818 [AC_DEFINE([HAVE_SSS],[0],[Lacking sss library])
819 sss_msg="no"])
820
793# check for libpulse(audio) library 821# check for libpulse(audio) library
794pulse=0 822pulse=0
795libpulse_msg="no" 823libpulse_msg="no"
@@ -1958,6 +1986,7 @@ src/zonemaster/zonemaster.conf
1958src/rest/Makefile 1986src/rest/Makefile
1959src/abe/Makefile 1987src/abe/Makefile
1960src/reclaim/Makefile 1988src/reclaim/Makefile
1989src/escrow/Makefile
1961pkgconfig/Makefile 1990pkgconfig/Makefile
1962pkgconfig/gnunetarm.pc 1991pkgconfig/gnunetarm.pc
1963pkgconfig/gnunetats.pc 1992pkgconfig/gnunetats.pc
@@ -2059,6 +2088,10 @@ AS_IF([test "x$conversation_backend" = "xnone"],
2059# -- interface 2088# -- interface
2060interface_msg=`echo $DEFAULT_INTERFACE | tr -d \"` 2089interface_msg=`echo $DEFAULT_INTERFACE | tr -d \"`
2061# -- jansson 2090# -- jansson
2091# -- sss
2092AS_IF([test "$sss" != 1],
2093 [AC_MSG_WARN([sss library not found. GNS escrow plugin will not be compiled.])],
2094 [sss_msg="yes"])
2062# -- libextractor 2095# -- libextractor
2063AS_IF([test "$extractor" != 1], 2096AS_IF([test "$extractor" != 1],
2064 [AC_MSG_WARN([libextractor not found, but various file-sharing functions require it])], 2097 [AC_MSG_WARN([libextractor not found, but various file-sharing functions require it])],
@@ -2171,6 +2204,7 @@ libpulse: ${libpulse_msg}
2171libextractor: ${libextractor_msg} 2204libextractor: ${libextractor_msg}
2172texi2mdoc: ${texi2mdoc_msg} 2205texi2mdoc: ${texi2mdoc_msg}
2173mandoc: ${mandoc_msg} 2206mandoc: ${mandoc_msg}
2207sss: ${sss_msg}
2174 2208
2175GNUnet configuration: 2209GNUnet configuration:
2176===================== 2210=====================
diff --git a/src/Makefile.am b/src/Makefile.am
index 446b1aa2a..591d1c04f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,10 +9,14 @@ if HAVE_TESTING
9 ATS_TESTS = ats-tests 9 ATS_TESTS = ats-tests
10endif 10endif
11 11
12if HAVE_SSS
13 ESCROW_DIR = escrow
14endif
12if HAVE_EXPERIMENTAL 15if HAVE_EXPERIMENTAL
13 EXP_DIR = \ 16 EXP_DIR = \
14 rps \ 17 rps \
15 abd 18 abd \
19 $(ESCROW_DIR)
16if HAVE_ABE 20if HAVE_ABE
17 EXP_DIR += \ 21 EXP_DIR += \
18 abe 22 abe
diff --git a/src/escrow/.gitignore b/src/escrow/.gitignore
new file mode 100644
index 000000000..116fabf88
--- /dev/null
+++ b/src/escrow/.gitignore
@@ -0,0 +1 @@
gnunet-escrow \ No newline at end of file
diff --git a/src/escrow/Makefile.am b/src/escrow/Makefile.am
new file mode 100644
index 000000000..70dbfc2e9
--- /dev/null
+++ b/src/escrow/Makefile.am
@@ -0,0 +1,113 @@
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
11EXTRA_DIST = \
12 escrow.conf \
13 test_escrow.conf \
14 $(check_SCRIPTS)
15
16pkgcfgdir= $(pkgdatadir)/config.d/
17
18libexecdir= $(pkglibdir)/libexec/
19
20pkgcfg_DATA = \
21 escrow.conf
22
23lib_LTLIBRARIES = \
24 libgnunetescrow.la
25plugin_LTLIBRARIES = \
26 libgnunet_plugin_escrow_plaintext.la \
27 libgnunet_plugin_escrow_gns.la \
28 libgnunet_plugin_escrow_anastasis.la \
29 libgnunet_plugin_gnsrecord_escrow.la
30
31bin_PROGRAMS = \
32 gnunet-escrow
33
34libgnunetescrow_la_SOURCES = \
35 escrow_api.c \
36 escrow.h
37libgnunetescrow_la_LIBADD = \
38 $(top_builddir)/src/util/libgnunetutil.la \
39 $(GN_LIBINTL) $(XLIB)
40libgnunetescrow_la_LDFLAGS = \
41 $(GN_LIB_LDFLAGS) \
42 -version-info 0:0:0
43
44
45libgnunet_plugin_escrow_plaintext_la_SOURCES = \
46 plugin_escrow_plaintext.c \
47 escrow_plugin_helper.c \
48 escrow_plugin_helper.h
49libgnunet_plugin_escrow_plaintext_la_LIBADD = \
50 libgnunetescrow.la \
51 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
52 $(top_builddir)/src/identity/libgnunetidentity.la \
53 $(LTLIBINTL) $(MHD_LIBS)
54libgnunet_plugin_escrow_plaintext_la_LDFLAGS = \
55 $(GN_PLUGIN_LDFLAGS)
56
57libgnunet_plugin_escrow_gns_la_SOURCES = \
58 plugin_escrow_gns.c \
59 escrow_plugin_helper.c \
60 escrow_plugin_helper.h
61libgnunet_plugin_escrow_gns_la_LIBADD = \
62 libgnunetescrow.la \
63 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
64 $(top_builddir)/src/identity/libgnunetidentity.la \
65 $(top_builddir)/src/namestore/libgnunetnamestore.la \
66 $(top_builddir)/src/gns/libgnunetgns.la \
67 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
68 -lsss \
69 $(LTLIBINTL) $(MHD_LIBS)
70libgnunet_plugin_escrow_gns_la_LDFLAGS = \
71 $(GN_PLUGIN_LDFLAGS)
72
73libgnunet_plugin_escrow_anastasis_la_SOURCES = \
74 plugin_escrow_anastasis.c \
75 escrow_plugin_helper.c \
76 escrow_plugin_helper.h
77libgnunet_plugin_escrow_anastasis_la_LIBADD = \
78 libgnunetescrow.la \
79 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
80 $(top_builddir)/src/identity/libgnunetidentity.la \
81 $(LTLIBINTL) $(MHD_LIBS)
82libgnunet_plugin_escrow_anastasis_la_LDFLAGS = \
83 $(GN_PLUGIN_LDFLAGS)
84
85
86libgnunet_plugin_gnsrecord_escrow_la_SOURCES = \
87 plugin_gnsrecord_escrow.c
88libgnunet_plugin_gnsrecord_escrow_la_LIBADD = \
89 $(top_builddir)/src/util/libgnunetutil.la \
90 $(LTLIBINTL)
91libgnunet_plugin_gnsrecord_escrow_la_LDFLAGS = \
92 $(GN_PLUGIN_LDFLAGS)
93
94
95gnunet_escrow_SOURCES = \
96 gnunet-escrow.c
97gnunet_escrow_LDADD = \
98 libgnunetescrow.la \
99 $(top_builddir)/src/util/libgnunetutil.la \
100 $(top_builddir)/src/namestore/libgnunetnamestore.la \
101 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
102 $(top_builddir)/src/identity/libgnunetidentity.la \
103 $(GN_LIBINTL)
104
105check_SCRIPTS = \
106 test_plaintext_escrow.sh \
107 test_gns_escrow.sh
108 # test_anastasis_escrow.sh
109
110if ENABLE_TEST_RUN
111 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
112 TESTS = $(check_SCRIPTS)
113endif
diff --git a/src/escrow/escrow.h b/src/escrow/escrow.h
new file mode 100644
index 000000000..cf3660e03
--- /dev/null
+++ b/src/escrow/escrow.h
@@ -0,0 +1,244 @@
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 * @author Johannes Späth
23 * @file escrow/escrow.h
24 *
25 * @brief Common type definitions for the escrow component
26 */
27
28#ifndef ESCROW_H
29#define ESCROW_H
30
31#include "gnunet_escrow_lib.h"
32
33
34/**
35 * State while collecting all egos
36 */
37#define ESCROW_PLUGIN_STATE_INIT 0
38
39/**
40 * Done collecting egos
41 */
42#define ESCROW_PLUGIN_STATE_POST_INIT 1
43
44
45/**
46 * The ego list
47 */
48struct EgoEntry
49{
50 /**
51 * DLL
52 */
53 struct EgoEntry *next;
54
55 /**
56 * DLL
57 */
58 struct EgoEntry *prev;
59
60 /**
61 * Ego Identifier
62 */
63 char *identifier;
64
65 /**
66 * Public key string
67 */
68 char *keystring;
69
70 /**
71 * The Ego
72 */
73 struct GNUNET_IDENTITY_Ego *ego;
74};
75
76/**
77 * Handle for a plugin instance
78 */
79struct ESCROW_PluginHandle
80{
81 /**
82 * The identity init continuation.
83 */
84 GNUNET_ESCROW_IdentityInitContinuation id_init_cont;
85
86 /**
87 * The ego create continuation.
88 */
89 GNUNET_ESCROW_EgoCreateContinuation ego_create_cont;
90
91 /**
92 * The current restore callback.
93 */
94 GNUNET_ESCROW_EgoContinuation curr_restore_cb;
95
96 /**
97 * The handle to the escrow component.
98 */
99 struct GNUNET_ESCROW_Handle *escrow_handle;
100
101 /**
102 * The state of the plugin (in the initialization phase).
103 */
104 int state;
105
106 /**
107 * The head of the ego list.
108 */
109 struct EgoEntry *ego_head;
110
111 /**
112 * The tail of the ego list
113 */
114 struct EgoEntry *ego_tail;
115
116 /**
117 * The head of the plugin operation list
118 */
119 struct ESCROW_PluginOperationWrapper *plugin_op_head;
120
121 /**
122 * The tail of the plugin operation list
123 */
124 struct ESCROW_PluginOperationWrapper *plugin_op_tail;
125};
126
127/**
128 * Wrapper for an escrow plugin operation
129 */
130struct ESCROW_PluginOperationWrapper
131{
132 /**
133 * Plugin operations are kept in a DLL.
134 */
135 struct ESCROW_PluginOperationWrapper *prev;
136
137 /**
138 * Plugin operations are kept in a DLL.
139 */
140 struct ESCROW_PluginOperationWrapper *next;
141
142 /**
143 * The actual plugin operation
144 */
145 void *plugin_op;
146};
147
148
149/**
150 * Continuation for a plugin operation (e.g. used for restore, as this
151 * callback has to be called from the IDENTITY service after finishing)
152 */
153typedef void (*ESCROW_Plugin_Continuation) (void *cls);
154
155
156/**
157 * Wrapper for the Plugin_AnchorContinuation.
158 *
159 * As this type of function is called from the scheduler, which only takes
160 * one argument as closure, this struct is used to pass more arguments.
161 */
162struct ESCROW_Plugin_AnchorContinuationWrapper
163{
164 /**
165 * Handle for the escrow component
166 */
167 struct GNUNET_ESCROW_Handle *h;
168
169 /**
170 * The escrow anchor
171 */
172 struct GNUNET_ESCROW_Anchor *escrowAnchor;
173
174 /**
175 * The unique ID of the respective ESCROW_Operation
176 */
177 uint32_t op_id;
178
179 /**
180 * The error message, NULL on success
181 */
182 const char *emsg;
183};
184
185/**
186 * Wrapper for the Plugin_EgoContinuation.
187 *
188 * As this type of function is called from the scheduler, which only takes
189 * one argument as closure, this struct is used to pass more arguments.
190 */
191struct ESCROW_Plugin_EgoContinuationWrapper
192{
193 /**
194 * Handle for the escrow component
195 */
196 struct GNUNET_ESCROW_Handle *h;
197
198 /**
199 * The restored ego
200 */
201 const struct GNUNET_IDENTITY_Ego *ego;
202
203 /**
204 * The unique ID of the respective ESCROW_Operation
205 */
206 uint32_t op_id;
207
208 /**
209 * The error message, NULL on success
210 */
211 const char *emsg;
212};
213
214/**
215 * Wrapper for the Plugin_VerifyContinuation.
216 *
217 * As this type of function is called from the scheduler, which only takes
218 * one argument as closure, this struct is used to pass more arguments.
219 */
220struct ESCROW_Plugin_VerifyContinuationWrapper
221{
222 /**
223 * Handle for the escrow component
224 */
225 struct GNUNET_ESCROW_Handle *h;
226
227 /**
228 * The result of the verification
229 */
230 int verificationResult;
231
232 /**
233 * The unique ID of the respective ESCROW_Operation
234 */
235 uint32_t op_id;
236
237 /**
238 * The error message, NULL on success
239 */
240 const char *emsg;
241};
242
243
244#endif
diff --git a/src/escrow/escrow_api.c b/src/escrow/escrow_api.c
new file mode 100644
index 000000000..1c81a7f6e
--- /dev/null
+++ b/src/escrow/escrow_api.c
@@ -0,0 +1,478 @@
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 * @author Johannes Späth
23 * @file escrow/escrow_api.c
24 *
25 * @brief api to interact with the escrow component
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_escrow_lib.h"
31#include "gnunet_escrow_plugin.h"
32#include "escrow.h"
33
34
35/**
36 * Init canary for the plaintext plugin
37 */
38static int plaintext_initialized;
39
40
41/**
42 * Init canary for the GNS plugin
43 */
44static int gns_initialized;
45
46
47/**
48 * Init canary for the Anastasis plugin
49 */
50static int anastasis_initialized;
51
52
53/**
54 * Pointer to the plaintext plugin API
55 */
56static struct GNUNET_ESCROW_KeyPluginFunctions *plaintext_api;
57
58
59/**
60 * Pointer to the GNS plugin API
61 */
62static struct GNUNET_ESCROW_KeyPluginFunctions *gns_api;
63
64
65/**
66 * Pointer to the Anastasis plugin API
67 */
68static struct GNUNET_ESCROW_KeyPluginFunctions *anastasis_api;
69
70
71/**
72 * Initialize an escrow plugin
73 *
74 * @param method the escrow method determining the plugin
75 *
76 * @return pointer to the escrow plugin API
77 */
78const struct GNUNET_ESCROW_KeyPluginFunctions *
79init_plugin (struct GNUNET_ESCROW_Handle *h,
80 enum GNUNET_ESCROW_Key_Escrow_Method method)
81{
82 switch (method)
83 {
84 case GNUNET_ESCROW_KEY_PLAINTEXT:
85 if (GNUNET_YES == plaintext_initialized)
86 return plaintext_api;
87 plaintext_initialized = GNUNET_YES;
88 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
89 "Loading PLAINTEXT escrow plugin\n");
90 plaintext_api = GNUNET_PLUGIN_load ("libgnunet_plugin_escrow_plaintext",
91 (void *)h->cfg);
92 return plaintext_api;
93 case GNUNET_ESCROW_KEY_GNS:
94 if (GNUNET_YES == gns_initialized)
95 return gns_api;
96 gns_initialized = GNUNET_YES;
97 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
98 "Loading GNS escrow plugin\n");
99 gns_api = GNUNET_PLUGIN_load ("libgnunet_plugin_escrow_gns",
100 (void *)h->cfg);
101 return gns_api;
102 case GNUNET_ESCROW_KEY_ANASTASIS:
103 if (GNUNET_YES == anastasis_initialized)
104 return anastasis_api;
105 anastasis_initialized = GNUNET_YES;
106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
107 "Loading ANASTASIS escrow plugin\n");
108 anastasis_api = GNUNET_PLUGIN_load ("libgnunet_plugin_escrow_anastasis",
109 (void *)h->cfg);
110 return anastasis_api;
111 case GNUNET_ESCROW_KEY_NONE: // error case
112 fprintf (stderr, "incorrect escrow method!");
113 return NULL;
114 }
115 // should never be reached
116 return NULL;
117}
118
119
120/**
121 * Get a fresh operation id to distinguish between escrow operations
122 *
123 * @param h the escrow handle
124 *
125 * @return next operation id to use
126 */
127static uint32_t
128get_op_id (struct GNUNET_ESCROW_Handle *h)
129{
130 return h->last_op_id_used++;
131}
132
133
134/**
135 * Initialize the escrow component.
136 *
137 * @param cfg the configuration to use
138 *
139 * @return handle to use
140 */
141struct GNUNET_ESCROW_Handle *
142GNUNET_ESCROW_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
143{
144 struct GNUNET_ESCROW_Handle *h;
145
146 h = GNUNET_new (struct GNUNET_ESCROW_Handle);
147 h->cfg = GNUNET_CONFIGURATION_dup (cfg);
148 h->op_head = NULL;
149 h->op_tail = NULL;
150 return h;
151}
152
153
154/**
155 * Unload all loaded plugins on destruction.
156 *
157 * @param h the escrow handle
158 */
159void
160GNUNET_ESCROW_fini (struct GNUNET_ESCROW_Handle *h)
161{
162 struct GNUNET_ESCROW_Operation *op;
163
164 /* unload all loaded plugins */
165 if (GNUNET_YES == plaintext_initialized)
166 {
167 plaintext_initialized = GNUNET_NO;
168 GNUNET_break (NULL ==
169 GNUNET_PLUGIN_unload ("libgnunet_plugin_escrow_plaintext",
170 plaintext_api));
171 plaintext_api = NULL;
172 }
173
174 if (GNUNET_YES == gns_initialized)
175 {
176 gns_initialized = GNUNET_NO;
177 GNUNET_break (NULL ==
178 GNUNET_PLUGIN_unload ("libgnunet_plugin_escrow_gns",
179 gns_api));
180 gns_api = NULL;
181 }
182
183 if (GNUNET_YES == anastasis_initialized)
184 {
185 anastasis_initialized = GNUNET_NO;
186 GNUNET_break (NULL ==
187 GNUNET_PLUGIN_unload ("libgnunet_plugin_escrow_anastasis",
188 anastasis_api));
189 anastasis_api = NULL;
190 }
191
192 /* clean up the operation DLL */
193 while (NULL != (op = h->op_head))
194 {
195 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
196 GNUNET_ESCROW_cancel (op);
197 }
198
199 /* free the configuration */
200 GNUNET_free (h->cfg);
201
202 /* free the escrow handle */
203 GNUNET_free (h);
204}
205
206
207void
208handle_start_escrow_result (void *cls)
209{
210 struct ESCROW_Plugin_AnchorContinuationWrapper *w = cls;
211 struct GNUNET_ESCROW_Operation *op;
212
213 for (op = w->h->op_head; NULL != op; op = op->next)
214 if (op->id == w->op_id)
215 break;
216
217 if (NULL == op)
218 {
219 GNUNET_break (0);
220 return;
221 }
222 GNUNET_CONTAINER_DLL_remove (w->h->op_head, w->h->op_tail, op);
223 if (NULL != op->cb_put)
224 op->cb_put (op->cb_cls, w->escrowAnchor, w->emsg);
225 GNUNET_free (op);
226}
227
228
229/**
230 * Put some data in escrow using the specified escrow method
231 *
232 * @param h the handle for the escrow component
233 * @param ego the identity ego to put in escrow
234 * @param userSecret the user secret (e.g. for derivation of escrow identities)
235 * @param method the escrow method to use
236 * @param cb function to call with the escrow anchor on completion
237 * @param cb_cls closure for @a cb
238 *
239 * @return handle to abort the operation
240 */
241struct GNUNET_ESCROW_Operation *
242GNUNET_ESCROW_put (struct GNUNET_ESCROW_Handle *h,
243 struct GNUNET_IDENTITY_Ego *ego,
244 const char *userSecret,
245 enum GNUNET_ESCROW_Key_Escrow_Method method,
246 GNUNET_ESCROW_AnchorContinuation cb,
247 void *cb_cls)
248{
249 struct GNUNET_ESCROW_Operation *op;
250 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
251
252 op = GNUNET_new (struct GNUNET_ESCROW_Operation);
253 op->h = h;
254 op->id = get_op_id (h);
255 op->method = method;
256 op->cb_put = cb;
257 op->cb_cls = cb_cls;
258 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
259
260 api = init_plugin (h, method);
261 op->plugin_op_wrap = api->start_key_escrow (h,
262 ego,
263 userSecret,
264 &handle_start_escrow_result,
265 op->id);
266
267 return op;
268}
269
270
271static void
272handle_restore_key_result (void *cls)
273{
274 struct ESCROW_Plugin_EgoContinuationWrapper *w = cls;
275 struct GNUNET_ESCROW_Operation *op;
276
277 for (op = w->h->op_head; NULL != op; op = op->next)
278 if (op->id == w->op_id)
279 break;
280
281 if (NULL == op)
282 {
283 GNUNET_break (0);
284 return;
285 }
286 GNUNET_CONTAINER_DLL_remove (w->h->op_head, w->h->op_tail, op);
287 if (NULL != op->cb_get)
288 op->cb_get (op->cb_cls, w->ego, w->emsg);
289 GNUNET_free (op);
290}
291
292
293/**
294 * Get the escrowed data back
295 *
296 * @param h the handle for the escrow component
297 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
298 * @param egoName the name of the ego to get back
299 * @param method the escrow method to use
300 * @param cb function to call with the restored ego on completion
301 * @param cb_cls closure for @a cb
302 *
303 * @return handle to abort the operation
304 */
305struct GNUNET_ESCROW_Operation *
306GNUNET_ESCROW_get (struct GNUNET_ESCROW_Handle *h,
307 struct GNUNET_ESCROW_Anchor *escrowAnchor,
308 const char *egoName,
309 enum GNUNET_ESCROW_Key_Escrow_Method method,
310 GNUNET_ESCROW_EgoContinuation cb,
311 void *cb_cls)
312{
313 struct GNUNET_ESCROW_Operation *op;
314 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
315
316 op = GNUNET_new (struct GNUNET_ESCROW_Operation);
317 op->h = h;
318 op->id = get_op_id (h);
319 op->method = method;
320 op->cb_get = cb;
321 op->cb_cls = cb_cls;
322 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
323
324 api = init_plugin (h, method);
325 op->plugin_op_wrap = api->restore_key (h, escrowAnchor, egoName, &handle_restore_key_result, op->id);
326
327 return op;
328}
329
330
331void
332handle_verify_escrow_result (void *cls)
333{
334 struct ESCROW_Plugin_VerifyContinuationWrapper *w = cls;
335 struct GNUNET_ESCROW_Operation *op;
336
337 for (op = w->h->op_head; NULL != op; op = op->next)
338 if (op->id == w->op_id)
339 break;
340
341 if (NULL == op)
342 {
343 GNUNET_break (0);
344 return;
345 }
346 GNUNET_CONTAINER_DLL_remove (w->h->op_head, w->h->op_tail, op);
347 if (NULL != op->cb_verify)
348 op->cb_verify (op->cb_cls, w->verificationResult, w->emsg);
349 GNUNET_free (op);
350}
351
352
353/**
354 * Verify the escrowed data
355 *
356 * @param h the handle for the escrow component
357 * @param ego the identity ego that was put into escrow
358 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
359 * @param method the escrow method to use
360 * @param cb function to call with the verification result on completion
361 * @param cb_cls closure for @a cb
362 *
363 * @return handle to abort the operation
364 */
365struct GNUNET_ESCROW_Operation *
366GNUNET_ESCROW_verify (struct GNUNET_ESCROW_Handle *h,
367 struct GNUNET_IDENTITY_Ego *ego,
368 struct GNUNET_ESCROW_Anchor *escrowAnchor,
369 enum GNUNET_ESCROW_Key_Escrow_Method method,
370 GNUNET_ESCROW_VerifyContinuation cb,
371 void *cb_cls)
372{
373 struct GNUNET_ESCROW_Operation *op;
374 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
375
376 op = GNUNET_new (struct GNUNET_ESCROW_Operation);
377 op->h = h;
378 op->id = get_op_id (h);
379 op->method = method;
380 op->cb_verify = cb;
381 op->cb_cls = cb_cls;
382 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
383
384 api = init_plugin (h, method);
385 op->plugin_op_wrap = api->verify_key_escrow (h, ego, escrowAnchor, &handle_verify_escrow_result, op->id);
386
387 return op;
388}
389
390
391/**
392 * Get the status of an escrow, i.e.
393 * -> when the last escrow was
394 * -> when the next escrow is recommended
395 *
396 * @param h the handle for the escrow component
397 * @param ego the identity ego of which the escrow status has to be determined
398 * @param method the escrow method to use
399 *
400 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
401 */
402struct GNUNET_ESCROW_Status *
403GNUNET_ESCROW_get_status (struct GNUNET_ESCROW_Handle *h,
404 struct GNUNET_IDENTITY_Ego *ego,
405 enum GNUNET_ESCROW_Key_Escrow_Method method)
406{
407 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
408
409 api = init_plugin (h, method);
410 return api->get_status (h, ego);
411}
412
413
414/**
415 * Deserialize an escrow anchor string (e.g. from command line) into a
416 * GNUNET_ESCROW_Anchor struct
417 *
418 * @param h the handle for the escrow component
419 * @param anchorString the encoded escrow anchor string
420 * @param method the escrow method to use
421 *
422 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
423 */
424struct GNUNET_ESCROW_Anchor *
425GNUNET_ESCROW_anchor_string_to_data (struct GNUNET_ESCROW_Handle *h,
426 char *anchorString,
427 enum GNUNET_ESCROW_Key_Escrow_Method method)
428{
429 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
430
431 api = init_plugin (h, method);
432 return api->anchor_string_to_data (h, anchorString);
433}
434
435
436/**
437 * Serialize an escrow anchor (struct GNUNET_ESCROW_Anchor) into a string
438 *
439 * @param h the handle for the escrow component
440 * @param escrowAnchor the escrow anchor struct
441 * @param method the escrow method to use
442 *
443 * @return the encoded escrow anchor string
444 */
445char *
446GNUNET_ESCROW_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
447 struct GNUNET_ESCROW_Anchor *escrowAnchor,
448 enum GNUNET_ESCROW_Key_Escrow_Method method)
449{
450 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
451
452 api = init_plugin (h, method);
453 return api->anchor_data_to_string (h, escrowAnchor);
454}
455
456
457/**
458 * Cancel an escrow operation. Note that the operation MAY still
459 * be executed; this merely cancels the continuation.
460 *
461 * @param op operation to cancel
462 */
463void
464GNUNET_ESCROW_cancel (struct GNUNET_ESCROW_Operation *op)
465{
466 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
467
468 api = init_plugin (op->h, op->method);
469 api->cancel_plugin_operation (op->plugin_op_wrap);
470 // TODO: check which callback is not NULL?
471 op->cb_put = NULL;
472 op->cb_verify = NULL;
473 op->cb_get = NULL;
474 GNUNET_free (op);
475}
476
477
478/* end of escrow_api.c */
diff --git a/src/escrow/escrow_plugin_helper.c b/src/escrow/escrow_plugin_helper.c
new file mode 100644
index 000000000..36acae049
--- /dev/null
+++ b/src/escrow/escrow_plugin_helper.c
@@ -0,0 +1,361 @@
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 * @author Johannes Späth
23 * @file escrow/escrow_plugin.c
24 *
25 * @brief helper functions for escrow plugins
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
31#include "gnunet_escrow_plugin.h"
32
33
34/**
35 * Maintains the ego list for an escrow plugin.
36 * This function is an implementation of GNUNET_IDENTITY_Callback.
37 *
38 * It is initially called for all egos and then again
39 * whenever a ego's identifier changes or if it is deleted. At the
40 * end of the initial pass over all egos, the function is once called
41 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
42 * be invoked in the future or that there was an error.
43 *
44 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
45 * this function is only called ONCE, and 'NULL' being passed in
46 * 'ego' does indicate an error (i.e. name is taken or no default
47 * value is known). If 'ego' is non-NULL and if '*ctx'
48 * is set in those callbacks, the value WILL be passed to a subsequent
49 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
50 * that one was not NULL).
51 *
52 * When an identity is renamed, this function is called with the
53 * (known) ego but the NEW identifier.
54 *
55 * When an identity is deleted, this function is called with the
56 * (known) ego and "NULL" for the 'identifier'. In this case,
57 * the 'ego' is henceforth invalid (and the 'ctx' should also be
58 * cleaned up).
59 *
60 * @param cls plugin handle
61 * @param ego ego handle
62 * @param ctx context for application to store data for this ego
63 * (during the lifetime of this process, initially NULL)
64 * @param identifier identifier assigned by the user for this ego,
65 * NULL if the user just deleted the ego and it
66 * must thus no longer be used
67 */
68void
69ESCROW_list_ego (void *cls,
70 struct GNUNET_IDENTITY_Ego *ego,
71 void **ctx,
72 const char *identifier)
73{
74 struct ESCROW_PluginHandle *ph = cls;
75 struct EgoEntry *ego_entry;
76 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
77
78 // TODO: error when this method is called at cleanup if init is not yet finished
79 if ((NULL == ego) && (ESCROW_PLUGIN_STATE_INIT == ph->state))
80 {
81 ph->state = ESCROW_PLUGIN_STATE_POST_INIT;
82 /* call IdentityInitContinuation */
83 ph->id_init_cont ();
84 return;
85 }
86 GNUNET_assert (NULL != ego);
87
88 if (ESCROW_PLUGIN_STATE_INIT == ph->state)
89 {
90 ego_entry = GNUNET_new (struct EgoEntry);
91 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
92 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
93 ego_entry->ego = ego;
94 ego_entry->identifier = GNUNET_strdup (identifier);
95 GNUNET_CONTAINER_DLL_insert_tail (ph->ego_head,
96 ph->ego_tail,
97 ego_entry);
98 return;
99 }
100 /* Ego renamed or added */
101 if (identifier != NULL)
102 {
103 for (ego_entry = ph->ego_head; NULL != ego_entry;
104 ego_entry = ego_entry->next)
105 {
106 if (ego_entry->ego == ego)
107 {
108 /* Rename */
109 GNUNET_free (ego_entry->identifier);
110 ego_entry->identifier = GNUNET_strdup (identifier);
111 /* TODO: this handles an edge case when the user restores an ego
112 that already exists. In that case, @param ego is the same for the
113 new as for the existing ego and this method thinks it is a rename. */
114 if (NULL != ph->ego_create_cont)
115 ph->ego_create_cont (ego);
116 break;
117 }
118 }
119 if (NULL == ego_entry)
120 {
121 /* Add */
122 ego_entry = GNUNET_new (struct EgoEntry);
123 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
124 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
125 ego_entry->ego = ego;
126 ego_entry->identifier = GNUNET_strdup (identifier);
127 GNUNET_CONTAINER_DLL_insert_tail (ph->ego_head,
128 ph->ego_tail,
129 ego_entry);
130 /* new ego is added to the list, call ego_create_cont if this was
131 because of an ESCROW_get operation, i.e. ego_create_cont != NULL */
132 if (NULL != ph->ego_create_cont)
133 ph->ego_create_cont (ego);
134 }
135 }
136 else
137 {
138 /* Delete */
139 for (ego_entry = ph->ego_head; NULL != ego_entry;
140 ego_entry = ego_entry->next)
141 {
142 if (ego_entry->ego == ego)
143 break;
144 }
145 if (NULL == ego_entry)
146 return; /* Not found */
147
148 GNUNET_CONTAINER_DLL_remove (ph->ego_head,
149 ph->ego_tail,
150 ego_entry);
151 GNUNET_free (ego_entry->identifier);
152 GNUNET_free (ego_entry->keystring);
153 GNUNET_free (ego_entry);
154 return;
155 }
156}
157
158
159/**
160 * Cleanup the ego list of an escrow plugin.
161 *
162 * @param ph handle for the plugin
163 */
164void
165ESCROW_cleanup_ego_list (struct ESCROW_PluginHandle *ph)
166{
167 struct EgoEntry *ego_entry;
168
169 while (NULL != (ego_entry = ph->ego_head))
170 {
171 GNUNET_CONTAINER_DLL_remove (ph->ego_head, ph->ego_tail, ego_entry);
172 GNUNET_free (ego_entry->identifier);
173 GNUNET_free (ego_entry->keystring);
174 GNUNET_free (ego_entry);
175 }
176}
177
178
179char *
180string_to_upper (const char *str)
181{
182 char *str_upper;
183 uint16_t i;
184
185 str_upper = GNUNET_strdup (str);
186
187 for (i = 0; i < strlen(str_upper); i++)
188 {
189 if (str_upper[i] >= 'a' && str_upper[i] <= 'z')
190 str_upper[i] -= 32; // 'a' - 'A' = 32
191 }
192
193 return str_upper;
194}
195
196
197/**
198 * Update the status of an escrow in the configuration.
199 *
200 * @param h handle for the escrow component
201 * @param ego the ego of which the escrow status is updated
202 * @param plugin_name the name of the used plugin
203 *
204 * @return GNUNET_OK on success
205 */
206int
207ESCROW_update_escrow_status (struct GNUNET_ESCROW_Handle *h,
208 struct GNUNET_IDENTITY_Ego *ego,
209 const char *plugin_name)
210{
211 struct GNUNET_CRYPTO_EcdsaPublicKey *pub;
212 char *config_section, *pubkey_string, *config_option, *plugin_name_upper;
213 struct GNUNET_TIME_Absolute now, next_escrow;
214 struct GNUNET_TIME_Relative escrow_interval;
215 char *conf_file;
216
217 pub = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
218 GNUNET_IDENTITY_ego_get_public_key (ego, pub);
219 pubkey_string = GNUNET_CRYPTO_ecdsa_public_key_to_string (pub);
220
221 // allocate enough space for "escrow-PUBKEY"
222 config_section = GNUNET_malloc (7 + strlen (pubkey_string) + 1);
223 sprintf (config_section, "escrow-%s", pubkey_string);
224
225 // allocate enough space for "<plugin_name>_INTERVAL"
226 config_option = GNUNET_malloc (strlen (plugin_name) + 9 + 1);
227 plugin_name_upper = string_to_upper (plugin_name);
228 sprintf (config_option, "%s_INTERVAL", plugin_name_upper);
229
230 now = GNUNET_TIME_absolute_get ();
231 GNUNET_CONFIGURATION_set_value_number (h->cfg,
232 config_section,
233 "LAST_ESCROW_TIME",
234 (unsigned long long)now.abs_value_us);
235 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (h->cfg,
236 "escrow",
237 config_option,
238 &escrow_interval))
239 {
240 fprintf (stderr, "could not find config value for escrow interval\n");
241 GNUNET_free (pub);
242 GNUNET_free (config_section);
243 GNUNET_free (pubkey_string);
244 GNUNET_free (config_option);
245 GNUNET_free (plugin_name_upper);
246 return GNUNET_NO;
247 }
248 next_escrow = GNUNET_TIME_absolute_add (now, escrow_interval);
249 GNUNET_CONFIGURATION_set_value_number (h->cfg,
250 config_section,
251 "NEXT_RECOMMENDED_ESCROW_TIME",
252 (unsigned long long)next_escrow.abs_value_us);
253
254 GNUNET_CONFIGURATION_set_value_string (h->cfg,
255 config_section,
256 "ESCROW_METHOD",
257 plugin_name);
258
259 GNUNET_assert (GNUNET_OK ==
260 GNUNET_CONFIGURATION_get_value_filename (h->cfg,
261 "PATHS",
262 "DEFAULTCONFIG",
263 &conf_file));
264 if (GNUNET_OK != GNUNET_CONFIGURATION_write (h->cfg, conf_file))
265 {
266 fprintf (stderr, "unable to write config file\n");
267 GNUNET_free (pub);
268 GNUNET_free (config_section);
269 GNUNET_free (pubkey_string);
270 GNUNET_free (config_option);
271 GNUNET_free (plugin_name_upper);
272 GNUNET_free (conf_file);
273 return GNUNET_NO;
274 }
275
276 GNUNET_free (pub);
277 GNUNET_free (config_section);
278 GNUNET_free (pubkey_string);
279 GNUNET_free (config_option);
280 GNUNET_free (plugin_name_upper);
281 GNUNET_free (conf_file);
282
283 return GNUNET_OK;
284}
285
286
287/**
288 * Get the status of an escrow from the configuration.
289 *
290 * @param h handle for the escrow component
291 * @param ego the ego of which the escrow status has to be obtained
292 *
293 * @return the status of the escrow, packed into a GNUNET_ESCROW_Status struct
294 */
295struct GNUNET_ESCROW_Status *
296ESCROW_get_escrow_status (struct GNUNET_ESCROW_Handle *h,
297 struct GNUNET_IDENTITY_Ego *ego)
298{
299 struct GNUNET_ESCROW_Status *status;
300 unsigned long long conf_last_escrow, conf_next_escrow;
301 struct GNUNET_CRYPTO_EcdsaPublicKey *pub;
302 char *config_section, *pubkey_string, *conf_escrow_method;
303
304 pub = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
305 GNUNET_IDENTITY_ego_get_public_key (ego, pub);
306 pubkey_string = GNUNET_CRYPTO_ecdsa_public_key_to_string (pub);
307
308 // allocate enough space for "escrow-PUBKEY"
309 config_section = GNUNET_malloc (7 + strlen (pubkey_string) + 1);
310 sprintf (config_section, "escrow-%s", pubkey_string);
311
312 status = GNUNET_new (struct GNUNET_ESCROW_Status);
313 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (h->cfg,
314 config_section,
315 "LAST_ESCROW_TIME",
316 &conf_last_escrow))
317 {
318 // TODO: is that the behavior when the section is not defined?
319 status->last_escrow_time = GNUNET_TIME_absolute_get_zero_();
320 }
321 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (h->cfg,
322 config_section,
323 "NEXT_RECOMMENDED_ESCROW_TIME",
324 &conf_next_escrow))
325 {
326 // TODO: is that the behavior when the section is not defined?
327 status->next_recommended_escrow_time = GNUNET_TIME_absolute_get ();
328 }
329 status->last_method = GNUNET_ESCROW_KEY_NONE;
330 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (h->cfg,
331 config_section,
332 "ESCROW_METHOD",
333 &conf_escrow_method))
334 {
335 // TODO: error handling?
336 }
337 status->last_escrow_time.abs_value_us = (uint64_t)conf_last_escrow;
338 status->next_recommended_escrow_time.abs_value_us = (uint64_t)conf_next_escrow;
339 if (NULL != conf_escrow_method)
340 {
341 if (NULL != conf_escrow_method && 0 == strcmp (conf_escrow_method, "plaintext"))
342 status->last_method = GNUNET_ESCROW_KEY_PLAINTEXT;
343 else if (0 == strcmp (conf_escrow_method, "gns"))
344 status->last_method = GNUNET_ESCROW_KEY_GNS;
345 else if (0 == strcmp (conf_escrow_method, "anastasis"))
346 status->last_method = GNUNET_ESCROW_KEY_ANASTASIS;
347 else
348 status->last_method = GNUNET_ESCROW_KEY_NONE;
349 }
350
351
352 GNUNET_free (config_section);
353 GNUNET_free (pubkey_string);
354 GNUNET_free (pub);
355 GNUNET_free (conf_escrow_method);
356
357 return status;
358}
359
360
361/* end of escrow_plugin.c */
diff --git a/src/escrow/escrow_plugin_helper.h b/src/escrow/escrow_plugin_helper.h
new file mode 100644
index 000000000..f2a54eb6b
--- /dev/null
+++ b/src/escrow/escrow_plugin_helper.h
@@ -0,0 +1,108 @@
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 * @author Johannes Späth
23 * @file escrow/escrow_plugin.h
24 *
25 * @brief helper functions for escrow plugins
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
31#include "gnunet_escrow_plugin.h"
32
33
34/**
35 * Maintains the ego list for an escrow plugin.
36 * This function is an implementation of GNUNET_IDENTITY_Callback.
37 *
38 * It is initially called for all egos and then again
39 * whenever a ego's identifier changes or if it is deleted. At the
40 * end of the initial pass over all egos, the function is once called
41 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
42 * be invoked in the future or that there was an error.
43 *
44 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
45 * this function is only called ONCE, and 'NULL' being passed in
46 * 'ego' does indicate an error (i.e. name is taken or no default
47 * value is known). If 'ego' is non-NULL and if '*ctx'
48 * is set in those callbacks, the value WILL be passed to a subsequent
49 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
50 * that one was not NULL).
51 *
52 * When an identity is renamed, this function is called with the
53 * (known) ego but the NEW identifier.
54 *
55 * When an identity is deleted, this function is called with the
56 * (known) ego and "NULL" for the 'identifier'. In this case,
57 * the 'ego' is henceforth invalid (and the 'ctx' should also be
58 * cleaned up).
59 *
60 * @param cls plugin handle
61 * @param ego ego handle
62 * @param ctx context for application to store data for this ego
63 * (during the lifetime of this process, initially NULL)
64 * @param identifier identifier assigned by the user for this ego,
65 * NULL if the user just deleted the ego and it
66 * must thus no longer be used
67 */
68void
69ESCROW_list_ego (void *cls,
70 struct GNUNET_IDENTITY_Ego *ego,
71 void **ctx,
72 const char *identifier);
73
74
75/**
76 * Cleanup the ego list of an escrow plugin.
77 *
78 * @param ph handle for the plugin
79 */
80void
81ESCROW_cleanup_ego_list (struct ESCROW_PluginHandle *ph);
82
83
84/**
85 * Update the status of an escrow in the configuration.
86 *
87 * @param h handle for the escrow component
88 * @param ego the ego of which the escrow status is updated
89 * @param plugin_name the name of the used plugin
90 *
91 * @return GNUNET_OK on success
92 */
93int
94ESCROW_update_escrow_status (struct GNUNET_ESCROW_Handle *h,
95 struct GNUNET_IDENTITY_Ego *ego,
96 const char *plugin_name);
97
98/**
99 * Get the status of an escrow from the configuration.
100 *
101 * @param h handle for the escrow component
102 * @param ego the ego of which the escrow status has to be obtained
103 *
104 * @return the status of the escrow, packed into a GNUNET_ESCROW_Status struct
105 */
106struct GNUNET_ESCROW_Status *
107ESCROW_get_escrow_status (struct GNUNET_ESCROW_Handle *h,
108 struct GNUNET_IDENTITY_Ego *ego);
diff --git a/src/escrow/gnunet-escrow.c b/src/escrow/gnunet-escrow.c
new file mode 100644
index 000000000..0919146d2
--- /dev/null
+++ b/src/escrow/gnunet-escrow.c
@@ -0,0 +1,535 @@
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 * @author Johannes Späth
22 * @file src/escrow/gnunet-escrow.c
23 * @brief Identity Escrow utility
24 *
25 */
26
27#include "platform.h"
28
29#include "gnunet_util_lib.h"
30#include "gnunet_escrow_lib.h"
31#include "../identity/identity.h"
32
33/**
34 * return value
35 */
36static int ret;
37
38/**
39 * Plaintext method string
40 */
41static const char *plaintext_string = "plaintext";
42
43/**
44 * GNS method string
45 */
46static const char *gns_string = "gns";
47
48/**
49 * Anastasis method string
50 */
51static const char *anastasis_string = "anastasis";
52
53/**
54 * -P option
55 */
56static char *put_ego;
57
58/**
59 * -V option
60 */
61static char *verify_ego;
62
63/**
64 * -G option
65 */
66static char *get_ego;
67
68/**
69 * -S option
70 */
71static char *status_ego;
72
73/**
74 * The ego
75 */
76struct GNUNET_IDENTITY_Ego *ego;
77
78/**
79 * User secret string
80 */
81static char *user_secret_string;
82
83/**
84 * Anchor string
85 */
86static char *anchor_string;
87
88/**
89 * The escrow anchor
90 */
91struct GNUNET_ESCROW_Anchor *anchor;
92
93/**
94 * Plugin name
95 */
96static char *method_name;
97
98/**
99 * Escrow method
100 */
101enum GNUNET_ESCROW_Key_Escrow_Method method;
102
103/**
104 * Handle to the escrow component
105 */
106static struct GNUNET_ESCROW_Handle *escrow_handle;
107
108/**
109 * Escrow operation
110 */
111static struct GNUNET_ESCROW_Operation *escrow_op;
112
113/**
114 * Escrow status
115 */
116static struct GNUNET_ESCROW_Status *escrow_status;
117
118/**
119 * Handle to the identity service
120 */
121static struct GNUNET_IDENTITY_Handle *identity_handle;
122
123/**
124 * Cleanup task
125 */
126static struct GNUNET_SCHEDULER_Task *cleanup_task;
127
128
129/**
130 * Called to clean up the escrow component
131 */
132static void
133do_cleanup (void *cls)
134{
135 cleanup_task = NULL;
136 if (NULL != escrow_op)
137 {
138 GNUNET_ESCROW_cancel (escrow_op);
139 escrow_op = NULL;
140 }
141 if (NULL != escrow_handle)
142 GNUNET_ESCROW_fini (escrow_handle);
143 if (NULL != identity_handle)
144 GNUNET_IDENTITY_disconnect (identity_handle);
145 if (NULL != method_name)
146 {
147 GNUNET_free (method_name);
148 method_name = NULL;
149 }
150 if (NULL != user_secret_string)
151 {
152 GNUNET_free (user_secret_string);
153 user_secret_string = NULL;
154 }
155 if (NULL != anchor_string)
156 {
157 GNUNET_free (anchor_string);
158 anchor_string = NULL;
159 }
160 if (NULL != anchor)
161 {
162 GNUNET_free (anchor);
163 anchor = NULL;
164 }
165 if (NULL != put_ego)
166 {
167 GNUNET_free (put_ego);
168 put_ego = NULL;
169 }
170 if (NULL != verify_ego)
171 {
172 GNUNET_free (verify_ego);
173 verify_ego = NULL;
174 }
175 if (NULL != get_ego)
176 {
177 GNUNET_free (get_ego);
178 get_ego = NULL;
179 }
180 if (NULL != status_ego)
181 {
182 GNUNET_free (status_ego);
183 status_ego = NULL;
184 }
185 if (NULL != escrow_status)
186 {
187 GNUNET_free (escrow_status);
188 escrow_status = NULL;
189 }
190 if (NULL != ego)
191 {
192 /* does not have to be freed, as this is done when
193 cleaning up the ego list in the plugin */
194 ego = NULL;
195 }
196 method = -1;
197}
198
199
200static void
201put_cb (void *cls,
202 struct GNUNET_ESCROW_Anchor *escrowAnchor,
203 const char *emsg)
204{
205 char *anchorString;
206
207 escrow_op = NULL;
208
209 if (NULL == escrowAnchor)
210 {
211 ret = 1;
212 if (NULL != emsg)
213 fprintf (stderr, "Escrow failed: %s", emsg);
214 }
215 else
216 {
217 anchorString = GNUNET_ESCROW_anchor_data_to_string (escrow_handle,
218 escrowAnchor,
219 method);
220
221 fprintf (stdout, "Escrow finished! Please keep the following anchor \
222in order to restore the key later!\n%s\n", anchorString);
223 }
224 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
225}
226
227
228static void
229verify_cb (void *cls,
230 int verificationResult,
231 const char *emsg)
232{
233 escrow_op = NULL;
234
235 switch (verificationResult)
236 {
237 case GNUNET_ESCROW_VALID:
238 fprintf (stdout, "Escrow is valid!\n");
239 break;
240 case GNUNET_ESCROW_INVALID:
241 ret = 2;
242 fprintf (stdout, "Escrow is INvalid! Please perform a new escrow.\n");
243 break;
244 default:
245 ret = 1;
246 if (NULL != emsg)
247 fprintf (stderr, "invalid verificationResult: %s", emsg);
248 }
249 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
250}
251
252
253static void
254get_cb (void *cls,
255 const struct GNUNET_IDENTITY_Ego *ego,
256 const char *emsg)
257{
258 escrow_op = NULL;
259
260 if (NULL == ego)
261 {
262 ret = 1;
263 if (NULL != emsg)
264 fprintf (stderr, "Escrow failed: %s", emsg);
265 }
266 else
267 fprintf (stdout, "Ego %s could successfully be restored!\n", ego->name);
268 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
269}
270
271
272static void
273start_process ()
274{
275 /* put */
276 if (NULL != put_ego)
277 {
278 if (NULL == ego)
279 {
280 ret = 1;
281 fprintf (stderr, "Ego %s not found\n", put_ego);
282 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
283 return;
284 }
285 escrow_op = GNUNET_ESCROW_put (escrow_handle,
286 ego,
287 user_secret_string,
288 method,
289 &put_cb,
290 NULL);
291 return;
292 }
293 /* verify */
294 if (NULL != verify_ego)
295 {
296 if (NULL == ego)
297 {
298 ret = 1;
299 fprintf (stderr, "Ego %s not found\n", verify_ego);
300 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
301 return;
302 }
303 escrow_op = GNUNET_ESCROW_verify (escrow_handle,
304 ego,
305 anchor,
306 method,
307 &verify_cb,
308 NULL);
309 return;
310 }
311 /* get */
312 if (NULL != get_ego)
313 {
314 if (NULL != ego)
315 {
316 ret = 1;
317 fprintf (stderr, "The name %s is already in use for an ego\n", get_ego);
318 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
319 return;
320 }
321 escrow_op = GNUNET_ESCROW_get (escrow_handle,
322 anchor,
323 get_ego,
324 method,
325 &get_cb,
326 NULL);
327 return;
328 }
329 /* status */
330 if (NULL != status_ego)
331 {
332 if (NULL == ego)
333 {
334 ret = 1;
335 fprintf (stderr, "Ego %s not found\n", status_ego);
336 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
337 return;
338 }
339 escrow_status = GNUNET_ESCROW_get_status (escrow_handle,
340 ego,
341 method);
342 // TODO: formatting/interpretation
343 fprintf (stdout, "Last escrow:\t\t\t%s\n",
344 GNUNET_STRINGS_absolute_time_to_string (escrow_status->last_escrow_time));
345 fprintf (stdout, "Next recommended escrow:\t%s\n",
346 GNUNET_STRINGS_absolute_time_to_string (escrow_status->next_recommended_escrow_time));
347 fprintf (stdout, "Last method:\t\t\t%d\n", escrow_status->last_method);
348 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
349 return;
350 }
351}
352
353
354static int init = GNUNET_YES;
355
356static void
357ego_cb (void *cls,
358 struct GNUNET_IDENTITY_Ego *e,
359 void **ctx,
360 const char *name)
361{
362 char *ego_name = cls;
363
364 if (NULL == name)
365 {
366 if (GNUNET_YES == init)
367 {
368 init = GNUNET_NO;
369 start_process ();
370 }
371 return;
372 }
373 if (0 != strcmp (name, ego_name))
374 return;
375 ego = e;
376}
377
378
379static void
380run (void *cls,
381 char *const *args,
382 const char *cfgfile,
383 const struct GNUNET_CONFIGURATION_Handle *c)
384{
385 char *ego_name;
386
387 ret = 0;
388
389 /* check if method is set */
390 if (NULL == method_name)
391 {
392 ret = 1;
393 fprintf (stderr, _ ("Escrow method (-m option) is missing\n"));
394 return;
395 }
396
397 if (NULL != put_ego)
398 {
399 if (NULL != verify_ego || NULL != get_ego || NULL != status_ego)
400 {
401 ret = 1;
402 fprintf (stderr, _ ("-P may only be used without -V, -G or -S!\n"));
403 return;
404 }
405 /* put */
406 ego_name = put_ego;
407 }
408 else if (NULL != verify_ego)
409 {
410 if (NULL != get_ego || NULL != status_ego)
411 {
412 ret = 1;
413 fprintf (stderr, _ ("-V may only be used without -P, -G or -S!\n"));
414 return;
415 }
416 /* verify */
417 if (NULL == anchor_string)
418 {
419 ret = 1;
420 fprintf (stderr, _ ("-a is needed for -V!\n"));
421 return;
422 }
423 ego_name = verify_ego;
424 }
425 else if (NULL != get_ego)
426 {
427 if (NULL != status_ego)
428 {
429 ret = 1;
430 fprintf (stderr, _ ("-G may only be used without -P, -V or -S!\n"));
431 return;
432 }
433 /* get */
434 if (NULL == anchor_string)
435 {
436 ret = 1;
437 fprintf (stderr, _ ("-a is needed for -G!\n"));
438 return;
439 }
440 ego_name = get_ego;
441 }
442 else if (NULL != status_ego)
443 {
444 /* status */
445 ego_name = status_ego;
446 }
447 else
448 {
449 /* nothing */
450 ret = 1;
451 fprintf (stderr, _ ("-P, -V, -G or -S option must be specified!\n"));
452 return;
453 }
454
455 /* determine method */
456 if (!strncmp (plaintext_string, method_name, strlen (plaintext_string)))
457 method = GNUNET_ESCROW_KEY_PLAINTEXT;
458 else if (!strncmp (gns_string, method_name, strlen (gns_string)))
459 method = GNUNET_ESCROW_KEY_GNS;
460 else if (!strncmp (anastasis_string, method_name, strlen (anastasis_string)))
461 method = GNUNET_ESCROW_KEY_ANASTASIS;
462 else
463 {
464 ret = 1;
465 fprintf (stderr, _ ("unknown method name!"));
466 return;
467 }
468
469 escrow_handle = GNUNET_ESCROW_init (c);
470
471 if (NULL != anchor_string)
472 {
473 /* parse anchor_string according to method */
474 anchor = GNUNET_ESCROW_anchor_string_to_data (escrow_handle,
475 anchor_string,
476 method);
477 }
478
479 /* connect to identity service in order to get the egos */
480 identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, ego_name);
481}
482
483
484int
485main (int argc, char *const argv[])
486{
487 struct GNUNET_GETOPT_CommandLineOption options[] = {
488 GNUNET_GETOPT_option_string ('P',
489 "put",
490 "NAME",
491 gettext_noop ("Put the ego NAME into escrow"),
492 &put_ego),
493 GNUNET_GETOPT_option_string ('V',
494 "verify",
495 "NAME",
496 gettext_noop ("Verify the escrow of the ego NAME"),
497 &verify_ego),
498 GNUNET_GETOPT_option_string ('G',
499 "get",
500 "NAME",
501 gettext_noop ("Get the ego NAME back from escrow"),
502 &get_ego),
503 GNUNET_GETOPT_option_string ('S',
504 "status",
505 "NAME",
506 gettext_noop ("Get the status of the escrow of ego NAME"),
507 &status_ego),
508 GNUNET_GETOPT_option_string ('u',
509 "userSecret",
510 "USER_SECRET",
511 gettext_noop ("The user secret string"),
512 &user_secret_string),
513 GNUNET_GETOPT_option_string ('a',
514 "anchor",
515 "ANCHOR",
516 gettext_noop ("The escrow anchor"),
517 &anchor_string),
518 GNUNET_GETOPT_option_string ('m',
519 "method",
520 "METHOD",
521 gettext_noop ("The escrow method (and plugin) to use"),
522 &method_name),
523 GNUNET_GETOPT_OPTION_END
524 };
525 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
526 argv,
527 "gnunet-escrow",
528 _ ("escrow command line tool"),
529 options,
530 &run,
531 NULL))
532 return 1;
533 else
534 return ret;
535}
diff --git a/src/escrow/plugin_escrow_anastasis.c b/src/escrow/plugin_escrow_anastasis.c
new file mode 100644
index 000000000..c0be1f50f
--- /dev/null
+++ b/src/escrow/plugin_escrow_anastasis.c
@@ -0,0 +1,274 @@
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 escrow/plugin_escrow_anastasis.c
23 * @brief escrow-plugin-anastasis escrow plugin for escrow of the key using Anastasis
24 *
25 * @author Johannes Späth
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_escrow_plugin.h"
30#include "escrow_plugin_helper.h"
31#include <inttypes.h>
32
33
34/**
35 * Identity handle
36 */
37static struct GNUNET_IDENTITY_Handle *identity_handle;
38
39/**
40 * Handle for the plugin instance
41 */
42struct ESCROW_PluginHandle ph;
43
44
45/**
46 * Start the Anastasis escrow of the key
47 *
48 * @param h the handle for the escrow component
49 * @param ego the identity ego containing the private key
50 * @param userSecret the user secret (e.g. for derivation of escrow identities)
51 * @param cb the function called upon completion
52 * @param op_id unique ID of the respective ESCROW_Operation
53 *
54 * @return plugin operation wrapper
55 */
56struct ESCROW_PluginOperationWrapper *
57start_anastasis_key_escrow (struct GNUNET_ESCROW_Handle *h,
58 struct GNUNET_IDENTITY_Ego *ego,
59 const char *userSecret,
60 GNUNET_SCHEDULER_TaskCallback cb,
61 uint32_t op_id)
62{
63 struct ESCROW_Plugin_AnchorContinuationWrapper *w;
64
65 w = GNUNET_new (struct ESCROW_Plugin_AnchorContinuationWrapper);
66 w->h = h;
67 w->op_id = op_id;
68
69 // TODO: implement
70 w->escrowAnchor = NULL;
71 w->emsg = _ ("Anastasis escrow is not yet implemented!\n");
72 GNUNET_SCHEDULER_add_now (cb, w);
73 return NULL;
74}
75
76
77/**
78 * Verify the Anastasis escrow of the key
79 *
80 * @param h the handle for the escrow component
81 * @param ego the identity ego containing the private key
82 * @param escrowAnchor the escrow anchor needed to restore the key
83 * @param cb the function called upon completion
84 * @param op_id unique ID of the respective ESCROW_Operation
85 *
86 * @return plugin operation wrapper
87 */
88struct ESCROW_PluginOperationWrapper *
89verify_anastasis_key_escrow (struct GNUNET_ESCROW_Handle *h,
90 struct GNUNET_IDENTITY_Ego *ego,
91 struct GNUNET_ESCROW_Anchor *escrowAnchor,
92 GNUNET_SCHEDULER_TaskCallback cb,
93 uint32_t op_id)
94{
95 struct ESCROW_Plugin_VerifyContinuationWrapper *w;
96
97 w = GNUNET_new (struct ESCROW_Plugin_VerifyContinuationWrapper);
98 w->h = h;
99 w->op_id = op_id;
100
101 // TODO: implement
102 w->verificationResult = GNUNET_ESCROW_INVALID;
103 w->emsg = _ ("Anastasis escrow is not yet implemented!\n");
104 GNUNET_SCHEDULER_add_now (cb, w);
105 return NULL;
106}
107
108
109/**
110 * Restore the key from Anastasis escrow
111 *
112 * @param h the handle for the escrow component
113 * @param escrowAnchor the escrow anchor needed to restore the key
114 * @param egoName the name of the ego to restore
115 * @param cb the function called upon completion
116 * @param op_id unique ID of the respective ESCROW_Operation
117 *
118 * @return plugin operation wrapper
119 */
120struct ESCROW_PluginOperationWrapper *
121restore_anastasis_key_escrow (struct GNUNET_ESCROW_Handle *h,
122 struct GNUNET_ESCROW_Anchor *escrowAnchor,
123 const char *egoName,
124 GNUNET_SCHEDULER_TaskCallback cb,
125 uint32_t op_id)
126{
127 struct ESCROW_Plugin_EgoContinuationWrapper *w;
128
129 w = GNUNET_new (struct ESCROW_Plugin_EgoContinuationWrapper);
130 w->h = h;
131 w->op_id = op_id;
132
133 // TODO: implement
134 w->ego = NULL;
135 w->emsg = _ ("Anastasis escrow is not yet implemented!\n");
136 GNUNET_SCHEDULER_add_now (cb, w);
137 return NULL;
138}
139
140
141/**
142 * Get the status of a Anastasis escrow
143 *
144 * @param h the handle for the escrow component
145 * @param ego the identity ego of which the status has to be obtained
146 *
147 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
148 */
149struct GNUNET_ESCROW_Status *
150anastasis_get_status (struct GNUNET_ESCROW_Handle *h,
151 struct GNUNET_IDENTITY_Ego *ego)
152{
153 return ESCROW_get_escrow_status (h, ego);
154}
155
156
157/**
158 * Deserialize an escrow anchor string into a GNUNET_ESCROW_Anchor struct
159 *
160 * @param anchorString the encoded escrow anchor string
161 *
162 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
163 */
164struct GNUNET_ESCROW_Anchor *
165anastasis_anchor_string_to_data (struct GNUNET_ESCROW_Handle *h,
166 char *anchorString)
167{
168 struct GNUNET_ESCROW_Anchor *anchor;
169 uint32_t data_size;
170
171 data_size = strlen (anchorString) + 1;
172
173 anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + data_size);
174 anchor->size = data_size;
175 // TODO: deserialize?
176 GNUNET_memcpy (&anchor[1], anchorString, data_size);
177
178 return anchor;
179}
180
181
182/**
183 * Serialize an escrow anchor struct into a string
184 *
185 * @param h the handle for the escrow component
186 * @param escrowAnchor the escrow anchor struct
187 *
188 * @return the encoded escrow anchor string
189 */
190char *
191anastasis_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
192 struct GNUNET_ESCROW_Anchor *escrowAnchor)
193{
194 // TODO: implement
195 return NULL;
196}
197
198
199/**
200 * Cancel an Anastasis plugin operation.
201 *
202 * @param plugin_op_wrap the plugin operation wrapper containing the operation
203 */
204void
205cancel_anastasis_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
206{
207 // TODO: implement
208 return;
209}
210
211
212/**
213 * IdentityInitContinuation for the Anastasis plugin
214 */
215void
216anastasis_cont_init ()
217{
218 return;
219}
220
221
222/**
223 * Entry point for the plugin.
224 *
225 * @param cls Config info
226 *
227 * @return the exported block API
228 */
229void *
230libgnunet_plugin_escrow_anastasis_init (void *cls)
231{
232 struct GNUNET_ESCROW_KeyPluginFunctions *api;
233 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
234
235 api = GNUNET_new (struct GNUNET_ESCROW_KeyPluginFunctions);
236 api->start_key_escrow = &start_anastasis_key_escrow;
237 api->verify_key_escrow = &verify_anastasis_key_escrow;
238 api->restore_key = &restore_anastasis_key_escrow;
239 api->get_status = &anastasis_get_status;
240 api->anchor_string_to_data = &anastasis_anchor_string_to_data;
241 api->cancel_plugin_operation = &cancel_anastasis_operation;
242
243 ph.state = ESCROW_PLUGIN_STATE_INIT;
244 ph.id_init_cont = &anastasis_cont_init;
245
246 identity_handle = GNUNET_IDENTITY_connect (cfg,
247 &ESCROW_list_ego,
248 &ph);
249
250 return api;
251}
252
253
254/**
255 * Exit point from the plugin.
256 *
257 * @param cls the return value from #libgnunet_plugin_block_test_init()
258 *
259 * @return NULL
260 */
261void *
262libgnunet_plugin_escrow_anastasis_done (void *cls)
263{
264 struct GNUNET_RECLAIM_EscrowKeyPluginFunctions *api = cls;
265
266 GNUNET_free (api);
267 GNUNET_IDENTITY_disconnect (identity_handle);
268 ESCROW_cleanup_ego_list (&ph);
269
270 return NULL;
271}
272
273
274/* end of plugin_escrow_anastasis.c */
diff --git a/src/escrow/plugin_escrow_gns.c b/src/escrow/plugin_escrow_gns.c
new file mode 100644
index 000000000..4f9ce64a1
--- /dev/null
+++ b/src/escrow/plugin_escrow_gns.c
@@ -0,0 +1,1449 @@
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 escrow/plugin_escrow_gns.c
23 * @brief escrow-plugin-gns escrow plugin for the escrow of the key
24 * using GNS and escrow identities
25 *
26 * @author Johannes Späth
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_escrow_plugin.h"
31#include "escrow_plugin_helper.h"
32#include "gnunet_namestore_service.h"
33#include "gnunet_gns_service.h"
34#include "gnunet_gnsrecord_lib.h"
35#include "../identity/identity.h"
36#include <sss.h>
37#include <inttypes.h>
38
39
40/* declare this function here, as it is used by other functions above the definition */
41char *
42gns_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
43 struct GNUNET_ESCROW_Anchor *escrowAnchor);
44
45
46/**
47 * Continuation with a private key (used for restore_private_key)
48 */
49typedef void (*PkContinuation) (void *cls,
50 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk);
51
52
53struct IdentityOperationEntry
54{
55 /**
56 * DLL
57 */
58 struct IdentityOperationEntry *prev;
59
60 /**
61 * DLL
62 */
63 struct IdentityOperationEntry *next;
64
65 /**
66 * Identity operation
67 */
68 struct GNUNET_IDENTITY_Operation *id_op;
69
70 /**
71 * Private key of the respective ego
72 */
73 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
74
75 /**
76 * Name of the respective ego
77 */
78 const char *name;
79
80 /**
81 * Index of the respective share
82 */
83 uint8_t i;
84
85 /**
86 * The plugin operation that started the identity operation
87 */
88 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
89};
90
91
92struct PkEntry
93{
94 /**
95 * DLL
96 */
97 struct PkEntry *prev;
98
99 /**
100 * DLL
101 */
102 struct PkEntry *next;
103
104 /**
105 * private key
106 */
107 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
108
109 /**
110 * index of the respective share
111 */
112 uint8_t i;
113};
114
115
116struct NamestoreQueueEntry
117{
118 /**
119 * DLL
120 */
121 struct NamestoreQueueEntry *prev;
122
123 /**
124 * DLL
125 */
126 struct NamestoreQueueEntry *next;
127
128 /**
129 * Namestore queue entry
130 */
131 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
132
133 /**
134 * Plugin operation that called the namestore operation
135 */
136 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
137};
138
139
140struct GnsLookupRequestEntry
141{
142 /**
143 * DLL
144 */
145 struct GnsLookupRequestEntry *prev;
146
147 /**
148 * DLL
149 */
150 struct GnsLookupRequestEntry *next;
151
152 /**
153 * GNS lookup request
154 */
155 struct GNUNET_GNS_LookupRequest *lr;
156
157 /**
158 * Plugin operation that started the lookup
159 */
160 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
161
162 /**
163 * index of the respective share
164 */
165 uint8_t i;
166};
167
168
169struct ESCROW_GnsPluginOperation
170{
171 /**
172 * Handle for the escrow component
173 */
174 struct GNUNET_ESCROW_Handle *h;
175
176 /**
177 * Scheduler task the SCHEDULE operation returns (needed for cancellation)
178 */
179 struct GNUNET_SCHEDULER_Task *sched_task;
180
181 /**
182 * Namestore handle
183 */
184 struct GNUNET_NAMESTORE_Handle *ns_h;
185
186 /**
187 * GNS handle
188 */
189 struct GNUNET_GNS_Handle *gns_h;
190
191 /**
192 * Continuation for a plugin operation (e.g. used for restore, as this
193 * callback has to be called from the IDENTITY service after finishing)
194 */
195 ESCROW_Plugin_Continuation cont;
196
197 /**
198 * Ego continuation wrapper
199 */
200 struct ESCROW_Plugin_EgoContinuationWrapper *ego_wrap;
201
202 /**
203 * Anchor continuation wrapper
204 */
205 struct ESCROW_Plugin_AnchorContinuationWrapper *anchor_wrap;
206
207 /**
208 * Verify continuation wrapper
209 */
210 struct ESCROW_Plugin_VerifyContinuationWrapper *verify_wrap;
211
212 /**
213 * Counter for the created escrow identities
214 */
215 uint8_t escrow_id_counter;
216
217 /**
218 * Number of shares
219 */
220 uint8_t shares;
221
222 /**
223 * Share threshold
224 */
225 uint8_t share_threshold;
226
227 /**
228 * Continuation to be called with the restored private key
229 */
230 PkContinuation restore_pk_cont;
231
232 /**
233 * Closure for @a cont
234 */
235 void *restore_pk_cont_cls;
236
237 /**
238 * Array for the restored keyshares
239 */
240 sss_Keyshare *restored_keyshares;
241
242 /**
243 * Identity operation for the create of the restored ego
244 */
245 struct GNUNET_IDENTITY_Operation *id_op;
246
247 /**
248 * The ego
249 */
250 struct GNUNET_IDENTITY_Ego *ego;
251
252 /**
253 * The name of the ego
254 */
255 const char *egoName;
256
257 /**
258 * Private key of the ego
259 */
260 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
261
262 /**
263 * User secret string
264 */
265 char *userSecret;
266
267 /**
268 * DLL head for identity operations
269 */
270 struct IdentityOperationEntry *id_ops_head;
271
272 /**
273 * DLL tail for identity operations
274 */
275 struct IdentityOperationEntry *id_ops_tail;
276
277 /**
278 * DLL head for escrow private keys
279 */
280 struct PkEntry *escrow_pks_head;
281
282 /**
283 * DLL tail for escrow private keys
284 */
285 struct PkEntry *escrow_pks_tail;
286
287 /**
288 * DLL head for namestore queue entries
289 */
290 struct NamestoreQueueEntry *ns_qes_head;
291
292 /**
293 * DLL tail for namestore queue entries
294 */
295 struct NamestoreQueueEntry *ns_qes_tail;
296
297 /**
298 * DLL head for GNS lookup requests
299 */
300 struct GnsLookupRequestEntry *gns_lrs_head;
301
302 /**
303 * DLL tail for GNS lookup requests
304 */
305 struct GnsLookupRequestEntry *gns_lrs_tail;
306};
307
308/**
309 * Identity handle
310 */
311static struct GNUNET_IDENTITY_Handle *identity_handle;
312
313/**
314 * Handle for the plugin instance
315 */
316struct ESCROW_PluginHandle ph;
317
318
319/**
320 * Clean up a plugin operation, i.e. remove it from the list and
321 * free the respective memory
322 */
323void
324cleanup_plugin_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
325{
326 struct ESCROW_GnsPluginOperation *p_op;
327 struct IdentityOperationEntry *curr_id_op, *next_id_op;
328 struct PkEntry *curr_pk, *next_pk;
329 struct NamestoreQueueEntry *curr_ns_qe, *next_ns_qe;
330 struct GnsLookupRequestEntry *curr_gns_lr, *next_gns_lr;
331
332 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
333
334 GNUNET_CONTAINER_DLL_remove (ph.plugin_op_head,
335 ph.plugin_op_tail,
336 plugin_op_wrap);
337 if (NULL != p_op->anchor_wrap)
338 GNUNET_free (p_op->anchor_wrap);
339 if (NULL != p_op->ego_wrap)
340 GNUNET_free (p_op->ego_wrap);
341 if (NULL != p_op->verify_wrap)
342 GNUNET_free (p_op->verify_wrap);
343 if (NULL != p_op->userSecret)
344 GNUNET_free (p_op->userSecret);
345 /* clean up identity operation list */
346 for (curr_id_op = p_op->id_ops_head; NULL != curr_id_op; curr_id_op = next_id_op)
347 {
348 next_id_op = curr_id_op->next;
349 GNUNET_CONTAINER_DLL_remove (p_op->id_ops_head,
350 p_op->id_ops_tail,
351 curr_id_op);
352 GNUNET_IDENTITY_cancel (curr_id_op->id_op);
353 GNUNET_free (curr_id_op);
354 }
355 /* clean up escrow pk list */
356 for (curr_pk = p_op->escrow_pks_head; NULL != curr_pk; curr_pk = next_pk)
357 {
358 next_pk = curr_pk->next;
359 GNUNET_CONTAINER_DLL_remove (p_op->escrow_pks_head,
360 p_op->escrow_pks_tail,
361 curr_pk);
362 GNUNET_free (curr_pk);
363 }
364 /* clean up namestore operation list */
365 for (curr_ns_qe = p_op->ns_qes_head; NULL != curr_ns_qe; curr_ns_qe = next_ns_qe)
366 {
367 next_ns_qe = curr_ns_qe->next;
368 GNUNET_CONTAINER_DLL_remove (p_op->ns_qes_head,
369 p_op->ns_qes_tail,
370 curr_ns_qe);
371 // also frees the curr_ns_qe->ns_qe
372 GNUNET_NAMESTORE_cancel (curr_ns_qe->ns_qe);
373 GNUNET_free (curr_ns_qe);
374 }
375 /* clean up GNS lookup request list */
376 for (curr_gns_lr = p_op->gns_lrs_head; NULL != curr_gns_lr; curr_gns_lr = next_gns_lr)
377 {
378 next_gns_lr = curr_gns_lr->next;
379 GNUNET_CONTAINER_DLL_remove (p_op->gns_lrs_head,
380 p_op->gns_lrs_tail,
381 curr_gns_lr);
382 GNUNET_GNS_lookup_cancel (curr_gns_lr->lr);
383 GNUNET_free (curr_gns_lr);
384 }
385 /* free the keyshares array */
386 if (NULL != p_op->restored_keyshares)
387 GNUNET_free (p_op->restored_keyshares);
388 /* disconnect from namestore service */
389 if (NULL != p_op->ns_h)
390 GNUNET_NAMESTORE_disconnect (p_op->ns_h);
391 /* disconnect from GNS service */
392 if (NULL != p_op->gns_h)
393 GNUNET_GNS_disconnect (p_op->gns_h);
394 /* cancel scheduled task */
395 if (NULL != p_op->sched_task)
396 GNUNET_SCHEDULER_cancel (p_op->sched_task);
397 /* cancel identity operation */
398 if (NULL != p_op->id_op)
399 GNUNET_IDENTITY_cancel (p_op->id_op);
400 GNUNET_free (p_op);
401 GNUNET_free (plugin_op_wrap);
402}
403
404
405void
406start_cont (void *cls)
407{
408 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
409 struct ESCROW_GnsPluginOperation *p_op;
410
411 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
412 p_op->cont (p_op->anchor_wrap);
413
414 cleanup_plugin_operation (plugin_op_wrap);
415}
416
417
418sss_Keyshare *
419split_private_key (struct ESCROW_GnsPluginOperation *p_op)
420{
421 sss_Keyshare *keyshares;
422
423 keyshares = GNUNET_malloc (sizeof (sss_Keyshare) * p_op->shares);
424 sss_create_keyshares (keyshares,
425 p_op->pk->d,
426 p_op->shares,
427 p_op->share_threshold);
428
429 return keyshares;
430}
431
432
433static void
434keyshare_distribution_finished (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
435{
436 struct ESCROW_GnsPluginOperation *p_op;
437 struct GNUNET_ESCROW_Anchor *anchor;
438 int anchorDataSize;
439
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All keyshares distributed\n");
441
442 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
443
444 anchorDataSize = strlen(p_op->userSecret) + 1;
445 anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + anchorDataSize);
446 anchor->method = GNUNET_ESCROW_KEY_GNS;
447 anchor->size = anchorDataSize;
448 GNUNET_memcpy (&anchor[1], p_op->userSecret, anchorDataSize);
449
450 p_op->anchor_wrap->escrowAnchor = anchor;
451
452 /* set the last escrow time */
453 ESCROW_update_escrow_status (p_op->h, p_op->ego, "gns");
454
455 /* call the continuation */
456 start_cont (plugin_op_wrap);
457}
458
459
460static void
461keyshare_distributed (void *cls,
462 int32_t success,
463 const char *emsg)
464{
465 struct NamestoreQueueEntry *ns_qe = cls;
466 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
467 struct ESCROW_GnsPluginOperation *p_op;
468
469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Keyshare distributed\n");
470
471 plugin_op_wrap = ns_qe->plugin_op_wrap;
472 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
473
474 if (GNUNET_SYSERR == success)
475 {
476 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
477 "Failed to store keyshare %s\n",
478 emsg);
479 p_op->anchor_wrap->escrowAnchor = NULL;
480 p_op->anchor_wrap->emsg = _ ("Keyshare distribution failed!\n");
481 p_op->cont (p_op->anchor_wrap);
482 // this also cancels all running namestore operations
483 cleanup_plugin_operation (plugin_op_wrap);
484 }
485
486 // remove qe from list, check if all namestore operations are finished
487 GNUNET_CONTAINER_DLL_remove (p_op->ns_qes_head,
488 p_op->ns_qes_tail,
489 ns_qe);
490 GNUNET_free (ns_qe);
491 if (NULL == p_op->ns_qes_head)
492 keyshare_distribution_finished (plugin_op_wrap);
493}
494
495
496static char *
497get_label (const char *userSecret)
498{
499 char *label;
500 struct GNUNET_HashCode hash;
501 struct GNUNET_CRYPTO_HashAsciiEncoded hashEnc;
502
503 // the label is the hash of the userSecret
504 GNUNET_CRYPTO_hash (userSecret, strlen (userSecret), &hash);
505 GNUNET_CRYPTO_hash_to_enc (&hash, &hashEnc);
506 label = GNUNET_strdup ((char *)hashEnc.encoding);
507
508 return label;
509}
510
511
512static int
513distribute_keyshares (struct ESCROW_PluginOperationWrapper *plugin_op_wrap,
514 sss_Keyshare *keyshares)
515{
516 struct ESCROW_GnsPluginOperation *p_op;
517 struct GNUNET_NAMESTORE_Handle *ns_h;
518 struct NamestoreQueueEntry *curr_ns_qe;
519 struct PkEntry *curr_pk;
520 char *curr_label;
521 struct GNUNET_GNSRECORD_Data curr_rd[1];
522
523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Distributing keyshares\n");
524
525 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
526
527 ns_h = GNUNET_NAMESTORE_connect (p_op->h->cfg);
528 p_op->ns_h = ns_h;
529
530 for (curr_pk = p_op->escrow_pks_head; NULL != curr_pk; curr_pk = curr_pk->next)
531 {
532 curr_label = get_label (p_op->userSecret);
533 curr_ns_qe = GNUNET_new (struct NamestoreQueueEntry);
534
535 curr_rd[0].data_size = sizeof (sss_Keyshare);
536 curr_rd[0].data = keyshares[curr_pk->i];
537 curr_rd[0].record_type = GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE;
538 curr_rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
539 // TODO: config param?
540 curr_rd[0].expiration_time = 30 * 24 * GNUNET_TIME_relative_get_hour_().rel_value_us;
541
542 curr_ns_qe->plugin_op_wrap = plugin_op_wrap;
543 curr_ns_qe->ns_qe = GNUNET_NAMESTORE_records_store (ns_h,
544 curr_pk->pk,
545 curr_label,
546 1,
547 curr_rd,
548 &keyshare_distributed,
549 curr_ns_qe);
550 GNUNET_CONTAINER_DLL_insert_tail (p_op->ns_qes_head,
551 p_op->ns_qes_tail,
552 curr_ns_qe);
553 GNUNET_free (curr_label);
554 }
555
556 return GNUNET_OK;
557}
558
559
560void
561escrow_ids_finished (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
562{
563 struct ESCROW_GnsPluginOperation *p_op;
564 sss_Keyshare *keyshares;
565
566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All escrow identities created\n");
567
568 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
569
570 /* split the private key (SSS) */
571 keyshares = split_private_key (p_op);
572 if (NULL == keyshares)
573 {
574 p_op->anchor_wrap->escrowAnchor = NULL;
575 p_op->anchor_wrap->emsg = _ ("Failed to split the key!\n");
576 start_cont (plugin_op_wrap);
577 return;
578 }
579
580 /* distribute the shares to the identities */
581 if (GNUNET_OK != distribute_keyshares (plugin_op_wrap, keyshares))
582 {
583 p_op->anchor_wrap->escrowAnchor = NULL;
584 p_op->anchor_wrap->emsg = _ ("Failed to distribute the keyshares!\n");
585 start_cont (plugin_op_wrap);
586 return;
587 }
588
589 /* operation continues in keyshare_distribution_finished
590 after all keyshares have been distributed */
591}
592
593
594void
595escrow_id_created (void *cls,
596 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
597 const char *emsg)
598{
599 struct IdentityOperationEntry *id_op = cls;
600 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
601 struct ESCROW_GnsPluginOperation *p_op;
602 struct PkEntry *pk_entry;
603
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Escrow identity %d created\n", id_op->i);
605
606 plugin_op_wrap = id_op->plugin_op_wrap;
607 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
608
609 if (NULL == pk)
610 {
611 if (NULL != emsg)
612 {
613 fprintf (stderr,
614 "Identity create operation returned with error: %s\n",
615 emsg);
616 p_op->anchor_wrap->emsg = _ ("Identity create failed!\n");
617 }
618 else
619 p_op->anchor_wrap->emsg = _ ("Failed to create ego!\n");
620 p_op->anchor_wrap->escrowAnchor = NULL;
621 p_op->cont (p_op->anchor_wrap);
622 // this also cancels all running identity operations
623 cleanup_plugin_operation (plugin_op_wrap);
624 return;
625 }
626
627 /* escrow identity successfully created */
628 GNUNET_CONTAINER_DLL_remove (p_op->id_ops_head,
629 p_op->id_ops_tail,
630 id_op);
631
632 /* insert pk into our list */
633 pk_entry = GNUNET_new (struct PkEntry);
634 pk_entry->pk = pk;
635 pk_entry->i = id_op->i;
636 GNUNET_CONTAINER_DLL_insert_tail (p_op->escrow_pks_head,
637 p_op->escrow_pks_tail,
638 pk_entry);
639
640 GNUNET_free (id_op);
641
642 /* check if this was the last id_op */
643 p_op->escrow_id_counter++;
644 if (p_op->escrow_id_counter == p_op->shares)
645 {
646 escrow_ids_finished (plugin_op_wrap);
647 }
648}
649
650
651static uint8_t
652count_digits (uint8_t n)
653{
654 uint8_t i = 0;
655
656 do
657 {
658 i++;
659 n /= 10;
660 } while (n != 0);
661
662 return i;
663}
664
665
666static char *
667get_escrow_id_name (const char *name,
668 uint8_t i)
669{
670 char *str, *prefix, *number;
671 uint8_t j = 0;
672
673 prefix = "escrow-id_";
674 number = GNUNET_malloc (count_digits (i) + 1);
675 sprintf (number, "%d", i);
676
677 str = GNUNET_malloc (strlen (prefix)
678 + strlen (name)
679 + 1
680 + strlen (number)
681 + 1);
682
683 memcpy (str, prefix, strlen (prefix));
684 j += strlen (prefix);
685 memcpy (str + j, name, strlen (name));
686 j += strlen (name);
687 str[j++] = '_';
688 memcpy (str + j, number, strlen (number));
689 j += strlen (number);
690 str[j] = '\0';
691
692 GNUNET_free (number);
693
694 return str;
695}
696
697
698static int
699escrow_id_exists (const char *name,
700 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
701{
702 struct EgoEntry *curr;
703
704 for (curr = ph.ego_head; NULL != curr; curr = curr->next)
705 {
706 if (0 == strcmp (name, curr->identifier))
707 {
708 if (0 == memcmp (&curr->ego->pk,
709 pk,
710 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
711 return GNUNET_YES;
712 else // the escrow id's name exists for an ego, but the pk is wrong
713 return GNUNET_SYSERR;
714 }
715 }
716
717 return GNUNET_NO;
718}
719
720
721static struct GNUNET_CRYPTO_EcdsaPrivateKey *
722derive_private_key (const char *name,
723 const char *password,
724 uint8_t i)
725{
726 struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
727 static const char ctx[] = "gnunet-escrow-id-ctx";
728
729 pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
730 GNUNET_CRYPTO_kdf (pk,
731 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
732 ctx, strlen (ctx),
733 password, strlen (password),
734 name, strlen (name),
735 &i, 1,
736 NULL);
737
738 pk->d[0] &= 248;
739 pk->d[31] &= 127;
740 pk->d[31] |= 64;
741
742 return pk;
743}
744
745
746static void
747handle_existing_wrong_ego_deletion (void *cls,
748 const char *emsg)
749{
750 struct IdentityOperationEntry *curr_id_op = cls;
751 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
752 struct ESCROW_GnsPluginOperation *p_op;
753
754 plugin_op_wrap = curr_id_op->plugin_op_wrap;
755 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
756
757 if (NULL != emsg)
758 {
759 fprintf (stderr,
760 "Identity create operation returned with error: %s\n",
761 emsg);
762 p_op->anchor_wrap->emsg = _ ("Identity delete of wrong existing ego failed!\n");
763 p_op->anchor_wrap->escrowAnchor = NULL;
764 p_op->cont (p_op->anchor_wrap);
765 // this also cancels all running identity operations
766 cleanup_plugin_operation (plugin_op_wrap);
767 return;
768 }
769
770 /* no error occured, so create the new identity */
771 // the IdentityOperationEntry is reused, so only the id_op is updated
772 curr_id_op->id_op = GNUNET_IDENTITY_create (identity_handle,
773 curr_id_op->name,
774 curr_id_op->pk,
775 &escrow_id_created,
776 curr_id_op);
777}
778
779
780static void
781create_escrow_identities (struct ESCROW_PluginOperationWrapper *plugin_op_wrap,
782 const char *name)
783{
784 struct ESCROW_GnsPluginOperation *p_op;
785 struct GNUNET_CRYPTO_EcdsaPrivateKey *curr_pk;
786 char *curr_name;
787 struct IdentityOperationEntry *curr_id_op;
788 struct PkEntry *curr_pk_entry;
789 int exists_ret;
790
791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating escrow identities\n");
792
793 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
794
795 for (uint8_t i = 0; i < p_op->shares; i++)
796 {
797 curr_pk = derive_private_key (name, p_op->userSecret, i);
798 curr_name = get_escrow_id_name (name, i);
799
800 // check if the escrow identity already exists
801 exists_ret = escrow_id_exists (curr_name, curr_pk);
802 if (GNUNET_SYSERR == exists_ret)
803 {
804 /* an ego with identifier name but the wrong pk exists, delete it first */
805 curr_id_op = GNUNET_new (struct IdentityOperationEntry);
806 curr_id_op->pk = curr_pk;
807 curr_id_op->name = curr_name;
808 curr_id_op->i = i;
809 curr_id_op->plugin_op_wrap = plugin_op_wrap;
810 curr_id_op->id_op = GNUNET_IDENTITY_delete (identity_handle,
811 curr_name,
812 &handle_existing_wrong_ego_deletion,
813 curr_id_op);
814 GNUNET_CONTAINER_DLL_insert (p_op->id_ops_head,
815 p_op->id_ops_tail,
816 curr_id_op);
817 }
818 else if (GNUNET_YES == exists_ret)
819 {
820 // the escrow id already exists, so insert the pk into our list
821 curr_pk_entry = GNUNET_new (struct PkEntry);
822 curr_pk_entry->pk = curr_pk;
823 curr_pk_entry->i = i;
824 GNUNET_CONTAINER_DLL_insert (p_op->escrow_pks_head,
825 p_op->escrow_pks_tail,
826 curr_pk_entry);
827
828 p_op->escrow_id_counter++;
829 if (p_op->escrow_id_counter == p_op->shares)
830 {
831 escrow_ids_finished (plugin_op_wrap);
832 }
833 }
834 else // GNUNET_NO
835 {
836 /* store the identity operation in our list */
837 curr_id_op = GNUNET_new (struct IdentityOperationEntry);
838 curr_id_op->pk = curr_pk;
839 curr_id_op->name = curr_name;
840 curr_id_op->i = i;
841 curr_id_op->plugin_op_wrap = plugin_op_wrap;
842 curr_id_op->id_op = GNUNET_IDENTITY_create (identity_handle,
843 curr_name,
844 curr_pk,
845 &escrow_id_created,
846 curr_id_op);
847 GNUNET_CONTAINER_DLL_insert (p_op->id_ops_head,
848 p_op->id_ops_tail,
849 curr_id_op);
850 }
851 }
852}
853
854
855void
856continue_start (void *cls)
857{
858 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
859 struct ESCROW_GnsPluginOperation *p_op;
860 unsigned long long shares, share_threshold;
861 struct GNUNET_TIME_Relative delay;
862
863 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
864
865 if (ESCROW_PLUGIN_STATE_POST_INIT != ph.state)
866 {
867 delay.rel_value_us = 200 * GNUNET_TIME_relative_get_millisecond_().rel_value_us;
868 GNUNET_SCHEDULER_add_delayed (delay, &continue_start, plugin_op_wrap);
869 return;
870 }
871
872 // get config
873 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (p_op->h->cfg,
874 "escrow",
875 "gns_shares",
876 &shares))
877 {
878 fprintf (stderr, "Number of shares not specified in config!");
879 p_op->anchor_wrap->escrowAnchor = NULL;
880 p_op->sched_task = GNUNET_SCHEDULER_add_now (&start_cont, plugin_op_wrap);
881 return;
882 }
883 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (p_op->h->cfg,
884 "escrow",
885 "gns_share_threshold",
886 &share_threshold))
887 {
888 fprintf (stderr, "Share threshold not specified in config");
889 p_op->anchor_wrap->escrowAnchor = NULL;
890 p_op->sched_task = GNUNET_SCHEDULER_add_now (&start_cont, plugin_op_wrap);
891 return;
892 }
893 p_op->shares = (uint8_t)shares;
894 p_op->share_threshold = (uint8_t)share_threshold;
895
896 /* create the escrow identities */
897 create_escrow_identities (plugin_op_wrap, p_op->ego->name);
898
899 /* operation continues in escrow_ids_finished
900 after all escrow identities are created */
901}
902
903
904/**
905 * Start the GNS escrow of the key
906 *
907 * @param h the handle for the escrow component
908 * @param ego the identity ego containing the private key
909 * @param userSecret the user secret (e.g. for derivation of escrow identities)
910 * @param cb the function called upon completion
911 * @param op_id unique ID of the respective ESCROW_Operation
912 *
913 * @return plugin operation wrapper
914 */
915struct ESCROW_PluginOperationWrapper *
916start_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
917 struct GNUNET_IDENTITY_Ego *ego,
918 const char *userSecret,
919 GNUNET_SCHEDULER_TaskCallback cb,
920 uint32_t op_id)
921{
922 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
923 struct ESCROW_GnsPluginOperation *p_op;
924 struct ESCROW_Plugin_AnchorContinuationWrapper *w;
925 struct GNUNET_TIME_Relative delay;
926
927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting GNS escrow\n");
928
929 // create a new GNS plugin operation (in a wrapper) and insert it into the DLL
930 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
931 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
932 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
933 ph.plugin_op_tail,
934 plugin_op_wrap);
935
936 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
937 p_op->h = h;
938 p_op->cont = cb;
939 p_op->ego = ego;
940
941 w = GNUNET_new (struct ESCROW_Plugin_AnchorContinuationWrapper);
942 w->h = h;
943 w->op_id = op_id;
944 p_op->anchor_wrap = w;
945
946 if (NULL == ego || NULL == userSecret)
947 {
948 w->escrowAnchor = NULL;
949 if (NULL == ego)
950 w->emsg = _ ("ESCROW_put was called with ego == NULL\n");
951 else if (NULL == userSecret)
952 w->emsg = _ ("GNS escrow needs a user secret!\n");
953 p_op->sched_task = GNUNET_SCHEDULER_add_now (&start_cont, plugin_op_wrap);
954 return plugin_op_wrap;
955 }
956 p_op->pk = GNUNET_IDENTITY_ego_get_private_key (ego);
957 p_op->userSecret = GNUNET_strdup (userSecret);
958
959 if (ESCROW_PLUGIN_STATE_POST_INIT == ph.state)
960 {
961 continue_start (plugin_op_wrap);
962 }
963 else
964 {
965 delay.rel_value_us = 200 * GNUNET_TIME_relative_get_millisecond_().rel_value_us;
966 GNUNET_SCHEDULER_add_delayed (delay, &continue_start, plugin_op_wrap);
967 }
968
969 return plugin_op_wrap;
970}
971
972
973static void
974process_keyshares (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
975{
976 struct ESCROW_GnsPluginOperation *p_op;
977 struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
978
979 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
980
981 // TODO: check if enough keyshares have been restored, combine them
982
983 p_op->restore_pk_cont (p_op->restore_pk_cont_cls, pk);
984}
985
986
987static void
988process_gns_lookup_result (void *cls,
989 uint32_t rd_count,
990 const struct GNUNET_GNSRECORD_Data *rd)
991{
992 struct GnsLookupRequestEntry *gns_lr = cls;
993 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
994 struct ESCROW_GnsPluginOperation *p_op;
995 sss_Keyshare keyshare;
996
997 plugin_op_wrap = gns_lr->plugin_op_wrap;
998 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
999
1000 // TODO: handle result, store keyshare, check if this was the last keyshare
1001 GNUNET_memcpy (p_op->restored_keyshares[gns_lr->i],
1002 keyshare,
1003 sizeof (sss_Keyshare));
1004
1005 if (1) // TODO: last keyshare?
1006 process_keyshares(plugin_op_wrap);
1007}
1008
1009
1010static void
1011restore_private_key (struct ESCROW_PluginOperationWrapper *plugin_op_wrap,
1012 struct GNUNET_ESCROW_Anchor *escrowAnchor,
1013 PkContinuation cont,
1014 void *cont_cls)
1015{
1016 struct ESCROW_GnsPluginOperation *p_op;
1017 struct GNUNET_CRYPTO_EcdsaPrivateKey *curr_escrow_pk, *ego_pk;
1018 struct GNUNET_CRYPTO_EcdsaPublicKey curr_escrow_pub;
1019 char *curr_escrow_name;
1020 struct GnsLookupRequestEntry *curr_gns_lr;
1021
1022 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1023
1024 p_op->gns_h = GNUNET_GNS_connect (p_op->h->cfg);
1025 p_op->restore_pk_cont = cont;
1026 p_op->restore_pk_cont_cls = cont_cls;
1027 p_op->restored_keyshares = GNUNET_malloc (sizeof (sss_Keyshare) * p_op->shares);
1028
1029 for (uint8_t i = 0; i < p_op->shares; i++)
1030 {
1031 curr_escrow_pk = derive_private_key (p_op->ego->name, p_op->userSecret, i);
1032 curr_escrow_name = get_escrow_id_name (p_op->ego->name, i);
1033
1034 curr_gns_lr = GNUNET_new (struct GnsLookupRequestEntry);
1035 curr_gns_lr->plugin_op_wrap = plugin_op_wrap;
1036 curr_gns_lr->i = i;
1037 GNUNET_CRYPTO_ecdsa_key_get_public (curr_escrow_pk, &curr_escrow_pub);
1038 curr_gns_lr->lr = GNUNET_GNS_lookup (p_op->gns_h,
1039 NULL, // TODO: name
1040 &curr_escrow_pub,
1041 GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE,
1042 GNUNET_GNS_LO_DEFAULT,
1043 &process_gns_lookup_result,
1044 curr_gns_lr);
1045 GNUNET_CONTAINER_DLL_insert_tail (p_op->gns_lrs_head,
1046 p_op->gns_lrs_tail,
1047 curr_gns_lr);
1048 }
1049}
1050
1051
1052void
1053verify_cont (void *cls)
1054{
1055 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1056 struct ESCROW_GnsPluginOperation *p_op;
1057
1058 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1059 p_op->cont (p_op->verify_wrap);
1060
1061 cleanup_plugin_operation (plugin_op_wrap);
1062}
1063
1064
1065static void
1066verify_restored_pk (void *cls,
1067 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
1068{
1069 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1070 struct ESCROW_GnsPluginOperation *p_op;
1071 const struct GNUNET_CRYPTO_EcdsaPrivateKey *ego_pk;
1072 char *ego_pk_string;
1073 int verificationResult;
1074
1075 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1076
1077 ego_pk = GNUNET_IDENTITY_ego_get_private_key (p_op->ego);
1078 ego_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (ego_pk);
1079 verificationResult = memcmp (pk,
1080 ego_pk,
1081 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
1082 == 0 ? GNUNET_ESCROW_VALID : GNUNET_ESCROW_INVALID;
1083
1084 p_op->verify_wrap->verificationResult = verificationResult;
1085 verify_cont (plugin_op_wrap);
1086}
1087
1088
1089/**
1090 * Verify the GNS escrow of the key
1091 *
1092 * @param h the handle for the escrow component
1093 * @param ego the identity ego containing the private key
1094 * @param escrowAnchor the escrow anchor needed to restore the key
1095 * @param cb the function called upon completion
1096 * @param op_id unique ID of the respective ESCROW_Operation
1097 *
1098 * @return plugin operation wrapper
1099 */
1100struct ESCROW_PluginOperationWrapper *
1101verify_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
1102 struct GNUNET_IDENTITY_Ego *ego,
1103 struct GNUNET_ESCROW_Anchor *escrowAnchor,
1104 GNUNET_SCHEDULER_TaskCallback cb,
1105 uint32_t op_id)
1106{
1107 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
1108 struct ESCROW_GnsPluginOperation *p_op;
1109 struct ESCROW_Plugin_VerifyContinuationWrapper *w;
1110
1111 // create a new GNS plugin operation (in a wrapper) and insert it into the DLL
1112 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
1113 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
1114 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
1115 ph.plugin_op_tail,
1116 plugin_op_wrap);
1117
1118 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1119 p_op->h = h;
1120 p_op->cont = cb;
1121 p_op->ego = ego;
1122 p_op->userSecret = gns_anchor_data_to_string (h, escrowAnchor);
1123
1124 w = GNUNET_new (struct ESCROW_Plugin_VerifyContinuationWrapper);
1125 w->h = h;
1126 w->op_id = op_id;
1127 p_op->verify_wrap = w;
1128
1129 if (NULL == ego)
1130 {
1131 w->verificationResult = GNUNET_ESCROW_INVALID;
1132 w->emsg = _ ("ESCROW_verify was called with ego == NULL!\n");
1133 p_op->sched_task = GNUNET_SCHEDULER_add_now (&verify_cont, plugin_op_wrap);
1134 return plugin_op_wrap;
1135 }
1136
1137 restore_private_key (plugin_op_wrap,
1138 escrowAnchor,
1139 &verify_restored_pk,
1140 plugin_op_wrap);
1141
1142 return plugin_op_wrap;
1143}
1144
1145
1146void
1147ego_created (const struct GNUNET_IDENTITY_Ego *ego)
1148{
1149 struct ESCROW_PluginOperationWrapper *curr;
1150 struct ESCROW_GnsPluginOperation *curr_p_op;
1151 char *ego_pk_string, *curr_pk_string;
1152
1153 ego_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (&ego->pk);
1154
1155 for (curr = ph.plugin_op_head; NULL != curr; curr = curr->next)
1156 {
1157 curr_p_op = (struct ESCROW_GnsPluginOperation *)curr->plugin_op;
1158 curr_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (curr_p_op->pk);
1159 // compare the strings of the private keys
1160 if (0 == strcmp (ego_pk_string, curr_pk_string))
1161 {
1162 // the ego was created due to a restore operation that is not yet finished
1163 curr_p_op->ego_wrap->ego = ego;
1164 curr_p_op->cont (curr_p_op->ego_wrap);
1165
1166 cleanup_plugin_operation (curr);
1167
1168 GNUNET_free (curr_pk_string);
1169 GNUNET_free (ego_pk_string);
1170 return;
1171 }
1172 GNUNET_free (curr_pk_string);
1173 }
1174 GNUNET_free (ego_pk_string);
1175}
1176
1177
1178static void
1179handle_restore_error (void *cls)
1180{
1181 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1182 struct ESCROW_GnsPluginOperation *p_op;
1183
1184 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1185 p_op->cont (p_op->ego_wrap);
1186
1187 cleanup_plugin_operation (plugin_op_wrap);
1188}
1189
1190
1191static void
1192id_create_finished (void *cls,
1193 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
1194 const char *emsg)
1195{
1196 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1197 struct ESCROW_GnsPluginOperation *p_op;
1198
1199 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1200
1201 if (NULL == pk)
1202 {
1203 if (NULL != emsg)
1204 {
1205 fprintf (stderr,
1206 "Identity create operation returned with error: %s\n",
1207 emsg);
1208 p_op->ego_wrap->emsg = _ ("Identity create failed!\n");
1209 }
1210 else
1211 p_op->ego_wrap->emsg = _ ("Failed to create ego!\n");
1212 p_op->ego_wrap->ego = NULL;
1213 p_op->cont (p_op->ego_wrap);
1214 return;
1215 }
1216
1217 /* no error occurred, p_op->restore_cont will be called in ego_created, which
1218 is called from ESCROW_list_ego after adding the new ego to our list */
1219 p_op->pk = pk;
1220}
1221
1222
1223static void
1224restore_ego_from_pk (void *cls,
1225 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
1226{
1227 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1228 struct ESCROW_GnsPluginOperation *p_op;
1229
1230 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1231
1232 p_op->id_op = GNUNET_IDENTITY_create (identity_handle,
1233 p_op->egoName,
1234 pk,
1235 &id_create_finished,
1236 plugin_op_wrap);
1237}
1238
1239
1240/**
1241 * Restore the key from GNS escrow
1242 *
1243 * @param h the handle for the escrow component
1244 * @param escrowAnchor the escrow anchor needed to restore the key
1245 * @param egoName the name of the ego to restore
1246 * @param cb the function called upon completion
1247 * @param op_id unique ID of the respective ESCROW_Operation
1248 *
1249 * @return plugin operation wrapper
1250 */
1251struct ESCROW_PluginOperationWrapper *
1252restore_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
1253 struct GNUNET_ESCROW_Anchor *escrowAnchor,
1254 const char *egoName,
1255 GNUNET_SCHEDULER_TaskCallback cb,
1256 uint32_t op_id)
1257{
1258 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
1259 struct ESCROW_GnsPluginOperation *p_op;
1260 struct ESCROW_Plugin_EgoContinuationWrapper *w;
1261
1262 // create a new GNS plugin operation (in a wrapper) and insert it into the DLL
1263 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
1264 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
1265 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
1266 ph.plugin_op_tail,
1267 plugin_op_wrap);
1268
1269 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1270 p_op->h = h;
1271 // set cont here (has to be scheduled from the IDENTITY service when it finished)
1272 p_op->cont = cb;
1273 p_op->egoName = egoName;
1274 p_op->userSecret = gns_anchor_data_to_string (h, escrowAnchor);
1275
1276 w = GNUNET_new (struct ESCROW_Plugin_EgoContinuationWrapper);
1277 w->h = h;
1278 w->op_id = op_id;
1279 p_op->ego_wrap = w;
1280
1281 if (NULL == escrowAnchor)
1282 {
1283 w->ego = NULL;
1284 w->emsg = _ ("ESCROW_get was called with escrowAnchor == NULL!\n");
1285 // schedule handle_restore_error, which calls the callback and cleans up
1286 p_op->sched_task = GNUNET_SCHEDULER_add_now (&handle_restore_error, plugin_op_wrap);
1287 return plugin_op_wrap;
1288 }
1289
1290 restore_private_key (plugin_op_wrap,
1291 escrowAnchor,
1292 &restore_ego_from_pk,
1293 plugin_op_wrap);
1294
1295 return plugin_op_wrap;
1296}
1297
1298
1299/**
1300 * Get the status of a GNS escrow
1301 *
1302 * @param h the handle for the escrow component
1303 * @param ego the identity ego of which the status has to be obtained
1304 *
1305 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
1306 */
1307struct GNUNET_ESCROW_Status *
1308gns_get_status (struct GNUNET_ESCROW_Handle *h,
1309 struct GNUNET_IDENTITY_Ego *ego)
1310{
1311 return ESCROW_get_escrow_status (h, ego);
1312}
1313
1314
1315/**
1316 * Deserialize an escrow anchor string into a GNUNET_ESCROW_Anchor struct
1317 *
1318 * @param anchorString the encoded escrow anchor string
1319 *
1320 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
1321 */
1322struct GNUNET_ESCROW_Anchor *
1323gns_anchor_string_to_data (struct GNUNET_ESCROW_Handle *h,
1324 char *anchorString)
1325{
1326 struct GNUNET_ESCROW_Anchor *anchor;
1327 uint32_t data_size;
1328
1329 data_size = strlen (anchorString) + 1;
1330
1331 anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + data_size);
1332 anchor->size = data_size;
1333 // TODO: deserialize?
1334 GNUNET_memcpy (&anchor[1], anchorString, data_size);
1335
1336 return anchor;
1337}
1338
1339
1340/**
1341 * Serialize an escrow anchor struct into a string
1342 *
1343 * @param h the handle for the escrow component
1344 * @param escrowAnchor the escrow anchor struct
1345 *
1346 * @return the encoded escrow anchor string
1347 */
1348char *
1349gns_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
1350 struct GNUNET_ESCROW_Anchor *escrowAnchor)
1351{
1352 char *anchorString;
1353
1354 anchorString = GNUNET_malloc (escrowAnchor->size);
1355 GNUNET_memcpy (anchorString, &escrowAnchor[1], escrowAnchor->size);
1356
1357 return anchorString;
1358}
1359
1360
1361/**
1362 * Cancel a GNS plugin operation.
1363 *
1364 * @param plugin_op_wrap the plugin operation wrapper containing the operation
1365 */
1366void
1367cancel_gns_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
1368{
1369 struct ESCROW_PluginOperationWrapper *curr;
1370
1371 for (curr = ph.plugin_op_head; NULL != curr; curr = curr->next)
1372 {
1373 if (curr == plugin_op_wrap)
1374 {
1375 GNUNET_CONTAINER_DLL_remove (ph.plugin_op_head,
1376 ph.plugin_op_tail,
1377 curr);
1378 cleanup_plugin_operation (curr);
1379 return;
1380 }
1381 }
1382}
1383
1384
1385/**
1386 * IdentityInitContinuation for the GNS plugin
1387 */
1388void
1389gns_cont_init ()
1390{
1391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS plugin initialized");
1392}
1393
1394
1395/**
1396 * Entry point for the plugin.
1397 *
1398 * @param cls Config info
1399 *
1400 * @return the exported block API
1401 */
1402void *
1403libgnunet_plugin_escrow_gns_init (void *cls)
1404{
1405 struct GNUNET_ESCROW_KeyPluginFunctions *api;
1406 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1407
1408 api = GNUNET_new (struct GNUNET_ESCROW_KeyPluginFunctions);
1409 api->start_key_escrow = &start_gns_key_escrow;
1410 api->verify_key_escrow = &verify_gns_key_escrow;
1411 api->restore_key = &restore_gns_key_escrow;
1412 api->get_status = &gns_get_status;
1413 api->anchor_string_to_data = &gns_anchor_string_to_data;
1414 api->anchor_data_to_string = &gns_anchor_data_to_string;
1415 api->cancel_plugin_operation = &cancel_gns_operation;
1416
1417 ph.state = ESCROW_PLUGIN_STATE_INIT;
1418 ph.id_init_cont = &gns_cont_init;
1419
1420 ph.ego_create_cont = &ego_created;
1421 identity_handle = GNUNET_IDENTITY_connect (cfg,
1422 &ESCROW_list_ego,
1423 &ph);
1424
1425 return api;
1426}
1427
1428
1429/**
1430 * Exit point from the plugin.
1431 *
1432 * @param cls the return value from #libgnunet_plugin_block_test_init()
1433 *
1434 * @return NULL
1435 */
1436void *
1437libgnunet_plugin_escrow_gns_done (void *cls)
1438{
1439 struct GNUNET_RECLAIM_EscrowKeyPluginFunctions *api = cls;
1440
1441 GNUNET_free (api);
1442 GNUNET_IDENTITY_disconnect (identity_handle);
1443 ESCROW_cleanup_ego_list (&ph);
1444
1445 return NULL;
1446}
1447
1448
1449/* end of plugin_escrow_gns.c */
diff --git a/src/escrow/plugin_escrow_plaintext.c b/src/escrow/plugin_escrow_plaintext.c
new file mode 100644
index 000000000..4acc3bc47
--- /dev/null
+++ b/src/escrow/plugin_escrow_plaintext.c
@@ -0,0 +1,584 @@
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 escrow/plugin_escrow_plaintext.c
23 * @brief escrow-plugin-plaintext escrow plugin for plaintext escrow of the key
24 *
25 * @author Johannes Späth
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_escrow_plugin.h"
30#include "escrow_plugin_helper.h"
31#include "gnunet_identity_service.h"
32#include "../identity/identity.h"
33#include "escrow.h"
34#include <inttypes.h>
35
36
37struct ESCROW_PlaintextPluginOperation
38{
39 /**
40 * Handle for the escrow component
41 */
42 struct GNUNET_ESCROW_Handle *h;
43
44 /**
45 * Scheduler task the SCHEDULE operation returns (needed for cancellation)
46 */
47 struct GNUNET_SCHEDULER_Task *sched_task;
48
49 /**
50 * Identity operation
51 */
52 struct GNUNET_IDENTITY_Operation *id_op;
53
54 /**
55 * Private key of the created ego
56 */
57 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
58
59 /**
60 * Continuation for a plugin operation (e.g. used for restore, as this
61 * callback has to be called from the IDENTITY service after finishing)
62 */
63 ESCROW_Plugin_Continuation cont;
64
65 /**
66 * Ego continuation wrapper
67 */
68 struct ESCROW_Plugin_EgoContinuationWrapper *ego_wrap;
69
70 /**
71 * Anchor continuation wrapper
72 */
73 struct ESCROW_Plugin_AnchorContinuationWrapper *anchor_wrap;
74
75 /**
76 * Verify continuation wrapper
77 */
78 struct ESCROW_Plugin_VerifyContinuationWrapper *verify_wrap;
79};
80
81/**
82 * Identity handle
83 */
84static struct GNUNET_IDENTITY_Handle *identity_handle;
85
86/**
87 * Handle for the plugin instance
88 */
89struct ESCROW_PluginHandle ph;
90
91
92/**
93 * Clean up a plugin operation, i.e. remove it from the list and
94 * free the respective memory
95 */
96void
97cleanup_plugin_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
98{
99 struct ESCROW_PlaintextPluginOperation *p_op;
100
101 p_op = (struct ESCROW_PlaintextPluginOperation*)plugin_op_wrap->plugin_op;
102
103 GNUNET_CONTAINER_DLL_remove (ph.plugin_op_head,
104 ph.plugin_op_tail,
105 plugin_op_wrap);
106 if (NULL != p_op->anchor_wrap)
107 GNUNET_free (p_op->anchor_wrap);
108 if (NULL != p_op->ego_wrap)
109 GNUNET_free (p_op->ego_wrap);
110 if (NULL != p_op->verify_wrap)
111 GNUNET_free (p_op->verify_wrap);
112 GNUNET_free (p_op);
113 GNUNET_free (plugin_op_wrap);
114}
115
116
117void
118start_cont (void *cls)
119{
120 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
121 struct ESCROW_PlaintextPluginOperation *p_op;
122
123 p_op = (struct ESCROW_PlaintextPluginOperation*)plugin_op_wrap->plugin_op;
124 p_op->cont (p_op->anchor_wrap);
125
126 cleanup_plugin_operation (plugin_op_wrap);
127}
128
129
130/**
131 * Start the plaintext escrow of the key, i.e. simply hand out the key
132 *
133 * @param h the handle for the escrow component
134 * @param ego the identity ego containing the private key
135 * @param userSecret the user secret (e.g. for derivation of escrow identities)
136 * @param cb the function called upon completion
137 * @param op_id unique ID of the respective ESCROW_Operation
138 *
139 * @return plugin operation wrapper
140 */
141struct ESCROW_PluginOperationWrapper *
142start_plaintext_key_escrow (struct GNUNET_ESCROW_Handle *h,
143 struct GNUNET_IDENTITY_Ego *ego,
144 const char *userSecret,
145 ESCROW_Plugin_Continuation cb,
146 uint32_t op_id)
147{
148 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
149 struct GNUNET_ESCROW_Anchor *anchor;
150 char *pkString;
151 uint32_t anchorDataSize;
152 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
153 struct ESCROW_PlaintextPluginOperation *p_op;
154 struct ESCROW_Plugin_AnchorContinuationWrapper *w;
155
156 // create a new plaintext plugin operation (in a wrapper) and insert it into the DLL
157 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
158 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_PlaintextPluginOperation);
159 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
160 ph.plugin_op_tail,
161 plugin_op_wrap);
162
163 p_op = (struct ESCROW_PlaintextPluginOperation *)plugin_op_wrap->plugin_op;
164 p_op->h = h;
165 p_op->cont = cb;
166
167 w = GNUNET_new (struct ESCROW_Plugin_AnchorContinuationWrapper);
168 w->h = h;
169 w->op_id = op_id;
170 p_op->anchor_wrap = w;
171
172 if (NULL == ego)
173 {
174 w->escrowAnchor = NULL;
175 w->emsg = _ ("ESCROW_put was called with ego == NULL!\n");
176 p_op->sched_task = GNUNET_SCHEDULER_add_now (&start_cont, plugin_op_wrap);
177 return plugin_op_wrap;
178 }
179 pk = GNUNET_IDENTITY_ego_get_private_key (ego);
180 pkString = GNUNET_CRYPTO_ecdsa_private_key_to_string (pk);
181
182 anchorDataSize = strlen (pkString) + 1;
183 anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + anchorDataSize);
184 anchor->method = GNUNET_ESCROW_KEY_PLAINTEXT;
185 anchor->size = anchorDataSize;
186 GNUNET_memcpy (&anchor[1], pkString, anchorDataSize);
187
188 w->escrowAnchor = anchor;
189
190 /* set the last escrow time */
191 ESCROW_update_escrow_status (h, ego, "plaintext");
192
193 p_op->sched_task = GNUNET_SCHEDULER_add_now (&start_cont, plugin_op_wrap);
194 return plugin_op_wrap;
195}
196
197
198void
199verify_cont (void *cls)
200{
201 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
202 struct ESCROW_PlaintextPluginOperation *p_op;
203
204 p_op = (struct ESCROW_PlaintextPluginOperation*)plugin_op_wrap->plugin_op;
205 p_op->cont (p_op->verify_wrap);
206
207 cleanup_plugin_operation (plugin_op_wrap);
208}
209
210
211/**
212 * Verify the plaintext escrow of the key
213 *
214 * @param h the handle for the escrow component
215 * @param ego the identity ego containing the private key
216 * @param escrowAnchor the escrow anchor needed to restore the key
217 * @param cb the function called upon completion
218 * @param op_id unique ID of the respective ESCROW_Operation
219 *
220 * @return plugin operation wrapper
221 */
222struct ESCROW_PluginOperationWrapper *
223verify_plaintext_key_escrow (struct GNUNET_ESCROW_Handle *h,
224 struct GNUNET_IDENTITY_Ego *ego,
225 struct GNUNET_ESCROW_Anchor *escrowAnchor,
226 ESCROW_Plugin_Continuation cb,
227 uint32_t op_id)
228{
229 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
230 char *pkString;
231 int verificationResult;
232 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
233 struct ESCROW_PlaintextPluginOperation *p_op;
234 struct ESCROW_Plugin_VerifyContinuationWrapper *w;
235
236 // create a new plaintext plugin operation (in a wrapper) and insert it into the DLL
237 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
238 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_PlaintextPluginOperation);
239 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
240 ph.plugin_op_tail,
241 plugin_op_wrap);
242
243 p_op = (struct ESCROW_PlaintextPluginOperation *)plugin_op_wrap->plugin_op;
244 p_op->h = h;
245 p_op->cont = cb;
246
247 w = GNUNET_new (struct ESCROW_Plugin_VerifyContinuationWrapper);
248 w->h = h;
249 w->op_id = op_id;
250 p_op->verify_wrap = w;
251
252 if (NULL == ego)
253 {
254 w->verificationResult = GNUNET_ESCROW_INVALID;
255 w->emsg = _ ("ESCROW_verify was called with ego == NULL!\n");
256 p_op->sched_task = GNUNET_SCHEDULER_add_now (&verify_cont, plugin_op_wrap);
257 return plugin_op_wrap;
258 }
259 pk = GNUNET_IDENTITY_ego_get_private_key (ego);
260 pkString = GNUNET_CRYPTO_ecdsa_private_key_to_string (pk);
261 verificationResult = strncmp (pkString,
262 (char *)&escrowAnchor[1],
263 strlen (pkString)) == 0 ?
264 GNUNET_ESCROW_VALID : GNUNET_ESCROW_INVALID;
265
266 w->verificationResult = verificationResult;
267 p_op->sched_task = GNUNET_SCHEDULER_add_now (&verify_cont, plugin_op_wrap);
268 return plugin_op_wrap;
269}
270
271
272void
273ego_created (const struct GNUNET_IDENTITY_Ego *ego)
274{
275 struct ESCROW_PluginOperationWrapper *curr;
276 struct ESCROW_PlaintextPluginOperation *curr_p_op;
277 char *ego_pk_string, *curr_pk_string;
278
279 ego_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (&ego->pk);
280
281 for (curr = ph.plugin_op_head; NULL != curr; curr = curr->next)
282 {
283 curr_p_op = (struct ESCROW_PlaintextPluginOperation *)curr->plugin_op;
284 curr_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (curr_p_op->pk);
285 // compare the strings of the private keys
286 if (0 == strcmp (ego_pk_string, curr_pk_string))
287 {
288 // the ego was created due to a restore operation that is not yet finished
289 curr_p_op->ego_wrap->ego = ego;
290 curr_p_op->cont (curr_p_op->ego_wrap);
291
292 cleanup_plugin_operation (curr);
293
294 GNUNET_free (curr_pk_string);
295 GNUNET_free (ego_pk_string);
296 return;
297 }
298 GNUNET_free (curr_pk_string);
299 }
300 GNUNET_free (ego_pk_string);
301}
302
303
304/**
305 * Creation operation finished.
306 * This method only handles errors that may have occurred. On success,
307 * the callback is executed by the ESCROW_list_ego function, as the
308 * new ego is in our ego list only after ESCROW_list_ego has added it.
309 *
310 * @param cls pointer to operation handle
311 * @param pk private key of the ego, or NULL on error
312 * @param emsg error message, NULL on success
313 */
314static void
315create_finished (void *cls,
316 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
317 const char *emsg)
318{
319 struct ESCROW_PlaintextPluginOperation *p_op = cls;
320
321 if (NULL == pk)
322 {
323 if (NULL != emsg)
324 {
325 fprintf (stderr,
326 "Identity create operation returned with error: %s\n",
327 emsg);
328 p_op->ego_wrap->emsg = _ ("Identity create failed!\n");
329 }
330 else
331 p_op->ego_wrap->emsg = _ ("Failed to create ego!\n");
332 p_op->ego_wrap->ego = NULL;
333 p_op->cont (p_op->ego_wrap);
334 return;
335 }
336
337 /* no error occurred, p_op->restore_cont will be called in ego_created, which
338 is called from ESCROW_list_ego after adding the new ego to our list */
339 p_op->pk = pk;
340}
341
342
343void
344handle_restore_error (void *cls)
345{
346 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
347 struct ESCROW_PlaintextPluginOperation *p_op;
348
349 p_op = (struct ESCROW_PlaintextPluginOperation*)plugin_op_wrap->plugin_op;
350 p_op->cont (p_op->ego_wrap);
351
352 cleanup_plugin_operation (plugin_op_wrap);
353}
354
355
356/**
357 * Restore the key from plaintext escrow
358 *
359 * @param h the handle for the escrow component
360 * @param escrowAnchor the escrow anchor needed to restore the key
361 * @param egoName the name of the ego to restore
362 * @param cb the function called upon completion
363 * @param op_id unique ID of the respective ESCROW_Operation
364 *
365 * @return plugin operation wrapper
366 */
367struct ESCROW_PluginOperationWrapper *
368restore_plaintext_key_escrow (struct GNUNET_ESCROW_Handle *h,
369 struct GNUNET_ESCROW_Anchor *escrowAnchor,
370 const char *egoName,
371 ESCROW_Plugin_Continuation cb,
372 uint32_t op_id)
373{
374 struct GNUNET_CRYPTO_EcdsaPrivateKey pk;
375 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
376 struct ESCROW_PlaintextPluginOperation *p_op;
377 struct ESCROW_Plugin_EgoContinuationWrapper *w;
378
379 // create a new plaintext plugin operation (in a wrapper) and insert it into the DLL
380 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
381 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_PlaintextPluginOperation);
382 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
383 ph.plugin_op_tail,
384 plugin_op_wrap);
385
386 p_op = (struct ESCROW_PlaintextPluginOperation *)plugin_op_wrap->plugin_op;
387 p_op->h = h;
388 // set cont here (has to be scheduled from the IDENTITY service when it finished)
389 p_op->cont = cb;
390
391 w = GNUNET_new (struct ESCROW_Plugin_EgoContinuationWrapper);
392 w->h = h;
393 w->op_id = op_id;
394 p_op->ego_wrap = w;
395
396 if (NULL == escrowAnchor)
397 {
398 w->ego = NULL;
399 w->emsg = _ ("ESCROW_get was called with escrowAnchor == NULL!\n");
400 // schedule handle_restore_error, which calls the callback and cleans up
401 p_op->sched_task = GNUNET_SCHEDULER_add_now (&handle_restore_error, plugin_op_wrap);
402 return plugin_op_wrap;
403 }
404 if (GNUNET_OK !=
405 GNUNET_CRYPTO_ecdsa_private_key_from_string ((char *)&escrowAnchor[1],
406 strlen ((char *)&escrowAnchor[1]),
407 &pk))
408 {
409 w->ego = NULL;
410 w->emsg = _ ("Failed to create ECDSA private key from escrow anchor!\n");
411 // schedule handle_restore_error, which calls the callback and cleans up
412 p_op->sched_task = GNUNET_SCHEDULER_add_now (&handle_restore_error, plugin_op_wrap);
413 return plugin_op_wrap;
414 }
415
416 p_op->id_op = GNUNET_IDENTITY_create (identity_handle,
417 egoName,
418 &pk,
419 &create_finished,
420 p_op);
421
422 return plugin_op_wrap;
423}
424
425
426/**
427 * Get the status of a plaintext escrow
428 *
429 * @param h the handle for the escrow component
430 * @param ego the identity ego of which the status has to be obtained
431 *
432 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
433 */
434struct GNUNET_ESCROW_Status *
435plaintext_get_status (struct GNUNET_ESCROW_Handle *h,
436 struct GNUNET_IDENTITY_Ego *ego)
437{
438 return ESCROW_get_escrow_status (h, ego);
439}
440
441
442/**
443 * Deserialize an escrow anchor string into a GNUNET_ESCROW_Anchor struct
444 *
445 * @param h the handle for the escrow component
446 * @param anchorString the encoded escrow anchor string
447 *
448 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
449 */
450struct GNUNET_ESCROW_Anchor *
451plaintext_anchor_string_to_data (struct GNUNET_ESCROW_Handle *h,
452 char *anchorString)
453{
454 struct GNUNET_ESCROW_Anchor *anchor;
455 uint32_t data_size;
456
457 data_size = strlen (anchorString) + 1;
458
459 anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + data_size);
460 anchor->size = data_size;
461 // TODO: deserialize?
462 GNUNET_memcpy (&anchor[1], anchorString, data_size);
463
464 return anchor;
465}
466
467
468/**
469 * Serialize an escrow anchor struct into a string
470 *
471 * @param h the handle for the escrow component
472 * @param escrowAnchor the escrow anchor struct
473 *
474 * @return the encoded escrow anchor string
475 */
476char *
477plaintext_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
478 struct GNUNET_ESCROW_Anchor *escrowAnchor)
479{
480 char *anchorString;
481
482 anchorString = GNUNET_malloc (escrowAnchor->size);
483 GNUNET_memcpy (anchorString, &escrowAnchor[1], escrowAnchor->size);
484
485 return anchorString;
486}
487
488
489/**
490 * Cancel a plaintext plugin operation.
491 *
492 * @param plugin_op_wrap the plugin operation wrapper containing the operation
493 */
494void
495cancel_plaintext_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
496{
497 struct ESCROW_PluginOperationWrapper *curr;
498 struct ESCROW_PlaintextPluginOperation *plugin_op;
499
500 for (curr = ph.plugin_op_head; NULL != curr; curr = curr->next)
501 {
502 if (curr == plugin_op_wrap)
503 {
504 GNUNET_CONTAINER_DLL_remove (ph.plugin_op_head,
505 ph.plugin_op_tail,
506 curr);
507 plugin_op = (struct ESCROW_PlaintextPluginOperation *)curr->plugin_op;
508 GNUNET_IDENTITY_cancel (plugin_op->id_op);
509 if (NULL != plugin_op->sched_task)
510 GNUNET_SCHEDULER_cancel (plugin_op->sched_task);
511 GNUNET_free (plugin_op);
512 GNUNET_free (curr);
513 return;
514 }
515 }
516}
517
518
519/**
520 * IdentityInitContinuation for the plaintext plugin
521 */
522void
523plaintext_cont_init ()
524{
525 return;
526}
527
528
529/**
530 * Entry point for the plugin.
531 *
532 * @param cls Config info
533 *
534 * @return the exported block API
535 */
536void *
537libgnunet_plugin_escrow_plaintext_init (void *cls)
538{
539 struct GNUNET_ESCROW_KeyPluginFunctions *api;
540 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
541
542 api = GNUNET_new (struct GNUNET_ESCROW_KeyPluginFunctions);
543 api->start_key_escrow = &start_plaintext_key_escrow;
544 api->verify_key_escrow = &verify_plaintext_key_escrow;
545 api->restore_key = &restore_plaintext_key_escrow;
546 api->get_status = &plaintext_get_status;
547 api->anchor_string_to_data = &plaintext_anchor_string_to_data;
548 api->anchor_data_to_string = &plaintext_anchor_data_to_string;
549 api->cancel_plugin_operation = &cancel_plaintext_operation;
550
551 ph.state = ESCROW_PLUGIN_STATE_INIT;
552 ph.id_init_cont = &plaintext_cont_init;
553
554 // set ego_create_cont here so it is called every time an ego is created
555 ph.ego_create_cont = &ego_created;
556 identity_handle = GNUNET_IDENTITY_connect (cfg,
557 &ESCROW_list_ego,
558 &ph);
559
560 return api;
561}
562
563
564/**
565 * Exit point from the plugin.
566 *
567 * @param cls the return value from #libgnunet_plugin_block_test_init()
568 *
569 * @return NULL
570 */
571void *
572libgnunet_plugin_escrow_plaintext_done (void *cls)
573{
574 struct GNUNET_RECLAIM_EscrowKeyPluginFunctions *api = cls;
575
576 GNUNET_free (api);
577 GNUNET_IDENTITY_disconnect (identity_handle);
578 ESCROW_cleanup_ego_list (&ph);
579
580 return NULL;
581}
582
583
584/* end of plugin_escrow_plaintext.c */
diff --git a/src/escrow/plugin_gnsrecord_escrow.c b/src/escrow/plugin_gnsrecord_escrow.c
new file mode 100644
index 000000000..82ed3af96
--- /dev/null
+++ b/src/escrow/plugin_gnsrecord_escrow.c
@@ -0,0 +1,173 @@
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 escrow/plugin_gnsrecord_escrow.c
23 * @brief gnsrecord plugin to provide the API for escrow records
24 *
25 * @author Johannes Späth
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30
31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_gnsrecord_plugin.h"
33
34/**
35 * Convert the 'value' of a record to a string.
36 *
37 * @param cls closure, unused
38 * @param type type of the record
39 * @param data value in binary encoding
40 * @param data_size number of bytes in @a data
41 * @return NULL on error, otherwise human-readable representation of the value
42 */
43static char *
44value_to_string (void *cls, uint32_t type, const void *data, size_t data_size)
45{
46 switch (type)
47 {
48 case GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE:
49 return GNUNET_STRINGS_data_to_string_alloc (data, data_size);
50
51 default:
52 return NULL;
53 }
54}
55
56/**
57 * Convert human-readable version of a 'value' of a record to the binary
58 * representation.
59 *
60 * @param cls closure, unused
61 * @param type type of the record
62 * @param s human-readable string
63 * @param data set to value in binary encoding (will be allocated)
64 * @param data_size set to number of bytes in @a data
65 * @return #GNUNET_OK on success
66 */
67static int
68string_to_value (void *cls, uint32_t type, const char *s, void **data,
69 size_t *data_size)
70{
71 if (NULL == s)
72 return GNUNET_SYSERR;
73 switch (type)
74 {
75 case GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE:
76 return GNUNET_STRINGS_string_to_data (s, strlen (s), *data, *data_size);
77
78 default:
79 return GNUNET_SYSERR;
80 }
81}
82
83
84/**
85 * Mapping of record type numbers to human-readable
86 * record type names.
87 */
88static struct
89{
90 const char *name;
91 uint32_t number;
92} name_map[] = {
93 { "GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE", GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE },
94 { NULL, UINT32_MAX }
95};
96
97
98/**
99 * Convert a type name (i.e. "AAAA") to the corresponding number.
100 *
101 * @param cls closure, unused
102 * @param dns_typename name to convert
103 * @return corresponding number, UINT32_MAX on error
104 */
105static uint32_t
106typename_to_number (void *cls, const char *dns_typename)
107{
108 unsigned int i;
109
110 i = 0;
111 while ((NULL != name_map[i].name) &&
112 (0 != strcasecmp (dns_typename, name_map[i].name)))
113 i++;
114 return name_map[i].number;
115}
116
117
118/**
119 * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
120 *
121 * @param cls closure, unused
122 * @param type number of a type to convert
123 * @return corresponding typestring, NULL on error
124 */
125static const char *
126number_to_typename (void *cls, uint32_t type)
127{
128 unsigned int i;
129
130 i = 0;
131 while ((NULL != name_map[i].name) && (type != name_map[i].number))
132 i++;
133 return name_map[i].name;
134}
135
136
137/**
138 * Entry point for the plugin.
139 *
140 * @param cls NULL
141 * @return the exported block API
142 */
143void *
144libgnunet_plugin_gnsrecord_escrow_init (void *cls)
145{
146 struct GNUNET_GNSRECORD_PluginFunctions *api;
147
148 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
149 api->value_to_string = &value_to_string;
150 api->string_to_value = &string_to_value;
151 api->typename_to_number = &typename_to_number;
152 api->number_to_typename = &number_to_typename;
153 return api;
154}
155
156
157/**
158 * Exit point from the plugin.
159 *
160 * @param cls the return value from #libgnunet_plugin_block_test_init
161 * @return NULL
162 */
163void *
164libgnunet_plugin_gnsrecord_escrow_done (void *cls)
165{
166 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
167
168 GNUNET_free (api);
169 return NULL;
170}
171
172
173/* end of plugin_gnsrecord_escrow.c */
diff --git a/src/escrow/test_gns_escrow.sh b/src/escrow/test_gns_escrow.sh
new file mode 100755
index 000000000..00f8f3a49
--- /dev/null
+++ b/src/escrow/test_gns_escrow.sh
@@ -0,0 +1,47 @@
1#!/bin/sh
2
3LOCATION=$(which gnunet-config)
4if [ -z $LOCATION ]
5then
6 LOCATION="gnunet-config"
7fi
8$LOCATION --version 1> /dev/null
9if test $? != 0
10then
11 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
12 exit 77
13fi
14
15rm -rf `gnunet-config -c test_escrow.conf -s PATHS -o GNUNET_HOME -f`
16
17which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
18
19gnunet-arm -s -c test_escrow.conf
20gnunet-identity -C testego -c test_escrow.conf
21ANCHOR=$(gnunet-escrow -m gns -P testego -c test_escrow.conf)
22if test $? != 0
23then
24 echo "GNS escrow failed!"
25 gnunet-arm -e -c test_escrow.conf
26 exit 1
27else
28 ANCHOR=$(echo $ANCHOR | awk 'NF>1{print $NF}')
29fi
30gnunet-escrow -m gns -V testego -a $ANCHOR -c test_escrow.conf
31if test $? != 0
32then
33 echo "GNS verification failed!"
34 gnunet-arm -e -c test_escrow.conf
35 exit 1
36fi
37gnunet-identity -D testego -c test_escrow.conf
38gnunet-escrow -m gns -G testego -a $ANCHOR -c test_escrow.conf
39if test $? != 0
40then
41 echo "GNS restore failed!"
42 gnunet-arm -e -c test_escrow.conf
43 exit 1
44fi
45gnunet-arm -e -c test_escrow.conf
46
47exit 0
diff --git a/src/escrow/test_plaintext_escrow.sh b/src/escrow/test_plaintext_escrow.sh
new file mode 100755
index 000000000..8113110e2
--- /dev/null
+++ b/src/escrow/test_plaintext_escrow.sh
@@ -0,0 +1,47 @@
1#!/bin/sh
2
3LOCATION=$(which gnunet-config)
4if [ -z $LOCATION ]
5then
6 LOCATION="gnunet-config"
7fi
8$LOCATION --version 1> /dev/null
9if test $? != 0
10then
11 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
12 exit 77
13fi
14
15rm -rf `gnunet-config -c test_escrow.conf -s PATHS -o GNUNET_HOME -f`
16
17which timeout > /dev/null 2>&1 && DO_TIMEOUT="timeout 30"
18
19gnunet-arm -s -c test_escrow.conf
20gnunet-identity -C testego -c test_escrow.conf
21ANCHOR=$(gnunet-escrow -m plaintext -P testego -c test_escrow.conf)
22if test $? != 0
23then
24 echo "Plaintext escrow failed!"
25 gnunet-arm -e -c test_escrow.conf
26 exit 1
27else
28 ANCHOR=$(echo $ANCHOR | awk 'NF>1{print $NF}')
29fi
30gnunet-escrow -m plaintext -V testego -a $ANCHOR -c test_escrow.conf
31if test $? != 0
32then
33 echo "Plaintext verification failed!"
34 gnunet-arm -e -c test_escrow.conf
35 exit 1
36fi
37gnunet-identity -D testego -c test_escrow.conf
38gnunet-escrow -m plaintext -G testego -a $ANCHOR -c test_escrow.conf
39if test $? != 0
40then
41 echo "Plaintext restore failed!"
42 gnunet-arm -e -c test_escrow.conf
43 exit 1
44fi
45gnunet-arm -e -c test_escrow.conf
46
47exit 0
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index f8eef5406..a072ae54e 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -1188,6 +1188,21 @@ GNUNET_CRYPTO_eddsa_public_key_to_string (
1188 1188
1189 1189
1190/** 1190/**
1191 * Convert a string representing a private key to a private key.
1192 *
1193 * @param enc encoded private key
1194 * @param enclen number of bytes in @a enc (without 0-terminator)
1195 * @param priv where to store the private key
1196 * @return #GNUNET_OK on success
1197 */
1198int
1199GNUNET_CRYPTO_ecdsa_private_key_from_string (
1200 const char *enc,
1201 size_t enclen,
1202 struct GNUNET_CRYPTO_EcdsaPrivateKey *pub);
1203
1204
1205/**
1191 * Convert a string representing a public key to a public key. 1206 * Convert a string representing a public key to a public key.
1192 * 1207 *
1193 * @param enc encoded public key 1208 * @param enc encoded public key
@@ -1205,7 +1220,7 @@ GNUNET_CRYPTO_ecdsa_public_key_from_string (
1205/** 1220/**
1206 * Convert a string representing a private key to a private key. 1221 * Convert a string representing a private key to a private key.
1207 * 1222 *
1208 * @param enc encoded public key 1223 * @param enc encoded private key
1209 * @param enclen number of bytes in @a enc (without 0-terminator) 1224 * @param enclen number of bytes in @a enc (without 0-terminator)
1210 * @param priv where to store the private key 1225 * @param priv where to store the private key
1211 * @return #GNUNET_OK on success 1226 * @return #GNUNET_OK on success
diff --git a/src/include/gnunet_escrow_lib.h b/src/include/gnunet_escrow_lib.h
new file mode 100644
index 000000000..dabd0d83d
--- /dev/null
+++ b/src/include/gnunet_escrow_lib.h
@@ -0,0 +1,417 @@
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 * @author Johannes Späth
23 *
24 * @file
25 * Escrow definitions
26 *
27 * @defgroup escrow escrow component
28 * @{
29 */
30#ifndef GNUNET_ESCROW_LIB_H
31#define GNUNET_ESCROW_LIB_H
32
33#ifdef __cplusplus
34extern "C" {
35#if 0 /* keep Emacsens' auto-indent happy */
36}
37#endif
38#endif
39
40#include "gnunet_util_lib.h"
41#include "gnunet_identity_service.h"
42
43
44/**
45 * Enum for the different key escrow methods
46 */
47enum GNUNET_ESCROW_Key_Escrow_Method
48{
49 GNUNET_ESCROW_KEY_NONE, // error value
50 GNUNET_ESCROW_KEY_PLAINTEXT,
51 GNUNET_ESCROW_KEY_GNS,
52 GNUNET_ESCROW_KEY_ANASTASIS
53};
54
55
56/**
57 * Enum for the different verification results
58 */
59enum GNUNET_ESCROW_Verification_Result
60{
61 GNUNET_ESCROW_VALID,
62 GNUNET_ESCROW_INVALID
63};
64
65
66/**
67 * Struct for the escrow anchor
68 */
69struct GNUNET_ESCROW_Anchor
70{
71 /**
72 * The escrow method.
73 */
74 enum GNUNET_ESCROW_Key_Escrow_Method method;
75
76 /**
77 * The size of the anchor data.
78 */
79 uint32_t size;
80};
81
82
83/**
84 * Struct for the escrow status
85 */
86struct GNUNET_ESCROW_Status
87{
88 /**
89 * The time of the last successful escrow.
90 */
91 struct GNUNET_TIME_Absolute last_escrow_time;
92
93 /**
94 * The time of the next recommended escrow.
95 */
96 struct GNUNET_TIME_Absolute next_recommended_escrow_time;
97
98 /**
99 * The used escrow method.
100 */
101 enum GNUNET_ESCROW_Key_Escrow_Method last_method;
102};
103
104
105/**
106 * Function called after the initialization of the identity service.
107 * Passed via cls to the callback of GNUNET_IDENTITY_connect
108 */
109typedef void (*GNUNET_ESCROW_IdentityInitContinuation) ();
110
111/**
112 * Function called after the creation of an ego in case that happened
113 * because of an escrow GET operation.
114 */
115typedef void (*GNUNET_ESCROW_EgoCreateContinuation) (
116 const struct GNUNET_IDENTITY_Ego *ego);
117
118/**
119 * Continuation for PUT operations.
120 *
121 * @param cls closure
122 * @param escrowAnchor the escrow anchor needed to get the data back
123 * @param emsg error message, NULL on success
124 */
125typedef void (*GNUNET_ESCROW_AnchorContinuation) (
126 void *cls,
127 struct GNUNET_ESCROW_Anchor *escrowAnchor,
128 const char *emsg);
129
130/**
131 * Continuation for a GET operation.
132 *
133 * @param cls closure
134 * @param ego a new identity ego restored from the escrow
135 * @param emsg error message, NULL on success
136 */
137typedef void (*GNUNET_ESCROW_EgoContinuation) (
138 void *cls,
139 const struct GNUNET_IDENTITY_Ego *ego,
140 const char *emsg);
141
142/**
143 * Continuation for a VERIFY operation.
144 *
145 * @param cls closure
146 * @param verificationResult the result of the verification, i.e.
147 * GNUNET_ESCROW_VALID if the escrow could successfully by restored,
148 * GNUNET_ESCROW_INVALID otherwise
149 * @param emsg error message, NULL on success
150 */
151typedef void (*GNUNET_ESCROW_VerifyContinuation) (
152 void *cls,
153 int verificationResult,
154 const char *emsg);
155
156
157/**
158 * Handle for the escrow component.
159 */
160struct GNUNET_ESCROW_Handle
161{
162 /**
163 * Configuration to use.
164 */
165 struct GNUNET_CONFIGURATION_Handle *cfg;
166
167 /**
168 * Head of active operations.
169 */
170 struct GNUNET_ESCROW_Operation *op_head;
171
172 /**
173 * Tail of active operations.
174 */
175 struct GNUNET_ESCROW_Operation *op_tail;
176
177 /**
178 * The last operation id used for an ESCROW operation.
179 */
180 uint32_t last_op_id_used;
181};
182
183
184/**
185 * Handle for an operation with the escrow component.
186 */
187struct GNUNET_ESCROW_Operation
188{
189 /**
190 * Main escrow handle.
191 */
192 struct GNUNET_ESCROW_Handle *h;
193
194 /**
195 * ID of the operation.
196 */
197 uint32_t id;
198
199 /**
200 * We keep operations in a DLL.
201 */
202 struct GNUNET_ESCROW_Operation *next;
203
204 /**
205 * We keep operations in a DLL.
206 */
207 struct GNUNET_ESCROW_Operation *prev;
208
209 /**
210 * The used escrow method.
211 */
212 enum GNUNET_ESCROW_Key_Escrow_Method method;
213
214 /**
215 * The respective plugin operation
216 */
217 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
218
219 /**
220 * The escrow anchor.
221 */
222 struct GNUNET_ESCROW_Anchor *escrow_anchor;
223
224 /**
225 * The ego.
226 */
227 const struct GNUNET_IDENTITY_Ego *ego;
228
229 /**
230 * The verification result.
231 */
232 enum GNUNET_ESCROW_Verification_Result verification_result;
233
234 /**
235 * Continuation for a PUT operation.
236 */
237 GNUNET_ESCROW_AnchorContinuation cb_put;
238
239 /**
240 * Continuation for a GET operation.
241 */
242 GNUNET_ESCROW_EgoContinuation cb_get;
243
244 /**
245 * Continuation for a VERIFY operation.
246 */
247 GNUNET_ESCROW_VerifyContinuation cb_verify;
248
249 /**
250 * Closure for the callback
251 */
252 void *cb_cls;
253};
254
255
256/**
257 * Initialize the escrow component.
258 *
259 * @param cfg the configuration to use
260 *
261 * @return handle to use
262 */
263struct GNUNET_ESCROW_Handle *
264GNUNET_ESCROW_init (
265 const struct GNUNET_CONFIGURATION_Handle *cfg);
266
267
268/**
269 * Unload all loaded plugins on destruction.
270 *
271 * @param h the escrow handle
272 */
273void
274GNUNET_ESCROW_fini (
275 struct GNUNET_ESCROW_Handle *h);
276
277
278/**
279 * Put some data in escrow using the specified escrow method
280 *
281 * @param h the handle for the escrow component
282 * @param ego the identity ego to put in escrow
283 * @param userSecret the user secret (e.g. for derivation of escrow identities)
284 * @param method the escrow method to use
285 * @param cb function to call with the escrow anchor on completion
286 * @param cb_cls closure for @a cb
287 *
288 * @return handle to abort the operation
289 */
290struct GNUNET_ESCROW_Operation *
291GNUNET_ESCROW_put (
292 struct GNUNET_ESCROW_Handle *h,
293 struct GNUNET_IDENTITY_Ego *ego,
294 const char *userSecret,
295 enum GNUNET_ESCROW_Key_Escrow_Method method,
296 GNUNET_ESCROW_AnchorContinuation cb,
297 void *cb_cls);
298
299
300/**
301 * Get the escrowed data back
302 *
303 * @param h the handle for the escrow component
304 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
305 * @param egoName the name of the ego to get back
306 * @param method the escrow method to use
307 * @param cb function to call with the restored ego on completion
308 * @param cb_cls closure for @a cb
309 *
310 * @return handle to abort the operation
311 */
312struct GNUNET_ESCROW_Operation *
313GNUNET_ESCROW_get (
314 struct GNUNET_ESCROW_Handle *h,
315 struct GNUNET_ESCROW_Anchor *escrowAnchor,
316 const char *egoName,
317 enum GNUNET_ESCROW_Key_Escrow_Method method,
318 GNUNET_ESCROW_EgoContinuation cb,
319 void *cb_cls);
320
321
322/**
323 * Verify the escrowed data
324 *
325 * @param h the handle for the escrow component
326 * @param ego the identity ego that was put into escrow
327 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
328 * @param method the escrow method to use
329 * @param cb function to call with the verification result on completion
330 * @param cb_cls closure for @a cb
331 *
332 * @return handle to abort the operation
333 */
334struct GNUNET_ESCROW_Operation *
335GNUNET_ESCROW_verify (
336 struct GNUNET_ESCROW_Handle *h,
337 struct GNUNET_IDENTITY_Ego *ego,
338 struct GNUNET_ESCROW_Anchor *escrowAnchor,
339 enum GNUNET_ESCROW_Key_Escrow_Method method,
340 GNUNET_ESCROW_VerifyContinuation cb,
341 void *cb_cls);
342
343
344/**
345 * Get the status of an escrow, i.e.
346 * -> when the last escrow was
347 * -> when the next escrow is recommended
348 *
349 * @param h the handle for the escrow component
350 * @param ego the identity ego of which the escrow status has to be determined
351 * @param method the escrow method to use
352 *
353 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
354 */
355struct GNUNET_ESCROW_Status *
356GNUNET_ESCROW_get_status (
357 struct GNUNET_ESCROW_Handle *h,
358 struct GNUNET_IDENTITY_Ego *ego,
359 enum GNUNET_ESCROW_Key_Escrow_Method method);
360
361
362/**
363 * Deserialize an escrow anchor string (e.g. from command line) into a
364 * GNUNET_ESCROW_Anchor struct
365 *
366 * @param h the handle for the escrow component
367 * @param anchorString the encoded escrow anchor string
368 * @param method the escrow method to use
369 *
370 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
371 */
372struct GNUNET_ESCROW_Anchor *
373GNUNET_ESCROW_anchor_string_to_data (
374 struct GNUNET_ESCROW_Handle *h,
375 char *anchorString,
376 enum GNUNET_ESCROW_Key_Escrow_Method method);
377
378
379/**
380 * Serialize an escrow anchor (struct GNUNET_ESCROW_Anchor) into a string
381 *
382 * @param h the handle for the escrow component
383 * @param escrowAnchor the escrow anchor struct
384 * @param method the escrow method to use
385 *
386 * @return the encoded escrow anchor string
387 */
388char *
389GNUNET_ESCROW_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
390 struct GNUNET_ESCROW_Anchor *escrowAnchor,
391 enum GNUNET_ESCROW_Key_Escrow_Method method);
392
393
394/**
395 * Cancel an escrow operation. Note that the operation MAY still
396 * be executed; this merely cancels the continuation.
397 *
398 * @param op operation to cancel
399 */
400void
401GNUNET_ESCROW_cancel (struct GNUNET_ESCROW_Operation *op);
402
403
404#if 0 /* keep Emacsens' auto-indent happy */
405{
406#endif
407#ifdef __cplusplus
408}
409#endif
410
411
412/* ifndef GNUNET_ESCROW_LIB_H */
413#endif
414
415/** @} */ /* end of group escrow */
416
417/* end of gnunet_escrow_lib.h */
diff --git a/src/include/gnunet_escrow_plugin.h b/src/include/gnunet_escrow_plugin.h
new file mode 100644
index 000000000..4387ff613
--- /dev/null
+++ b/src/include/gnunet_escrow_plugin.h
@@ -0,0 +1,210 @@
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 * @author Johannes Späth
23 *
24 * @file
25 * Plugin API for escrow methods
26 *
27 * @defgroup escrow-plugin escrow plugin API for escrow methods
28 * @{
29 */
30#ifndef GNUNET_ESCROW_PLUGIN_H
31#define GNUNET_ESCROW_PLUGIN_H
32
33#include "gnunet_util_lib.h"
34#include "gnunet_escrow_lib.h"
35#include "gnunet_identity_service.h"
36#include "../escrow/escrow.h"
37#include "gnunet_scheduler_lib.h"
38
39#ifdef __cplusplus
40extern "C" {
41#if 0 /* keep Emacsens' auto-indent happy */
42}
43#endif
44#endif
45
46
47/**
48 * Function called to start the escrow of the key
49 *
50 * @param h the handle for the escrow component
51 * @param ego the identity ego containing the private key
52 * @param userSecret the user secret (e.g. for derivation of escrow identities)
53 * @param cb the function called upon completion
54 * @param op_id unique ID of the respective ESCROW_Operation
55 *
56 * @return a wrapper for the plugin operation
57 */
58typedef struct ESCROW_PluginOperationWrapper *(*GNUNET_ESCROW_StartKeyEscrowFunction) (
59 struct GNUNET_ESCROW_Handle *h,
60 struct GNUNET_IDENTITY_Ego *ego,
61 const char *userSecret,
62 GNUNET_SCHEDULER_TaskCallback cb,
63 uint32_t op_id);
64
65/**
66 * Function called to verify the escrow of the key
67 *
68 * @param h the handle for the escrow component
69 * @param ego the identity ego containing the private key
70 * @param escrowAnchor the escrow anchor needed to restore the key
71 * @param cb the function called upon completion
72 * @param op_id unique ID of the respective ESCROW_Operation
73 *
74 * @return a wrapper for the plugin operation
75 */
76typedef struct ESCROW_PluginOperationWrapper *(*GNUNET_ESCROW_VerifyKeyEscrowFunction) (
77 struct GNUNET_ESCROW_Handle *h,
78 struct GNUNET_IDENTITY_Ego *ego,
79 struct GNUNET_ESCROW_Anchor *escrowAnchor,
80 GNUNET_SCHEDULER_TaskCallback cb,
81 uint32_t op_id);
82
83/**
84 * Function called to restore a key from an escrow
85 *
86 * @param h the handle for the escrow component
87 * @param escrowAnchor the escrow anchor needed to restore the key
88 * @param egoName the name of the ego to restore
89 * @param cb the function called upon completion
90 * @param op_id unique ID of the respective ESCROW_Operation
91 *
92 * @return a wrapper for the plugin operation
93 */
94typedef struct ESCROW_PluginOperationWrapper *(*GNUNET_ESCROW_RestoreKeyFunction) (
95 struct GNUNET_ESCROW_Handle *h,
96 struct GNUNET_ESCROW_Anchor *escrowAnchor,
97 const char *egoName,
98 GNUNET_SCHEDULER_TaskCallback cb,
99 uint32_t op_id);
100
101
102/**
103 * Function called to get the status of an escrow, i.e.
104 * -> when the last successful escrow was
105 * -> when the next recommended escrow is
106 *
107 * @param h the handle for the escrow component
108 * @param ego the identity ego of which the status has to be obtained
109 *
110 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
111 */
112typedef struct GNUNET_ESCROW_Status *(*GNUNET_ESCROW_GetEscrowStatusFunction) (
113 struct GNUNET_ESCROW_Handle *h,
114 struct GNUNET_IDENTITY_Ego *ego);
115
116
117/**
118 * Function called to deserialize an escrow anchor string into a
119 * GNUNET_ESCROW_Anchor struct
120 *
121 * @param h the handle for the escrow component
122 * @param anchorString the encoded escrow anchor string
123 *
124 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
125 */
126typedef struct GNUNET_ESCROW_Anchor *(*GNUNET_ESCROW_AnchorStringToDataFunction) (
127 struct GNUNET_ESCROW_Handle *h,
128 char *anchorString);
129
130
131/**
132 * Function called to serialize an escrow anchor struct into a string
133 *
134 * @param h the handle for the escrow component
135 * @param escrowAnchor the escrow anchor struct
136 *
137 * @return the encoded escrow anchor string
138 */
139typedef char *(*GNUNET_ESCROW_AnchorDataToStringFunction) (
140 struct GNUNET_ESCROW_Handle *h,
141 struct GNUNET_ESCROW_Anchor *escrowAnchor);
142
143
144/**
145 * Function called to cancel a plugin operation
146 *
147 * @param plugin_op_wrap plugin operation wrapper containing the plugin operation
148 */
149typedef void (*GNUNET_ESCROW_CancelPluginOperationFunction) (
150 struct ESCROW_PluginOperationWrapper *plugin_op_wrap);
151
152
153/**
154 * Each plugin is required to return a pointer to a struct of this
155 * type as the return value from its entry point.
156 */
157struct GNUNET_ESCROW_KeyPluginFunctions
158{
159 /**
160 * Closure for all of the callbacks.
161 */
162 void *cls;
163
164 /**
165 * Start key escrow
166 */
167 GNUNET_ESCROW_StartKeyEscrowFunction start_key_escrow;
168
169 /**
170 * Verify key escrow
171 */
172 GNUNET_ESCROW_VerifyKeyEscrowFunction verify_key_escrow;
173
174 /**
175 * Restore key escrow
176 */
177 GNUNET_ESCROW_RestoreKeyFunction restore_key;
178
179 /**
180 * Get the status of an escrow
181 */
182 GNUNET_ESCROW_GetEscrowStatusFunction get_status;
183
184 /**
185 * Deserialize anchor string to data
186 */
187 GNUNET_ESCROW_AnchorStringToDataFunction anchor_string_to_data;
188
189 /**
190 * Serialize anchor data to string
191 */
192 GNUNET_ESCROW_AnchorDataToStringFunction anchor_data_to_string;
193
194 /**
195 * Cancel plugin operation
196 */
197 GNUNET_ESCROW_CancelPluginOperationFunction cancel_plugin_operation;
198};
199
200
201#if 0 /* keep Emacsens' auto-indent happy */
202{
203#endif
204#ifdef __cplusplus
205}
206#endif
207
208#endif
209
210/** @} */ /* end of group */
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index c976c89c5..6ad6801cb 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -150,6 +150,11 @@ extern "C" {
150 */ 150 */
151#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF 65555 151#define GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION_REF 65555
152 152
153/**
154 * Record type for an escrow key share (escrow component)
155 */
156#define GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE 65556
157
153 158
154/** 159/**
155 * Flags that can be set for a record. 160 * Flags that can be set for a record.
diff --git a/src/include/gnunet_reclaim_plugin.h b/src/include/gnunet_reclaim_plugin.h
index 7ee9e730f..ddd98697f 100644
--- a/src/include/gnunet_reclaim_plugin.h
+++ b/src/include/gnunet_reclaim_plugin.h
@@ -32,6 +32,7 @@
32 32
33#include "gnunet_util_lib.h" 33#include "gnunet_util_lib.h"
34#include "gnunet_reclaim_lib.h" 34#include "gnunet_reclaim_lib.h"
35#include "gnunet_identity_service.h"
35 36
36#ifdef __cplusplus 37#ifdef __cplusplus
37extern "C" { 38extern "C" {
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index 019dbe94e..ef52d9588 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -388,6 +388,39 @@ GNUNET_CRYPTO_ecdsa_public_key_from_string (
388 388
389 389
390/** 390/**
391 * Convert a string representing a private key to a private key.
392 *
393 * @param enc encoded private key
394 * @param enclen number of bytes in @a enc (without 0-terminator)
395 * @param priv where to store the private key
396 * @return #GNUNET_OK on success
397 */
398int
399GNUNET_CRYPTO_ecdsa_private_key_from_string (
400 const char *enc,
401 size_t enclen,
402 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
403{
404 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)) * 8;
405
406 if (keylen % 5 > 0)
407 keylen += 5 - keylen % 5;
408 keylen /= 5;
409 if (enclen != keylen)
410 return GNUNET_SYSERR;
411
412 if (GNUNET_OK !=
413 GNUNET_STRINGS_string_to_data (enc,
414 enclen,
415 priv,
416 sizeof(
417 struct GNUNET_CRYPTO_EcdsaPrivateKey)))
418 return GNUNET_SYSERR;
419 return GNUNET_OK;
420}
421
422
423/**
391 * Convert a string representing a public key to a public key. 424 * Convert a string representing a public key to a public key.
392 * 425 *
393 * @param enc encoded public key 426 * @param enc encoded public key
@@ -423,7 +456,7 @@ GNUNET_CRYPTO_eddsa_public_key_from_string (
423/** 456/**
424 * Convert a string representing a private key to a private key. 457 * Convert a string representing a private key to a private key.
425 * 458 *
426 * @param enc encoded public key 459 * @param enc encoded private key
427 * @param enclen number of bytes in @a enc (without 0-terminator) 460 * @param enclen number of bytes in @a enc (without 0-terminator)
428 * @param priv where to store the private key 461 * @param priv where to store the private key
429 * @return #GNUNET_OK on success 462 * @return #GNUNET_OK on success