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.c479
-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.c553
-rw-r--r--src/escrow/plugin_escrow_anastasis.c274
-rw-r--r--src/escrow/plugin_escrow_gns.c1781
-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.sh48
-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.h421
-rw-r--r--src/include/gnunet_escrow_plugin.h211
-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, 5497 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 bd92bd0e9..3a83e31d2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -792,6 +792,34 @@ AC_ARG_WITH(jansson,
792AS_IF([test "x$jansson" != x1], 792AS_IF([test "x$jansson" != x1],
793 [AC_MSG_ERROR([GNUnet requires libjansson])]) 793 [AC_MSG_ERROR([GNUnet requires libjansson])])
794 794
795# check for sss (Shamir Secret Sharing) library
796sss=0
797AC_MSG_CHECKING(for sss)
798AC_ARG_WITH(sss,
799 [ --with-sss=PREFIX (base of sss installation)],
800 [AC_MSG_RESULT([$with_sss])
801 AS_CASE([$with_sss],
802 [no],[],
803 [yes],[
804 CHECK_LIBHEADER(SSS, sss, sss_create_shares, sss.h, sss=1,)
805 ],[
806 LDFLAGS="-L$with_sss/lib $LDFLAGS"
807 CPPFLAGS="-I$with_sss/include $CPPFLAGS"
808 AC_CHECK_HEADERS(sss.h,
809 AC_CHECK_LIB([sss], [sss_create_shares],
810 EXT_LIB_PATH="-L$with_sss/lib $EXT_LIB_PATH"
811 sss=1))
812 ])
813 ],
814 [AC_MSG_RESULT([--with-sss not specified])
815 CHECK_LIBHEADER(SSS, sss, sss_create_shares, sss.h,sss=1,)])
816AM_CONDITIONAL(HAVE_SSS, [test "$sss" = 1])
817AS_IF([test "$sss" = 1],
818 [AC_DEFINE([HAVE_SSS],[1],[Have sss library])
819 sss_msg="yes"],
820 [AC_DEFINE([HAVE_SSS],[0],[Lacking sss library])
821 sss_msg="no"])
822
795# check for libpulse(audio) library 823# check for libpulse(audio) library
796pulse=0 824pulse=0
797libpulse_msg="no" 825libpulse_msg="no"
@@ -1964,6 +1992,7 @@ src/zonemaster/zonemaster.conf
1964src/rest/Makefile 1992src/rest/Makefile
1965src/abe/Makefile 1993src/abe/Makefile
1966src/reclaim/Makefile 1994src/reclaim/Makefile
1995src/escrow/Makefile
1967pkgconfig/Makefile 1996pkgconfig/Makefile
1968pkgconfig/gnunetarm.pc 1997pkgconfig/gnunetarm.pc
1969pkgconfig/gnunetats.pc 1998pkgconfig/gnunetats.pc
@@ -2065,6 +2094,10 @@ AS_IF([test "x$conversation_backend" = "xnone"],
2065# -- interface 2094# -- interface
2066interface_msg=`echo $DEFAULT_INTERFACE | tr -d \"` 2095interface_msg=`echo $DEFAULT_INTERFACE | tr -d \"`
2067# -- jansson 2096# -- jansson
2097# -- sss
2098AS_IF([test "$sss" != 1],
2099 [AC_MSG_WARN([sss library not found. GNS escrow plugin will not be compiled.])],
2100 [sss_msg="yes"])
2068# -- libextractor 2101# -- libextractor
2069AS_IF([test "$extractor" != 1], 2102AS_IF([test "$extractor" != 1],
2070 [AC_MSG_WARN([libextractor not found, but various file-sharing functions require it])], 2103 [AC_MSG_WARN([libextractor not found, but various file-sharing functions require it])],
@@ -2177,6 +2210,7 @@ libpulse: ${libpulse_msg}
2177libextractor: ${libextractor_msg} 2210libextractor: ${libextractor_msg}
2178texi2mdoc: ${texi2mdoc_msg} 2211texi2mdoc: ${texi2mdoc_msg}
2179mandoc: ${mandoc_msg} 2212mandoc: ${mandoc_msg}
2213sss: ${sss_msg}
2180 2214
2181GNUnet configuration: 2215GNUnet configuration:
2182===================== 2216=====================
diff --git a/src/Makefile.am b/src/Makefile.am
index 234a63389..64a4e594a 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..ddbf6a2b7
--- /dev/null
+++ b/src/escrow/escrow_api.c
@@ -0,0 +1,479 @@
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 * for GNS escrow, this has to be UNIQUE in the whole network!
236 * @param method the escrow method to use
237 * @param cb function to call with the escrow anchor on completion
238 * @param cb_cls closure for @a cb
239 *
240 * @return handle to abort the operation
241 */
242struct GNUNET_ESCROW_Operation *
243GNUNET_ESCROW_put (struct GNUNET_ESCROW_Handle *h,
244 struct GNUNET_IDENTITY_Ego *ego,
245 const char *userSecret,
246 enum GNUNET_ESCROW_Key_Escrow_Method method,
247 GNUNET_ESCROW_AnchorContinuation cb,
248 void *cb_cls)
249{
250 struct GNUNET_ESCROW_Operation *op;
251 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
252
253 op = GNUNET_new (struct GNUNET_ESCROW_Operation);
254 op->h = h;
255 op->id = get_op_id (h);
256 op->method = method;
257 op->cb_put = cb;
258 op->cb_cls = cb_cls;
259 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
260
261 api = init_plugin (h, method);
262 op->plugin_op_wrap = api->start_key_escrow (h,
263 ego,
264 userSecret,
265 &handle_start_escrow_result,
266 op->id);
267
268 return op;
269}
270
271
272static void
273handle_restore_key_result (void *cls)
274{
275 struct ESCROW_Plugin_EgoContinuationWrapper *w = cls;
276 struct GNUNET_ESCROW_Operation *op;
277
278 for (op = w->h->op_head; NULL != op; op = op->next)
279 if (op->id == w->op_id)
280 break;
281
282 if (NULL == op)
283 {
284 GNUNET_break (0);
285 return;
286 }
287 GNUNET_CONTAINER_DLL_remove (w->h->op_head, w->h->op_tail, op);
288 if (NULL != op->cb_get)
289 op->cb_get (op->cb_cls, w->ego, w->emsg);
290 GNUNET_free (op);
291}
292
293
294/**
295 * Get the escrowed data back
296 *
297 * @param h the handle for the escrow component
298 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
299 * @param egoName the name of the ego to get back
300 * @param method the escrow method to use
301 * @param cb function to call with the restored ego on completion
302 * @param cb_cls closure for @a cb
303 *
304 * @return handle to abort the operation
305 */
306struct GNUNET_ESCROW_Operation *
307GNUNET_ESCROW_get (struct GNUNET_ESCROW_Handle *h,
308 struct GNUNET_ESCROW_Anchor *escrowAnchor,
309 const char *egoName,
310 enum GNUNET_ESCROW_Key_Escrow_Method method,
311 GNUNET_ESCROW_EgoContinuation cb,
312 void *cb_cls)
313{
314 struct GNUNET_ESCROW_Operation *op;
315 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
316
317 op = GNUNET_new (struct GNUNET_ESCROW_Operation);
318 op->h = h;
319 op->id = get_op_id (h);
320 op->method = method;
321 op->cb_get = cb;
322 op->cb_cls = cb_cls;
323 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
324
325 api = init_plugin (h, method);
326 op->plugin_op_wrap = api->restore_key (h, escrowAnchor, egoName, &handle_restore_key_result, op->id);
327
328 return op;
329}
330
331
332void
333handle_verify_escrow_result (void *cls)
334{
335 struct ESCROW_Plugin_VerifyContinuationWrapper *w = cls;
336 struct GNUNET_ESCROW_Operation *op;
337
338 for (op = w->h->op_head; NULL != op; op = op->next)
339 if (op->id == w->op_id)
340 break;
341
342 if (NULL == op)
343 {
344 GNUNET_break (0);
345 return;
346 }
347 GNUNET_CONTAINER_DLL_remove (w->h->op_head, w->h->op_tail, op);
348 if (NULL != op->cb_verify)
349 op->cb_verify (op->cb_cls, w->verificationResult, w->emsg);
350 GNUNET_free (op);
351}
352
353
354/**
355 * Verify the escrowed data
356 *
357 * @param h the handle for the escrow component
358 * @param ego the identity ego that was put into escrow
359 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
360 * @param method the escrow method to use
361 * @param cb function to call with the verification result on completion
362 * @param cb_cls closure for @a cb
363 *
364 * @return handle to abort the operation
365 */
366struct GNUNET_ESCROW_Operation *
367GNUNET_ESCROW_verify (struct GNUNET_ESCROW_Handle *h,
368 struct GNUNET_IDENTITY_Ego *ego,
369 struct GNUNET_ESCROW_Anchor *escrowAnchor,
370 enum GNUNET_ESCROW_Key_Escrow_Method method,
371 GNUNET_ESCROW_VerifyContinuation cb,
372 void *cb_cls)
373{
374 struct GNUNET_ESCROW_Operation *op;
375 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
376
377 op = GNUNET_new (struct GNUNET_ESCROW_Operation);
378 op->h = h;
379 op->id = get_op_id (h);
380 op->method = method;
381 op->cb_verify = cb;
382 op->cb_cls = cb_cls;
383 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
384
385 api = init_plugin (h, method);
386 op->plugin_op_wrap = api->verify_key_escrow (h, ego, escrowAnchor, &handle_verify_escrow_result, op->id);
387
388 return op;
389}
390
391
392/**
393 * Get the status of an escrow, i.e.
394 * -> when the last escrow was
395 * -> when the next escrow is recommended
396 *
397 * @param h the handle for the escrow component
398 * @param ego the identity ego of which the escrow status has to be determined
399 * @param method the escrow method to use
400 *
401 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
402 */
403struct GNUNET_ESCROW_Status *
404GNUNET_ESCROW_get_status (struct GNUNET_ESCROW_Handle *h,
405 struct GNUNET_IDENTITY_Ego *ego,
406 enum GNUNET_ESCROW_Key_Escrow_Method method)
407{
408 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
409
410 api = init_plugin (h, method);
411 return api->get_status (h, ego);
412}
413
414
415/**
416 * Deserialize an escrow anchor string (e.g. from command line) into a
417 * GNUNET_ESCROW_Anchor struct
418 *
419 * @param h the handle for the escrow component
420 * @param anchorString the encoded escrow anchor string
421 * @param method the escrow method to use
422 *
423 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
424 */
425struct GNUNET_ESCROW_Anchor *
426GNUNET_ESCROW_anchor_string_to_data (struct GNUNET_ESCROW_Handle *h,
427 char *anchorString,
428 enum GNUNET_ESCROW_Key_Escrow_Method method)
429{
430 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
431
432 api = init_plugin (h, method);
433 return api->anchor_string_to_data (h, anchorString);
434}
435
436
437/**
438 * Serialize an escrow anchor (struct GNUNET_ESCROW_Anchor) into a string
439 *
440 * @param h the handle for the escrow component
441 * @param escrowAnchor the escrow anchor struct
442 * @param method the escrow method to use
443 *
444 * @return the encoded escrow anchor string
445 */
446char *
447GNUNET_ESCROW_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
448 struct GNUNET_ESCROW_Anchor *escrowAnchor,
449 enum GNUNET_ESCROW_Key_Escrow_Method method)
450{
451 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
452
453 api = init_plugin (h, method);
454 return api->anchor_data_to_string (h, escrowAnchor);
455}
456
457
458/**
459 * Cancel an escrow operation. Note that the operation MAY still
460 * be executed; this merely cancels the continuation.
461 *
462 * @param op operation to cancel
463 */
464void
465GNUNET_ESCROW_cancel (struct GNUNET_ESCROW_Operation *op)
466{
467 const struct GNUNET_ESCROW_KeyPluginFunctions *api;
468
469 api = init_plugin (op->h, op->method);
470 api->cancel_plugin_operation (op->plugin_op_wrap);
471 // TODO: check which callback is not NULL?
472 op->cb_put = NULL;
473 op->cb_verify = NULL;
474 op->cb_get = NULL;
475 GNUNET_free (op);
476}
477
478
479/* 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..23fa5d061
--- /dev/null
+++ b/src/escrow/gnunet-escrow.c
@@ -0,0 +1,553 @@
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 "
222 "in 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_SHARES_MISSING:
241 fprintf (stdout, "Escrow can be restored, but some shares are missing! "
242 "Please perform a new escrow.\n");
243 break;
244 case GNUNET_ESCROW_INVALID:
245 ret = 2;
246 fprintf (stdout, "Escrow is INvalid! Please perform a new escrow.\n");
247 break;
248 default:
249 ret = 1;
250 if (NULL != emsg)
251 fprintf (stderr, "invalid verificationResult: %s", emsg);
252 }
253 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
254}
255
256
257static void
258get_cb (void *cls,
259 const struct GNUNET_IDENTITY_Ego *ego,
260 const char *emsg)
261{
262 escrow_op = NULL;
263
264 if (NULL == ego)
265 {
266 ret = 1;
267 if (NULL != emsg)
268 fprintf (stderr, "Escrow failed: %s", emsg);
269 }
270 else
271 fprintf (stdout, "Identity %s could successfully be restored!\n", ego->name);
272 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
273}
274
275
276static void
277start_process ()
278{
279 /* put */
280 if (NULL != put_ego)
281 {
282 if (NULL == ego)
283 {
284 ret = 1;
285 fprintf (stderr, "Ego %s not found\n", put_ego);
286 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
287 return;
288 }
289 escrow_op = GNUNET_ESCROW_put (escrow_handle,
290 ego,
291 user_secret_string,
292 method,
293 &put_cb,
294 NULL);
295 return;
296 }
297 /* verify */
298 if (NULL != verify_ego)
299 {
300 if (NULL == ego)
301 {
302 ret = 1;
303 fprintf (stderr, "Ego %s not found\n", verify_ego);
304 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
305 return;
306 }
307 escrow_op = GNUNET_ESCROW_verify (escrow_handle,
308 ego,
309 anchor,
310 method,
311 &verify_cb,
312 NULL);
313 return;
314 }
315 /* get */
316 if (NULL != get_ego)
317 {
318 if (NULL != ego)
319 {
320 ret = 1;
321 fprintf (stderr, "The name %s is already in use for an ego\n", get_ego);
322 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
323 return;
324 }
325 escrow_op = GNUNET_ESCROW_get (escrow_handle,
326 anchor,
327 get_ego,
328 method,
329 &get_cb,
330 NULL);
331 return;
332 }
333 /* status */
334 if (NULL != status_ego)
335 {
336 if (NULL == ego)
337 {
338 ret = 1;
339 fprintf (stderr, "Ego %s not found\n", status_ego);
340 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
341 return;
342 }
343 escrow_status = GNUNET_ESCROW_get_status (escrow_handle,
344 ego,
345 method);
346 // TODO: formatting/interpretation
347 fprintf (stdout, "Last escrow:\t\t\t%s\n",
348 GNUNET_STRINGS_absolute_time_to_string (escrow_status->last_escrow_time));
349 fprintf (stdout, "Next recommended escrow:\t%s\n",
350 GNUNET_STRINGS_absolute_time_to_string (escrow_status->next_recommended_escrow_time));
351 fprintf (stdout, "Last method:\t\t\t");
352 switch (escrow_status->last_method)
353 {
354 case GNUNET_ESCROW_KEY_PLAINTEXT:
355 fprintf (stdout, "%s\n", plaintext_string);
356 break;
357 case GNUNET_ESCROW_KEY_GNS:
358 fprintf (stdout, "%s\n", gns_string);
359 break;
360 case GNUNET_ESCROW_KEY_ANASTASIS:
361 fprintf (stdout, "%s\n", anastasis_string);
362 break;
363 default:
364 fprintf (stdout, "INVALID METHOD\n");
365 }
366 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
367 return;
368 }
369}
370
371
372static int init = GNUNET_YES;
373
374static void
375ego_cb (void *cls,
376 struct GNUNET_IDENTITY_Ego *e,
377 void **ctx,
378 const char *name)
379{
380 char *ego_name = cls;
381
382 if (NULL == name)
383 {
384 if (GNUNET_YES == init)
385 {
386 init = GNUNET_NO;
387 start_process ();
388 }
389 return;
390 }
391 if (0 != strcmp (name, ego_name))
392 return;
393 ego = e;
394}
395
396
397static void
398run (void *cls,
399 char *const *args,
400 const char *cfgfile,
401 const struct GNUNET_CONFIGURATION_Handle *c)
402{
403 char *ego_name;
404
405 ret = 0;
406
407 /* check if method is set */
408 if (NULL == method_name)
409 {
410 ret = 1;
411 fprintf (stderr, _ ("Escrow method (-m option) is missing\n"));
412 return;
413 }
414
415 if (NULL != put_ego)
416 {
417 if (NULL != verify_ego || NULL != get_ego || NULL != status_ego)
418 {
419 ret = 1;
420 fprintf (stderr, _ ("-P may only be used without -V, -G or -S!\n"));
421 return;
422 }
423 /* put */
424 ego_name = put_ego;
425 }
426 else if (NULL != verify_ego)
427 {
428 if (NULL != get_ego || NULL != status_ego)
429 {
430 ret = 1;
431 fprintf (stderr, _ ("-V may only be used without -P, -G or -S!\n"));
432 return;
433 }
434 /* verify */
435 if (NULL == anchor_string)
436 {
437 ret = 1;
438 fprintf (stderr, _ ("-a is needed for -V!\n"));
439 return;
440 }
441 ego_name = verify_ego;
442 }
443 else if (NULL != get_ego)
444 {
445 if (NULL != status_ego)
446 {
447 ret = 1;
448 fprintf (stderr, _ ("-G may only be used without -P, -V or -S!\n"));
449 return;
450 }
451 /* get */
452 if (NULL == anchor_string)
453 {
454 ret = 1;
455 fprintf (stderr, _ ("-a is needed for -G!\n"));
456 return;
457 }
458 ego_name = get_ego;
459 }
460 else if (NULL != status_ego)
461 {
462 /* status */
463 ego_name = status_ego;
464 }
465 else
466 {
467 /* nothing */
468 ret = 1;
469 fprintf (stderr, _ ("-P, -V, -G or -S option must be specified!\n"));
470 return;
471 }
472
473 /* determine method */
474 if (!strncmp (plaintext_string, method_name, strlen (plaintext_string)))
475 method = GNUNET_ESCROW_KEY_PLAINTEXT;
476 else if (!strncmp (gns_string, method_name, strlen (gns_string)))
477 method = GNUNET_ESCROW_KEY_GNS;
478 else if (!strncmp (anastasis_string, method_name, strlen (anastasis_string)))
479 method = GNUNET_ESCROW_KEY_ANASTASIS;
480 else
481 {
482 ret = 1;
483 fprintf (stderr, _ ("unknown method name!"));
484 return;
485 }
486
487 escrow_handle = GNUNET_ESCROW_init (c);
488
489 if (NULL != anchor_string)
490 {
491 /* parse anchor_string according to method */
492 anchor = GNUNET_ESCROW_anchor_string_to_data (escrow_handle,
493 anchor_string,
494 method);
495 }
496
497 /* connect to identity service in order to get the egos */
498 identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, ego_name);
499}
500
501
502int
503main (int argc, char *const argv[])
504{
505 struct GNUNET_GETOPT_CommandLineOption options[] = {
506 GNUNET_GETOPT_option_string ('P',
507 "put",
508 "NAME",
509 gettext_noop ("Put the ego NAME into escrow"),
510 &put_ego),
511 GNUNET_GETOPT_option_string ('V',
512 "verify",
513 "NAME",
514 gettext_noop ("Verify the escrow of the ego NAME"),
515 &verify_ego),
516 GNUNET_GETOPT_option_string ('G',
517 "get",
518 "NAME",
519 gettext_noop ("Get the ego NAME back from escrow"),
520 &get_ego),
521 GNUNET_GETOPT_option_string ('S',
522 "status",
523 "NAME",
524 gettext_noop ("Get the status of the escrow of ego NAME"),
525 &status_ego),
526 GNUNET_GETOPT_option_string ('u',
527 "userSecret",
528 "USER_SECRET",
529 gettext_noop ("The user secret string"),
530 &user_secret_string),
531 GNUNET_GETOPT_option_string ('a',
532 "anchor",
533 "ANCHOR",
534 gettext_noop ("The escrow anchor"),
535 &anchor_string),
536 GNUNET_GETOPT_option_string ('m',
537 "method",
538 "METHOD",
539 gettext_noop ("The escrow method (and plugin) to use"),
540 &method_name),
541 GNUNET_GETOPT_OPTION_END
542 };
543 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
544 argv,
545 "gnunet-escrow",
546 _ ("escrow command line tool"),
547 options,
548 &run,
549 NULL))
550 return 1;
551 else
552 return ret;
553}
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..f9a68728d
--- /dev/null
+++ b/src/escrow/plugin_escrow_gns.c
@@ -0,0 +1,1781 @@
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 struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
74
75 /**
76 * Name of the respective ego
77 */
78 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 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
140// define TimeoutTaskEntry here, as it is already needed in GnsLookupRequest
141struct TimeoutTaskEntry;
142
143
144struct GnsLookupRequestEntry
145{
146 /**
147 * DLL
148 */
149 struct GnsLookupRequestEntry *prev;
150
151 /**
152 * DLL
153 */
154 struct GnsLookupRequestEntry *next;
155
156 /**
157 * GNS lookup request
158 */
159 struct GNUNET_GNS_LookupRequest *lr;
160
161 /**
162 * Plugin operation that started the lookup
163 */
164 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
165
166 /**
167 * index of the respective share
168 */
169 uint8_t i;
170
171 /**
172 * Timeout task scheduled for this lookup request
173 */
174 struct TimeoutTaskEntry *tt;
175};
176
177
178struct TimeoutTaskEntry
179{
180 /**
181 * DLL
182 */
183 struct TimeoutTaskEntry *prev;
184
185 /**
186 * DLL
187 */
188 struct TimeoutTaskEntry *next;
189
190 /**
191 * Timeout task
192 */
193 struct GNUNET_SCHEDULER_Task *tt;
194
195 /**
196 * GNS lookup request this timeout is for
197 */
198 struct GnsLookupRequestEntry *gns_lr;
199
200 /**
201 * Plugin operation that started the timeout
202 */
203 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
204};
205
206
207struct ESCROW_GnsPluginOperation
208{
209 /**
210 * Handle for the escrow component
211 */
212 struct GNUNET_ESCROW_Handle *h;
213
214 /**
215 * Scheduler task the SCHEDULE operation returns (needed for cancellation)
216 */
217 struct GNUNET_SCHEDULER_Task *sched_task;
218
219 /**
220 * Namestore handle
221 */
222 struct GNUNET_NAMESTORE_Handle *ns_h;
223
224 /**
225 * GNS handle
226 */
227 struct GNUNET_GNS_Handle *gns_h;
228
229 /**
230 * Continuation for a plugin operation (e.g. used for restore, as this
231 * callback has to be called from the IDENTITY service after finishing)
232 */
233 ESCROW_Plugin_Continuation cont;
234
235 /**
236 * Ego continuation wrapper
237 */
238 struct ESCROW_Plugin_EgoContinuationWrapper *ego_wrap;
239
240 /**
241 * Anchor continuation wrapper
242 */
243 struct ESCROW_Plugin_AnchorContinuationWrapper *anchor_wrap;
244
245 /**
246 * Verify continuation wrapper
247 */
248 struct ESCROW_Plugin_VerifyContinuationWrapper *verify_wrap;
249
250 /**
251 * Counter for the created escrow identities
252 */
253 uint8_t escrow_id_counter;
254
255 /**
256 * Number of shares
257 */
258 uint8_t shares;
259
260 /**
261 * Share threshold
262 */
263 uint8_t share_threshold;
264
265 /**
266 * Continuation to be called with the restored private key
267 */
268 PkContinuation restore_pk_cont;
269
270 /**
271 * Closure for @a cont
272 */
273 void *restore_pk_cont_cls;
274
275 /**
276 * Array for the restored keyshares
277 */
278 sss_Keyshare *restored_keyshares;
279
280 /**
281 * Identity operation for the create of the restored ego
282 */
283 struct GNUNET_IDENTITY_Operation *id_op;
284
285 /**
286 * The ego
287 */
288 struct GNUNET_IDENTITY_Ego *ego;
289
290 /**
291 * The name of the ego
292 */
293 char *egoName;
294
295 /**
296 * Private key of the ego
297 */
298 struct GNUNET_CRYPTO_EcdsaPrivateKey pk;
299
300 /**
301 * User secret string
302 */
303 char *userSecret;
304
305 /**
306 * DLL head for identity operations
307 */
308 struct IdentityOperationEntry *id_ops_head;
309
310 /**
311 * DLL tail for identity operations
312 */
313 struct IdentityOperationEntry *id_ops_tail;
314
315 /**
316 * DLL head for escrow private keys
317 */
318 struct PkEntry *escrow_pks_head;
319
320 /**
321 * DLL tail for escrow private keys
322 */
323 struct PkEntry *escrow_pks_tail;
324
325 /**
326 * DLL head for namestore queue entries
327 */
328 struct NamestoreQueueEntry *ns_qes_head;
329
330 /**
331 * DLL tail for namestore queue entries
332 */
333 struct NamestoreQueueEntry *ns_qes_tail;
334
335 /**
336 * DLL head for GNS lookup requests
337 */
338 struct GnsLookupRequestEntry *gns_lrs_head;
339
340 /**
341 * DLL tail for GNS lookup requests
342 */
343 struct GnsLookupRequestEntry *gns_lrs_tail;
344
345 /**
346 * DLL head for GNS timeout tasks
347 */
348 struct TimeoutTaskEntry *tts_head;
349
350 /**
351 * DLL tail for GNS timeout tasks
352 */
353 struct TimeoutTaskEntry *tts_tail;
354};
355
356/**
357 * Identity handle
358 */
359static struct GNUNET_IDENTITY_Handle *identity_handle;
360
361/**
362 * Handle for the plugin instance
363 */
364struct ESCROW_PluginHandle ph;
365
366
367/**
368 * Clean up a plugin operation, i.e. remove it from the list and
369 * free the respective memory
370 */
371void
372cleanup_plugin_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
373{
374 struct ESCROW_GnsPluginOperation *p_op;
375 struct IdentityOperationEntry *curr_id_op, *next_id_op;
376 struct PkEntry *curr_pk, *next_pk;
377 struct NamestoreQueueEntry *curr_ns_qe, *next_ns_qe;
378 struct GnsLookupRequestEntry *curr_gns_lr, *next_gns_lr;
379 struct TimeoutTaskEntry *curr_tt, *next_tt;
380
381 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
382
383 GNUNET_CONTAINER_DLL_remove (ph.plugin_op_head,
384 ph.plugin_op_tail,
385 plugin_op_wrap);
386 if (NULL != p_op->anchor_wrap)
387 GNUNET_free (p_op->anchor_wrap);
388 if (NULL != p_op->ego_wrap)
389 GNUNET_free (p_op->ego_wrap);
390 if (NULL != p_op->verify_wrap)
391 GNUNET_free (p_op->verify_wrap);
392 if (NULL != p_op->userSecret)
393 GNUNET_free (p_op->userSecret);
394 /* clean up identity operation list */
395 for (curr_id_op = p_op->id_ops_head; NULL != curr_id_op; curr_id_op = next_id_op)
396 {
397 next_id_op = curr_id_op->next;
398 GNUNET_CONTAINER_DLL_remove (p_op->id_ops_head,
399 p_op->id_ops_tail,
400 curr_id_op);
401 GNUNET_IDENTITY_cancel (curr_id_op->id_op);
402 GNUNET_free (curr_id_op->pk);
403 GNUNET_free (curr_id_op->name);
404 GNUNET_free (curr_id_op);
405 }
406 /* clean up escrow pk list */
407 for (curr_pk = p_op->escrow_pks_head; NULL != curr_pk; curr_pk = next_pk)
408 {
409 next_pk = curr_pk->next;
410 GNUNET_CONTAINER_DLL_remove (p_op->escrow_pks_head,
411 p_op->escrow_pks_tail,
412 curr_pk);
413 GNUNET_free (curr_pk);
414 }
415 /* clean up namestore operation list */
416 for (curr_ns_qe = p_op->ns_qes_head; NULL != curr_ns_qe; curr_ns_qe = next_ns_qe)
417 {
418 next_ns_qe = curr_ns_qe->next;
419 GNUNET_CONTAINER_DLL_remove (p_op->ns_qes_head,
420 p_op->ns_qes_tail,
421 curr_ns_qe);
422 // also frees the curr_ns_qe->ns_qe
423 GNUNET_NAMESTORE_cancel (curr_ns_qe->ns_qe);
424 GNUNET_free (curr_ns_qe);
425 }
426 /* clean up GNS lookup request list */
427 for (curr_gns_lr = p_op->gns_lrs_head; NULL != curr_gns_lr; curr_gns_lr = next_gns_lr)
428 {
429 next_gns_lr = curr_gns_lr->next;
430 GNUNET_CONTAINER_DLL_remove (p_op->gns_lrs_head,
431 p_op->gns_lrs_tail,
432 curr_gns_lr);
433 GNUNET_GNS_lookup_cancel (curr_gns_lr->lr);
434 GNUNET_free (curr_gns_lr);
435 }
436 /* clean up timeout task list */
437 for (curr_tt = p_op->tts_head; NULL != curr_tt; curr_tt = next_tt)
438 {
439 next_tt = curr_tt->next;
440 GNUNET_CONTAINER_DLL_remove (p_op->tts_head,
441 p_op->tts_tail,
442 curr_tt);
443 GNUNET_SCHEDULER_cancel (curr_tt->tt);
444 GNUNET_free (curr_tt);
445 }
446 /* free the keyshares array */
447 if (NULL != p_op->restored_keyshares)
448 GNUNET_free (p_op->restored_keyshares);
449 /* disconnect from namestore service */
450 if (NULL != p_op->ns_h)
451 GNUNET_NAMESTORE_disconnect (p_op->ns_h);
452 /* disconnect from GNS service */
453 if (NULL != p_op->gns_h)
454 GNUNET_GNS_disconnect (p_op->gns_h);
455 /* cancel scheduled task */
456 if (NULL != p_op->sched_task)
457 GNUNET_SCHEDULER_cancel (p_op->sched_task);
458 /* cancel identity operation */
459 if (NULL != p_op->id_op)
460 GNUNET_IDENTITY_cancel (p_op->id_op);
461 if (NULL != p_op->egoName)
462 GNUNET_free (p_op->egoName);
463 GNUNET_free (p_op);
464 GNUNET_free (plugin_op_wrap);
465}
466
467
468void
469start_cont (void *cls)
470{
471 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
472 struct ESCROW_GnsPluginOperation *p_op;
473
474 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
475 p_op->cont (p_op->anchor_wrap);
476
477 cleanup_plugin_operation (plugin_op_wrap);
478}
479
480
481void
482verify_cont (void *cls)
483{
484 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
485 struct ESCROW_GnsPluginOperation *p_op;
486
487 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
488 p_op->cont (p_op->verify_wrap);
489
490 cleanup_plugin_operation (plugin_op_wrap);
491}
492
493
494static void
495handle_restore_error (void *cls)
496{
497 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
498 struct ESCROW_GnsPluginOperation *p_op;
499
500 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
501 p_op->cont (p_op->ego_wrap);
502
503 cleanup_plugin_operation (plugin_op_wrap);
504}
505
506
507sss_Keyshare *
508split_private_key (struct ESCROW_GnsPluginOperation *p_op)
509{
510 sss_Keyshare *keyshares;
511
512 keyshares = GNUNET_malloc (sizeof (sss_Keyshare) * p_op->shares);
513 sss_create_keyshares (keyshares,
514 p_op->pk.d,
515 p_op->shares,
516 p_op->share_threshold);
517
518 return keyshares;
519}
520
521
522static void
523keyshare_distribution_finished (void *cls)
524{
525 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
526 struct ESCROW_GnsPluginOperation *p_op;
527 struct GNUNET_ESCROW_Anchor *anchor;
528 int anchorDataSize;
529
530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All keyshares distributed\n");
531
532 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
533
534 anchorDataSize = strlen(p_op->userSecret) + 1;
535 anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + anchorDataSize);
536 anchor->method = GNUNET_ESCROW_KEY_GNS;
537 anchor->size = anchorDataSize;
538 GNUNET_memcpy (&anchor[1], p_op->userSecret, anchorDataSize);
539
540 p_op->anchor_wrap->escrowAnchor = anchor;
541
542 /* set the last escrow time */
543 ESCROW_update_escrow_status (p_op->h, p_op->ego, "gns");
544
545 /* call the continuation */
546 start_cont (plugin_op_wrap);
547}
548
549
550static void
551keyshare_distributed (void *cls,
552 int32_t success,
553 const char *emsg)
554{
555 struct NamestoreQueueEntry *ns_qe = cls;
556 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
557 struct ESCROW_GnsPluginOperation *p_op;
558
559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Keyshare distributed\n");
560
561 plugin_op_wrap = ns_qe->plugin_op_wrap;
562 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
563
564 // remove qe from our list
565 GNUNET_CONTAINER_DLL_remove (p_op->ns_qes_head,
566 p_op->ns_qes_tail,
567 ns_qe);
568
569 if (GNUNET_SYSERR == success)
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 "Failed to store keyshare %s\n",
573 emsg);
574 p_op->anchor_wrap->escrowAnchor = NULL;
575 p_op->anchor_wrap->emsg = _ ("Keyshare distribution failed!\n");
576 p_op->cont (p_op->anchor_wrap);
577 // this also cancels all running namestore operations
578 cleanup_plugin_operation (plugin_op_wrap);
579 return;
580 }
581
582 // check if all namestore operations are finished
583 GNUNET_free (ns_qe);
584 if (NULL == p_op->ns_qes_head)
585 {
586 // schedule the further execution, lets NAMESTORE clean up its operation list
587 GNUNET_SCHEDULER_add_now (&keyshare_distribution_finished, plugin_op_wrap);
588 }
589}
590
591
592static char *
593get_label (const char *userSecret)
594{
595 char *label;
596 struct GNUNET_HashCode hash;
597 struct GNUNET_CRYPTO_HashAsciiEncoded hashEnc;
598
599 // the label is the hash of the userSecret
600 GNUNET_CRYPTO_hash (userSecret, strlen (userSecret), &hash);
601 GNUNET_CRYPTO_hash_to_enc (&hash, &hashEnc);
602 label = GNUNET_strdup ((char *)hashEnc.encoding);
603
604 return label;
605}
606
607
608static int
609distribute_keyshares (struct ESCROW_PluginOperationWrapper *plugin_op_wrap,
610 sss_Keyshare *keyshares)
611{
612 struct ESCROW_GnsPluginOperation *p_op;
613 struct GNUNET_NAMESTORE_Handle *ns_h;
614 struct NamestoreQueueEntry *curr_ns_qe;
615 struct PkEntry *curr_pk;
616 char *curr_label;
617 struct GNUNET_GNSRECORD_Data curr_rd[1];
618
619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Distributing keyshares\n");
620
621 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
622
623 ns_h = GNUNET_NAMESTORE_connect (p_op->h->cfg);
624 p_op->ns_h = ns_h;
625
626 for (curr_pk = p_op->escrow_pks_head; NULL != curr_pk; curr_pk = curr_pk->next)
627 {
628 curr_label = get_label (p_op->userSecret);
629 curr_ns_qe = GNUNET_new (struct NamestoreQueueEntry);
630
631 curr_rd[0].data_size = sizeof (sss_Keyshare);
632 curr_rd[0].data = keyshares[curr_pk->i];
633 curr_rd[0].record_type = GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE;
634 curr_rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
635 // TODO: config param?
636 curr_rd[0].expiration_time = 30 * 24 * GNUNET_TIME_relative_get_hour_().rel_value_us;
637
638 curr_ns_qe->plugin_op_wrap = plugin_op_wrap;
639 curr_ns_qe->ns_qe = GNUNET_NAMESTORE_records_store (ns_h,
640 &curr_pk->pk,
641 curr_label,
642 1,
643 curr_rd,
644 &keyshare_distributed,
645 curr_ns_qe);
646 GNUNET_CONTAINER_DLL_insert_tail (p_op->ns_qes_head,
647 p_op->ns_qes_tail,
648 curr_ns_qe);
649 GNUNET_free (curr_label);
650 }
651
652 return GNUNET_OK;
653}
654
655
656void
657escrow_ids_finished (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
658{
659 struct ESCROW_GnsPluginOperation *p_op;
660 sss_Keyshare *keyshares;
661
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All escrow identities created\n");
663
664 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
665
666 /* split the private key (SSS) */
667 keyshares = split_private_key (p_op);
668 if (NULL == keyshares)
669 {
670 p_op->anchor_wrap->escrowAnchor = NULL;
671 p_op->anchor_wrap->emsg = _ ("Failed to split the key!\n");
672 start_cont (plugin_op_wrap);
673 return;
674 }
675
676 /* distribute the shares to the identities */
677 if (GNUNET_OK != distribute_keyshares (plugin_op_wrap, keyshares))
678 {
679 p_op->anchor_wrap->escrowAnchor = NULL;
680 p_op->anchor_wrap->emsg = _ ("Failed to distribute the keyshares!\n");
681 start_cont (plugin_op_wrap);
682 return;
683 }
684
685 /* operation continues in keyshare_distribution_finished
686 after all keyshares have been distributed */
687}
688
689
690void
691escrow_id_created (void *cls,
692 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
693 const char *emsg)
694{
695 struct IdentityOperationEntry *id_op = cls;
696 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
697 struct ESCROW_GnsPluginOperation *p_op;
698 struct PkEntry *pk_entry;
699
700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Escrow identity %d created\n", id_op->i);
701
702 plugin_op_wrap = id_op->plugin_op_wrap;
703 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
704
705 if (NULL == pk)
706 {
707 if (NULL != emsg)
708 {
709 fprintf (stderr,
710 "Identity create operation returned with error: %s\n",
711 emsg);
712 p_op->anchor_wrap->emsg = _ ("Identity create failed!\n");
713 }
714 else
715 p_op->anchor_wrap->emsg = _ ("Failed to create ego!\n");
716 p_op->anchor_wrap->escrowAnchor = NULL;
717 p_op->cont (p_op->anchor_wrap);
718 // this also cancels all running identity operations
719 cleanup_plugin_operation (plugin_op_wrap);
720 return;
721 }
722
723 /* escrow identity successfully created */
724 GNUNET_CONTAINER_DLL_remove (p_op->id_ops_head,
725 p_op->id_ops_tail,
726 id_op);
727
728 /* insert pk into our list */
729 pk_entry = GNUNET_new (struct PkEntry);
730 pk_entry->pk = *pk;
731 pk_entry->i = id_op->i;
732 GNUNET_CONTAINER_DLL_insert_tail (p_op->escrow_pks_head,
733 p_op->escrow_pks_tail,
734 pk_entry);
735
736 GNUNET_free (id_op);
737
738 /* check if this was the last id_op */
739 p_op->escrow_id_counter++;
740 if (p_op->escrow_id_counter == p_op->shares)
741 {
742 escrow_ids_finished (plugin_op_wrap);
743 }
744}
745
746
747static uint8_t
748count_digits (uint8_t n)
749{
750 uint8_t i = 0;
751
752 do
753 {
754 i++;
755 n /= 10;
756 } while (n != 0);
757
758 return i;
759}
760
761
762static char *
763get_escrow_id_name (const char *name,
764 uint8_t i)
765{
766 char *str, *prefix, *number;
767 uint8_t j = 0;
768
769 prefix = "escrow-id_";
770 number = GNUNET_malloc (count_digits (i) + 1);
771 sprintf (number, "%d", i);
772
773 str = GNUNET_malloc (strlen (prefix)
774 + strlen (name)
775 + 1
776 + strlen (number)
777 + 1);
778
779 memcpy (str, prefix, strlen (prefix));
780 j += strlen (prefix);
781 memcpy (str + j, name, strlen (name));
782 j += strlen (name);
783 str[j++] = '_';
784 memcpy (str + j, number, strlen (number));
785 j += strlen (number);
786 str[j] = '\0';
787
788 GNUNET_free (number);
789
790 return str;
791}
792
793
794static int
795escrow_id_exists (const char *name,
796 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
797{
798 struct EgoEntry *curr;
799
800 for (curr = ph.ego_head; NULL != curr; curr = curr->next)
801 {
802 if (0 == strcmp (name, curr->identifier))
803 {
804 if (0 == memcmp (&curr->ego->pk,
805 pk,
806 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
807 return GNUNET_YES;
808 else // the escrow id's name exists for an ego, but the pk is wrong
809 return GNUNET_SYSERR;
810 }
811 }
812
813 return GNUNET_NO;
814}
815
816
817static struct GNUNET_CRYPTO_EcdsaPrivateKey *
818derive_private_key (const char *name,
819 const char *password,
820 uint8_t i)
821{
822 struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
823 static const char ctx[] = "gnunet-escrow-id-ctx";
824
825 pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
826 GNUNET_CRYPTO_kdf (pk,
827 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
828 ctx, strlen (ctx),
829 password, strlen (password),
830 name, strlen (name),
831 &i, 1,
832 NULL);
833
834 pk->d[0] &= 248;
835 pk->d[31] &= 127;
836 pk->d[31] |= 64;
837
838 return pk;
839}
840
841
842static void
843handle_existing_wrong_ego_deletion (void *cls,
844 const char *emsg)
845{
846 struct IdentityOperationEntry *curr_id_op = cls;
847 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
848 struct ESCROW_GnsPluginOperation *p_op;
849
850 plugin_op_wrap = curr_id_op->plugin_op_wrap;
851 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
852
853 if (NULL != emsg)
854 {
855 fprintf (stderr,
856 "Identity create operation returned with error: %s\n",
857 emsg);
858 p_op->anchor_wrap->emsg = _ ("Identity delete of wrong existing ego failed!\n");
859 p_op->anchor_wrap->escrowAnchor = NULL;
860 p_op->cont (p_op->anchor_wrap);
861 // this also cancels all running identity operations
862 cleanup_plugin_operation (plugin_op_wrap);
863 return;
864 }
865
866 /* no error occured, so create the new identity */
867 // the IdentityOperationEntry is reused, so only the id_op is updated
868 curr_id_op->id_op = GNUNET_IDENTITY_create (identity_handle,
869 curr_id_op->name,
870 curr_id_op->pk,
871 &escrow_id_created,
872 curr_id_op);
873}
874
875
876static void
877create_escrow_identities (struct ESCROW_PluginOperationWrapper *plugin_op_wrap,
878 const char *name)
879{
880 struct ESCROW_GnsPluginOperation *p_op;
881 struct GNUNET_CRYPTO_EcdsaPrivateKey *curr_pk;
882 char *curr_name, *curr_pk_string;
883 struct IdentityOperationEntry *curr_id_op;
884 struct PkEntry *curr_pk_entry;
885 int exists_ret;
886
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating escrow identities\n");
888
889 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
890
891 for (uint8_t i = 0; i < p_op->shares; i++)
892 {
893 curr_pk = derive_private_key (name, p_op->userSecret, i);
894 curr_name = get_escrow_id_name (name, i);
895
896 // TODO: REMOVE THIS LOGGING BEFORE PRODUCTIONAL USE!
897 curr_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (curr_pk);
898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
899 "derived private key: %s\n",
900 curr_pk_string);
901 GNUNET_free (curr_pk_string);
902
903 // check if the escrow identity already exists
904 exists_ret = escrow_id_exists (curr_name, curr_pk);
905 if (GNUNET_SYSERR == exists_ret)
906 {
907 /* an ego with identifier name but the wrong pk exists, delete it first */
908 curr_id_op = GNUNET_new (struct IdentityOperationEntry);
909 curr_id_op->pk = curr_pk;
910 curr_id_op->name = curr_name;
911 curr_id_op->i = i;
912 curr_id_op->plugin_op_wrap = plugin_op_wrap;
913 curr_id_op->id_op = GNUNET_IDENTITY_delete (identity_handle,
914 curr_name,
915 &handle_existing_wrong_ego_deletion,
916 curr_id_op);
917 GNUNET_CONTAINER_DLL_insert (p_op->id_ops_head,
918 p_op->id_ops_tail,
919 curr_id_op);
920 }
921 else if (GNUNET_YES == exists_ret)
922 {
923 // the escrow id already exists, so insert the pk into our list
924 curr_pk_entry = GNUNET_new (struct PkEntry);
925 curr_pk_entry->pk = *curr_pk;
926 curr_pk_entry->i = i;
927 GNUNET_CONTAINER_DLL_insert (p_op->escrow_pks_head,
928 p_op->escrow_pks_tail,
929 curr_pk_entry);
930
931 p_op->escrow_id_counter++;
932 if (p_op->escrow_id_counter == p_op->shares)
933 {
934 escrow_ids_finished (plugin_op_wrap);
935 }
936 }
937 else // GNUNET_NO
938 {
939 /* store the identity operation in our list */
940 curr_id_op = GNUNET_new (struct IdentityOperationEntry);
941 curr_id_op->pk = curr_pk;
942 curr_id_op->name = curr_name;
943 curr_id_op->i = i;
944 curr_id_op->plugin_op_wrap = plugin_op_wrap;
945 curr_id_op->id_op = GNUNET_IDENTITY_create (identity_handle,
946 curr_name,
947 curr_pk,
948 &escrow_id_created,
949 curr_id_op);
950 GNUNET_CONTAINER_DLL_insert (p_op->id_ops_head,
951 p_op->id_ops_tail,
952 curr_id_op);
953 }
954 }
955}
956
957
958static void
959handle_config_load_error (struct ESCROW_PluginOperationWrapper *plugin_op_wrap,
960 char *emsg)
961{
962 struct ESCROW_GnsPluginOperation *p_op;
963
964 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
965
966 if (NULL != p_op->anchor_wrap)
967 {
968 p_op->anchor_wrap->escrowAnchor = NULL;
969 p_op->anchor_wrap->emsg = emsg;
970 p_op->sched_task = GNUNET_SCHEDULER_add_now (&start_cont, plugin_op_wrap);
971 return;
972 }
973
974 if (NULL != p_op->verify_wrap)
975 {
976 p_op->verify_wrap->verificationResult = GNUNET_ESCROW_INVALID;
977 p_op->verify_wrap->emsg = emsg;
978 p_op->sched_task = GNUNET_SCHEDULER_add_now (&verify_cont, plugin_op_wrap);
979 return;
980 }
981
982 if (NULL != p_op->ego_wrap)
983 {
984 p_op->ego_wrap->ego = NULL;
985 p_op->ego_wrap->emsg = emsg;
986 p_op->sched_task = GNUNET_SCHEDULER_add_now (&handle_restore_error, plugin_op_wrap);
987 return;
988 }
989}
990
991
992static int
993load_keyshare_config (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
994{
995 struct ESCROW_GnsPluginOperation *p_op;
996 unsigned long long shares, share_threshold;
997
998 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
999
1000 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (p_op->h->cfg,
1001 "escrow",
1002 "gns_shares",
1003 &shares))
1004 {
1005 handle_config_load_error (plugin_op_wrap,
1006 "Number of shares not specified in config!");
1007 return GNUNET_SYSERR;
1008 }
1009 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (p_op->h->cfg,
1010 "escrow",
1011 "gns_share_threshold",
1012 &share_threshold))
1013 {
1014 handle_config_load_error (plugin_op_wrap,
1015 "Share threshold not specified in config");
1016 return GNUNET_SYSERR;
1017 }
1018 p_op->shares = (uint8_t)shares;
1019 p_op->share_threshold = (uint8_t)share_threshold;
1020
1021 return GNUNET_OK;
1022}
1023
1024
1025static void
1026continue_start (void *cls)
1027{
1028 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1029 struct ESCROW_GnsPluginOperation *p_op;
1030 struct GNUNET_TIME_Relative delay;
1031
1032 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1033
1034 if (ESCROW_PLUGIN_STATE_POST_INIT != ph.state)
1035 {
1036 delay.rel_value_us = 100 * GNUNET_TIME_relative_get_millisecond_().rel_value_us;
1037 GNUNET_SCHEDULER_add_delayed (delay, &continue_start, plugin_op_wrap);
1038 return;
1039 }
1040
1041 /* load config */
1042 if (GNUNET_OK != load_keyshare_config (plugin_op_wrap))
1043 return;
1044
1045 /* create the escrow identities */
1046 create_escrow_identities (plugin_op_wrap, p_op->ego->name);
1047
1048 /* operation continues in escrow_ids_finished
1049 after all escrow identities are created */
1050}
1051
1052
1053/**
1054 * Start the GNS escrow of the key
1055 *
1056 * @param h the handle for the escrow component
1057 * @param ego the identity ego containing the private key
1058 * @param userSecret the user secret (used for derivation of escrow identities)
1059 * this has to be UNIQUE in the whole network!
1060 * @param cb the function called upon completion
1061 * @param op_id unique ID of the respective ESCROW_Operation
1062 *
1063 * @return plugin operation wrapper
1064 */
1065struct ESCROW_PluginOperationWrapper *
1066start_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
1067 struct GNUNET_IDENTITY_Ego *ego,
1068 const char *userSecret,
1069 GNUNET_SCHEDULER_TaskCallback cb,
1070 uint32_t op_id)
1071{
1072 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
1073 struct ESCROW_GnsPluginOperation *p_op;
1074 struct ESCROW_Plugin_AnchorContinuationWrapper *w;
1075 struct GNUNET_TIME_Relative delay;
1076
1077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting GNS escrow\n");
1078
1079 // create a new GNS plugin operation (in a wrapper) and insert it into the DLL
1080 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
1081 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
1082 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
1083 ph.plugin_op_tail,
1084 plugin_op_wrap);
1085
1086 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1087 p_op->h = h;
1088 p_op->cont = cb;
1089 p_op->ego = ego;
1090
1091 w = GNUNET_new (struct ESCROW_Plugin_AnchorContinuationWrapper);
1092 w->h = h;
1093 w->op_id = op_id;
1094 p_op->anchor_wrap = w;
1095
1096 if (NULL == ego || NULL == userSecret)
1097 {
1098 w->escrowAnchor = NULL;
1099 if (NULL == ego)
1100 w->emsg = _ ("ESCROW_put was called with ego == NULL\n");
1101 else if (NULL == userSecret)
1102 w->emsg = _ ("GNS escrow needs a user secret!\n");
1103 p_op->sched_task = GNUNET_SCHEDULER_add_now (&start_cont, plugin_op_wrap);
1104 return plugin_op_wrap;
1105 }
1106 p_op->pk = *GNUNET_IDENTITY_ego_get_private_key (ego);
1107 p_op->userSecret = GNUNET_strdup (userSecret);
1108
1109 if (ESCROW_PLUGIN_STATE_POST_INIT == ph.state)
1110 {
1111 continue_start (plugin_op_wrap);
1112 }
1113 else
1114 {
1115 delay.rel_value_us = 200 * GNUNET_TIME_relative_get_millisecond_().rel_value_us;
1116 GNUNET_SCHEDULER_add_delayed (delay, &continue_start, plugin_op_wrap);
1117 }
1118
1119 return plugin_op_wrap;
1120}
1121
1122
1123static uint8_t
1124count_keyshares (sss_Keyshare *keyshares, uint8_t n)
1125{
1126 uint8_t i, c;
1127 sss_Keyshare null_ks;
1128
1129 memset (null_ks, 0, sizeof (sss_Keyshare));
1130
1131 c = 0;
1132 for (i = 0; i < n; i++)
1133 {
1134 if (0 != memcmp (keyshares[i], &null_ks, sizeof (sss_Keyshare)))
1135 c++;
1136 }
1137
1138 return c;
1139}
1140
1141
1142static void
1143remove_empty_keyshares (sss_Keyshare *keyshares, uint8_t n)
1144{
1145 uint8_t i, j;
1146 sss_Keyshare null_ks;
1147
1148 memset (null_ks, 0, sizeof (sss_Keyshare));
1149
1150 for (i = j = 0; i < n; i++)
1151 {
1152 if (0 != memcmp (keyshares[i], &null_ks, sizeof (sss_Keyshare)))
1153 {
1154 memcpy (keyshares[j], keyshares[i], sizeof (sss_Keyshare));
1155 j++;
1156 }
1157 }
1158}
1159
1160
1161static void
1162process_keyshares (void *cls)
1163{
1164 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1165 struct ESCROW_GnsPluginOperation *p_op;
1166 struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
1167 uint8_t keyshares_count;
1168
1169 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1170
1171 /* check if enough keyshares have been restored */
1172 keyshares_count = count_keyshares (p_op->restored_keyshares, p_op->shares);
1173 if (keyshares_count < p_op->share_threshold)
1174 {
1175 /* the key cannot be restored */
1176 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1177 "need %hhu shares, but could only get %hhu\n",
1178 p_op->share_threshold,
1179 keyshares_count);
1180
1181 if (NULL != p_op->verify_wrap) // this was called by a verify operation
1182 {
1183 p_op->verify_wrap->emsg =
1184 _ ("key could not be restored, failed to get enough keyshares\n");
1185 p_op->restore_pk_cont (p_op->restore_pk_cont_cls, NULL);
1186 return;
1187 }
1188
1189 if (NULL != p_op->ego_wrap) // this was called by a restore operation
1190 {
1191 p_op->ego_wrap->emsg =
1192 _ ("key could not be restored, failed to get enough keyshares\n");
1193 p_op->restore_pk_cont (p_op->restore_pk_cont_cls, NULL);
1194 return;
1195 }
1196 }
1197
1198 /* combine the shares */
1199 if (keyshares_count != p_op->shares)
1200 remove_empty_keyshares (p_op->restored_keyshares, p_op->shares);
1201
1202 pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1203 sss_combine_keyshares (pk->d,
1204 p_op->restored_keyshares,
1205 keyshares_count);
1206
1207 p_op->restore_pk_cont (p_op->restore_pk_cont_cls, pk);
1208}
1209
1210
1211static void
1212process_gns_lookup_result (void *cls,
1213 uint32_t rd_count,
1214 const struct GNUNET_GNSRECORD_Data *rd)
1215{
1216 struct GnsLookupRequestEntry *gns_lr = cls;
1217 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
1218 struct ESCROW_GnsPluginOperation *p_op;
1219 sss_Keyshare keyshare;
1220 char keyshare_string[64], *end;
1221
1222 plugin_op_wrap = gns_lr->plugin_op_wrap;
1223 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1224
1225 /* remove gns_lr from our list */
1226 GNUNET_CONTAINER_DLL_remove (p_op->gns_lrs_head,
1227 p_op->gns_lrs_tail,
1228 gns_lr);
1229
1230 /* cancel the timeout for that lookup */
1231 GNUNET_CONTAINER_DLL_remove (p_op->tts_head,
1232 p_op->tts_tail,
1233 gns_lr->tt);
1234 GNUNET_SCHEDULER_cancel (gns_lr->tt->tt);
1235 GNUNET_free (gns_lr->tt);
1236
1237 if (1 != rd_count)
1238 {
1239 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1240 "did not get exactly _one_ record from GNS\n");
1241 goto END;
1242 }
1243
1244 if (sizeof (sss_Keyshare) != rd[0].data_size)
1245 {
1246 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1247 "the size of the GNS record differs from the size of a keyshare\n");
1248 goto END;
1249 }
1250
1251 GNUNET_memcpy (&keyshare,
1252 rd[0].data,
1253 rd[0].data_size);
1254
1255 end = GNUNET_STRINGS_data_to_string (&keyshare,
1256 sizeof (sss_Keyshare),
1257 keyshare_string,
1258 sizeof (keyshare_string));
1259 GNUNET_break (NULL != end);
1260 *end = '\0';
1261
1262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1263 "got keyshare %s from GNS\n", keyshare_string);
1264
1265 GNUNET_memcpy (p_op->restored_keyshares[gns_lr->i],
1266 &keyshare,
1267 sizeof (sss_Keyshare));
1268
1269 END:
1270 GNUNET_free (gns_lr);
1271
1272 // check if this was the last gns_lr, i.e. our list is empty
1273 if (NULL == p_op->gns_lrs_head)
1274 {
1275 // schedule the further execution, lets GNS clean up its operation list
1276 GNUNET_SCHEDULER_add_now (&process_keyshares, plugin_op_wrap);
1277 }
1278}
1279
1280
1281static void
1282timeout_gns_request (void *cls)
1283{
1284 struct TimeoutTaskEntry *curr_tt = cls;
1285 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
1286 struct ESCROW_GnsPluginOperation *p_op;
1287
1288 plugin_op_wrap = curr_tt->plugin_op_wrap;
1289 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1290
1291 /* remove timeout task from our list */
1292 GNUNET_CONTAINER_DLL_remove (p_op->tts_head,
1293 p_op->tts_tail,
1294 curr_tt);
1295
1296 /* cancel the GNS lookup and remove it from our list */
1297 GNUNET_GNS_lookup_cancel (curr_tt->gns_lr->lr);
1298 GNUNET_CONTAINER_DLL_remove (p_op->gns_lrs_head,
1299 p_op->gns_lrs_tail,
1300 curr_tt->gns_lr);
1301 GNUNET_free (curr_tt->gns_lr);
1302
1303 GNUNET_free (curr_tt);
1304
1305 /* check if this was the last pending GNS lookup */
1306 if (NULL == p_op->gns_lrs_head)
1307 {
1308 // no need to schedule, as the timeout is already scheduled
1309 process_keyshares (plugin_op_wrap);
1310 }
1311}
1312
1313
1314static void
1315restore_private_key (struct ESCROW_PluginOperationWrapper *plugin_op_wrap,
1316 struct GNUNET_ESCROW_Anchor *escrowAnchor,
1317 PkContinuation cont,
1318 void *cont_cls)
1319{
1320 struct ESCROW_GnsPluginOperation *p_op;
1321 struct GNUNET_CRYPTO_EcdsaPrivateKey *curr_escrow_pk;
1322 struct GNUNET_CRYPTO_EcdsaPublicKey curr_escrow_pub;
1323 char *label, *curr_escrow_pk_string;
1324 struct GnsLookupRequestEntry *curr_gns_lr;
1325 struct GNUNET_TIME_Relative delay;
1326 struct TimeoutTaskEntry *curr_tt;
1327
1328 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1329
1330 p_op->gns_h = GNUNET_GNS_connect (p_op->h->cfg);
1331 p_op->restore_pk_cont = cont;
1332 p_op->restore_pk_cont_cls = cont_cls;
1333 p_op->restored_keyshares = GNUNET_malloc (sizeof (sss_Keyshare) * p_op->shares);
1334 // ensure that the array is initialized with 0, as this is needed for counting the shares
1335 memset (p_op->restored_keyshares, 0, sizeof (sss_Keyshare) * p_op->shares);
1336
1337 label = get_label (p_op->userSecret);
1338
1339 // init delay to 2s
1340 delay.rel_value_us = 2 * GNUNET_TIME_relative_get_second_().rel_value_us;
1341
1342 for (uint8_t i = 0; i < p_op->shares; i++)
1343 {
1344 curr_escrow_pk = derive_private_key (p_op->egoName, p_op->userSecret, i);
1345
1346 // TODO: REMOVE THIS LOGGING BEFORE PRODUCTIONAL USE!
1347 curr_escrow_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (curr_escrow_pk);
1348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1349 "derived private key: %s\n",
1350 curr_escrow_pk_string);
1351 GNUNET_free (curr_escrow_pk_string);
1352
1353 curr_gns_lr = GNUNET_new (struct GnsLookupRequestEntry);
1354 curr_gns_lr->plugin_op_wrap = plugin_op_wrap;
1355 curr_gns_lr->i = i;
1356 GNUNET_CRYPTO_ecdsa_key_get_public (curr_escrow_pk, &curr_escrow_pub);
1357 curr_gns_lr->lr = GNUNET_GNS_lookup (p_op->gns_h,
1358 label,
1359 &curr_escrow_pub,
1360 GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE,
1361 GNUNET_GNS_LO_DEFAULT,
1362 &process_gns_lookup_result,
1363 curr_gns_lr);
1364 GNUNET_CONTAINER_DLL_insert_tail (p_op->gns_lrs_head,
1365 p_op->gns_lrs_tail,
1366 curr_gns_lr);
1367
1368 /* start timeout for GNS lookup (cancels the lr if not yet finished) */
1369 curr_tt = GNUNET_new (struct TimeoutTaskEntry);
1370 curr_tt->gns_lr = curr_gns_lr;
1371 curr_tt->plugin_op_wrap = plugin_op_wrap;
1372 curr_tt->tt = GNUNET_SCHEDULER_add_delayed (delay,
1373 &timeout_gns_request,
1374 curr_tt);
1375 GNUNET_CONTAINER_DLL_insert_tail (p_op->tts_head,
1376 p_op->tts_tail,
1377 curr_tt);
1378
1379 // set the timeout task for the current gns lr entry
1380 curr_gns_lr->tt = curr_tt;
1381 }
1382 GNUNET_free (label);
1383}
1384
1385
1386static void
1387verify_restored_pk (void *cls,
1388 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
1389{
1390 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1391 struct ESCROW_GnsPluginOperation *p_op;
1392 const struct GNUNET_CRYPTO_EcdsaPrivateKey *ego_pk;
1393 int verificationResult;
1394
1395 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1396
1397 if (NULL == pk)
1398 verificationResult = GNUNET_ESCROW_INVALID;
1399 else
1400 {
1401 ego_pk = GNUNET_IDENTITY_ego_get_private_key (p_op->ego);
1402 verificationResult = memcmp (pk,
1403 ego_pk,
1404 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
1405 == 0 ? GNUNET_ESCROW_VALID : GNUNET_ESCROW_INVALID;
1406 }
1407
1408 // check if all shares could be restored
1409 if (GNUNET_ESCROW_VALID == verificationResult &&
1410 count_keyshares (p_op->restored_keyshares, p_op->shares) < p_op->shares)
1411 verificationResult = GNUNET_ESCROW_SHARES_MISSING;
1412
1413 p_op->verify_wrap->verificationResult = verificationResult;
1414 verify_cont (plugin_op_wrap);
1415}
1416
1417
1418/**
1419 * Verify the GNS escrow of the key
1420 *
1421 * @param h the handle for the escrow component
1422 * @param ego the identity ego containing the private key
1423 * @param escrowAnchor the escrow anchor needed to restore the key
1424 * @param cb the function called upon completion
1425 * @param op_id unique ID of the respective ESCROW_Operation
1426 *
1427 * @return plugin operation wrapper
1428 */
1429struct ESCROW_PluginOperationWrapper *
1430verify_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
1431 struct GNUNET_IDENTITY_Ego *ego,
1432 struct GNUNET_ESCROW_Anchor *escrowAnchor,
1433 GNUNET_SCHEDULER_TaskCallback cb,
1434 uint32_t op_id)
1435{
1436 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
1437 struct ESCROW_GnsPluginOperation *p_op;
1438 struct ESCROW_Plugin_VerifyContinuationWrapper *w;
1439
1440 // create a new GNS plugin operation (in a wrapper) and insert it into the DLL
1441 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
1442 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
1443 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
1444 ph.plugin_op_tail,
1445 plugin_op_wrap);
1446
1447 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1448 p_op->h = h;
1449 p_op->cont = cb;
1450 p_op->ego = ego;
1451 p_op->egoName = GNUNET_strdup (ego->name);
1452 p_op->userSecret = gns_anchor_data_to_string (h, escrowAnchor);
1453
1454 w = GNUNET_new (struct ESCROW_Plugin_VerifyContinuationWrapper);
1455 w->h = h;
1456 w->op_id = op_id;
1457 p_op->verify_wrap = w;
1458
1459 if (NULL == ego)
1460 {
1461 w->verificationResult = GNUNET_ESCROW_INVALID;
1462 w->emsg = _ ("ESCROW_verify was called with ego == NULL!\n");
1463 p_op->sched_task = GNUNET_SCHEDULER_add_now (&verify_cont, plugin_op_wrap);
1464 return plugin_op_wrap;
1465 }
1466
1467 /* load config */
1468 if (GNUNET_OK != load_keyshare_config (plugin_op_wrap))
1469 return plugin_op_wrap;
1470
1471 restore_private_key (plugin_op_wrap,
1472 escrowAnchor,
1473 &verify_restored_pk,
1474 plugin_op_wrap);
1475
1476 return plugin_op_wrap;
1477}
1478
1479
1480void
1481ego_created (const struct GNUNET_IDENTITY_Ego *ego)
1482{
1483 struct ESCROW_PluginOperationWrapper *curr;
1484 struct ESCROW_GnsPluginOperation *curr_p_op;
1485 char *ego_pk_string, *curr_pk_string;
1486
1487 ego_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (&ego->pk);
1488
1489 for (curr = ph.plugin_op_head; NULL != curr; curr = curr->next)
1490 {
1491 curr_p_op = (struct ESCROW_GnsPluginOperation *)curr->plugin_op;
1492 curr_pk_string = GNUNET_CRYPTO_ecdsa_private_key_to_string (&curr_p_op->pk);
1493 // compare the strings of the private keys
1494 if (0 == strcmp (ego_pk_string, curr_pk_string))
1495 {
1496 // the ego was created due to a restore operation that is not yet finished
1497 curr_p_op->ego_wrap->ego = ego;
1498 curr_p_op->cont (curr_p_op->ego_wrap);
1499
1500 cleanup_plugin_operation (curr);
1501
1502 GNUNET_free (curr_pk_string);
1503 GNUNET_free (ego_pk_string);
1504 return;
1505 }
1506 GNUNET_free (curr_pk_string);
1507 }
1508 GNUNET_free (ego_pk_string);
1509}
1510
1511
1512static void
1513id_create_finished (void *cls,
1514 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
1515 const char *emsg)
1516{
1517 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1518 struct ESCROW_GnsPluginOperation *p_op;
1519
1520 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1521
1522 if (NULL == pk)
1523 {
1524 if (NULL != emsg)
1525 {
1526 fprintf (stderr,
1527 "Identity create operation returned with error: %s\n",
1528 emsg);
1529 p_op->ego_wrap->emsg = _ ("Identity create failed!\n");
1530 }
1531 else
1532 p_op->ego_wrap->emsg = _ ("Failed to create ego!\n");
1533 p_op->ego_wrap->ego = NULL;
1534 p_op->cont (p_op->ego_wrap);
1535 return;
1536 }
1537
1538 /* no error occurred, p_op->restore_cont will be called in ego_created, which
1539 is called from ESCROW_list_ego after adding the new ego to our list */
1540 p_op->pk = *pk;
1541}
1542
1543
1544static void
1545restore_ego_from_pk (void *cls,
1546 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
1547{
1548 struct ESCROW_PluginOperationWrapper *plugin_op_wrap = cls;
1549 struct ESCROW_GnsPluginOperation *p_op;
1550
1551 p_op = (struct ESCROW_GnsPluginOperation*)plugin_op_wrap->plugin_op;
1552
1553 if (NULL == pk)
1554 {
1555 p_op->ego_wrap->ego = NULL;
1556 handle_restore_error (plugin_op_wrap);
1557 return;
1558 }
1559
1560 p_op->id_op = GNUNET_IDENTITY_create (identity_handle,
1561 p_op->egoName,
1562 pk,
1563 &id_create_finished,
1564 plugin_op_wrap);
1565}
1566
1567
1568/**
1569 * Restore the key from GNS escrow
1570 *
1571 * @param h the handle for the escrow component
1572 * @param escrowAnchor the escrow anchor needed to restore the key
1573 * @param egoName the name of the ego to restore
1574 * @param cb the function called upon completion
1575 * @param op_id unique ID of the respective ESCROW_Operation
1576 *
1577 * @return plugin operation wrapper
1578 */
1579struct ESCROW_PluginOperationWrapper *
1580restore_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
1581 struct GNUNET_ESCROW_Anchor *escrowAnchor,
1582 const char *egoName,
1583 GNUNET_SCHEDULER_TaskCallback cb,
1584 uint32_t op_id)
1585{
1586 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
1587 struct ESCROW_GnsPluginOperation *p_op;
1588 struct ESCROW_Plugin_EgoContinuationWrapper *w;
1589
1590 // create a new GNS plugin operation (in a wrapper) and insert it into the DLL
1591 plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
1592 plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
1593 GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
1594 ph.plugin_op_tail,
1595 plugin_op_wrap);
1596
1597 p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
1598 p_op->h = h;
1599 // set cont here (has to be scheduled from the IDENTITY service when it finished)
1600 p_op->cont = cb;
1601 p_op->egoName = GNUNET_strdup (egoName);
1602 p_op->userSecret = gns_anchor_data_to_string (h, escrowAnchor);
1603
1604 w = GNUNET_new (struct ESCROW_Plugin_EgoContinuationWrapper);
1605 w->h = h;
1606 w->op_id = op_id;
1607 p_op->ego_wrap = w;
1608
1609 if (NULL == escrowAnchor)
1610 {
1611 w->ego = NULL;
1612 w->emsg = _ ("ESCROW_get was called with escrowAnchor == NULL!\n");
1613 // schedule handle_restore_error, which calls the callback and cleans up
1614 p_op->sched_task = GNUNET_SCHEDULER_add_now (&handle_restore_error, plugin_op_wrap);
1615 return plugin_op_wrap;
1616 }
1617
1618 /* load config */
1619 if (GNUNET_OK != load_keyshare_config (plugin_op_wrap))
1620 return plugin_op_wrap;
1621
1622 restore_private_key (plugin_op_wrap,
1623 escrowAnchor,
1624 &restore_ego_from_pk,
1625 plugin_op_wrap);
1626
1627 return plugin_op_wrap;
1628}
1629
1630
1631/**
1632 * Get the status of a GNS escrow
1633 *
1634 * @param h the handle for the escrow component
1635 * @param ego the identity ego of which the status has to be obtained
1636 *
1637 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
1638 */
1639struct GNUNET_ESCROW_Status *
1640gns_get_status (struct GNUNET_ESCROW_Handle *h,
1641 struct GNUNET_IDENTITY_Ego *ego)
1642{
1643 return ESCROW_get_escrow_status (h, ego);
1644}
1645
1646
1647/**
1648 * Deserialize an escrow anchor string into a GNUNET_ESCROW_Anchor struct
1649 *
1650 * @param anchorString the encoded escrow anchor string
1651 *
1652 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
1653 */
1654struct GNUNET_ESCROW_Anchor *
1655gns_anchor_string_to_data (struct GNUNET_ESCROW_Handle *h,
1656 char *anchorString)
1657{
1658 struct GNUNET_ESCROW_Anchor *anchor;
1659 uint32_t data_size;
1660
1661 data_size = strlen (anchorString) + 1;
1662
1663 anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + data_size);
1664 anchor->size = data_size;
1665 // TODO: deserialize?
1666 GNUNET_memcpy (&anchor[1], anchorString, data_size);
1667
1668 return anchor;
1669}
1670
1671
1672/**
1673 * Serialize an escrow anchor struct into a string
1674 *
1675 * @param h the handle for the escrow component
1676 * @param escrowAnchor the escrow anchor struct
1677 *
1678 * @return the encoded escrow anchor string
1679 */
1680char *
1681gns_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
1682 struct GNUNET_ESCROW_Anchor *escrowAnchor)
1683{
1684 char *anchorString;
1685
1686 anchorString = GNUNET_malloc (escrowAnchor->size);
1687 GNUNET_memcpy (anchorString, &escrowAnchor[1], escrowAnchor->size);
1688
1689 return anchorString;
1690}
1691
1692
1693/**
1694 * Cancel a GNS plugin operation.
1695 *
1696 * @param plugin_op_wrap the plugin operation wrapper containing the operation
1697 */
1698void
1699cancel_gns_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
1700{
1701 struct ESCROW_PluginOperationWrapper *curr;
1702
1703 for (curr = ph.plugin_op_head; NULL != curr; curr = curr->next)
1704 {
1705 if (curr == plugin_op_wrap)
1706 {
1707 GNUNET_CONTAINER_DLL_remove (ph.plugin_op_head,
1708 ph.plugin_op_tail,
1709 curr);
1710 cleanup_plugin_operation (curr);
1711 return;
1712 }
1713 }
1714}
1715
1716
1717/**
1718 * IdentityInitContinuation for the GNS plugin
1719 */
1720void
1721gns_cont_init ()
1722{
1723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS plugin initialized\n");
1724}
1725
1726
1727/**
1728 * Entry point for the plugin.
1729 *
1730 * @param cls Config info
1731 *
1732 * @return the exported block API
1733 */
1734void *
1735libgnunet_plugin_escrow_gns_init (void *cls)
1736{
1737 struct GNUNET_ESCROW_KeyPluginFunctions *api;
1738 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1739
1740 api = GNUNET_new (struct GNUNET_ESCROW_KeyPluginFunctions);
1741 api->start_key_escrow = &start_gns_key_escrow;
1742 api->verify_key_escrow = &verify_gns_key_escrow;
1743 api->restore_key = &restore_gns_key_escrow;
1744 api->get_status = &gns_get_status;
1745 api->anchor_string_to_data = &gns_anchor_string_to_data;
1746 api->anchor_data_to_string = &gns_anchor_data_to_string;
1747 api->cancel_plugin_operation = &cancel_gns_operation;
1748
1749 ph.state = ESCROW_PLUGIN_STATE_INIT;
1750 ph.id_init_cont = &gns_cont_init;
1751
1752 ph.ego_create_cont = &ego_created;
1753 identity_handle = GNUNET_IDENTITY_connect (cfg,
1754 &ESCROW_list_ego,
1755 &ph);
1756
1757 return api;
1758}
1759
1760
1761/**
1762 * Exit point from the plugin.
1763 *
1764 * @param cls the return value from #libgnunet_plugin_block_test_init()
1765 *
1766 * @return NULL
1767 */
1768void *
1769libgnunet_plugin_escrow_gns_done (void *cls)
1770{
1771 struct GNUNET_RECLAIM_EscrowKeyPluginFunctions *api = cls;
1772
1773 GNUNET_free (api);
1774 GNUNET_IDENTITY_disconnect (identity_handle);
1775 ESCROW_cleanup_ego_list (&ph);
1776
1777 return NULL;
1778}
1779
1780
1781/* 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..0dab8fd1e
--- /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 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..b29650718
--- /dev/null
+++ b/src/escrow/test_gns_escrow.sh
@@ -0,0 +1,48 @@
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 -u secret -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}')
29 echo "using anchor $ANCHOR"
30fi
31gnunet-escrow -m gns -V testego -a $ANCHOR -c test_escrow.conf
32if test $? != 0
33then
34 echo "GNS verification failed!"
35 gnunet-arm -e -c test_escrow.conf
36 exit 1
37fi
38gnunet-identity -D testego -c test_escrow.conf
39gnunet-escrow -m gns -G testego -a $ANCHOR -c test_escrow.conf
40if test $? != 0
41then
42 echo "GNS restore failed!"
43 gnunet-arm -e -c test_escrow.conf
44 exit 1
45fi
46gnunet-arm -e -c test_escrow.conf
47
48exit 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 8c3f4f058..efd696b36 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -1198,6 +1198,21 @@ GNUNET_CRYPTO_eddsa_public_key_to_string (
1198 1198
1199 1199
1200/** 1200/**
1201 * Convert a string representing a private key to a private key.
1202 *
1203 * @param enc encoded private key
1204 * @param enclen number of bytes in @a enc (without 0-terminator)
1205 * @param priv where to store the private key
1206 * @return #GNUNET_OK on success
1207 */
1208int
1209GNUNET_CRYPTO_ecdsa_private_key_from_string (
1210 const char *enc,
1211 size_t enclen,
1212 struct GNUNET_CRYPTO_EcdsaPrivateKey *pub);
1213
1214
1215/**
1201 * Convert a string representing a public key to a public key. 1216 * Convert a string representing a public key to a public key.
1202 * 1217 *
1203 * @param enc encoded public key 1218 * @param enc encoded public key
@@ -1215,7 +1230,7 @@ GNUNET_CRYPTO_ecdsa_public_key_from_string (
1215/** 1230/**
1216 * Convert a string representing a private key to a private key. 1231 * Convert a string representing a private key to a private key.
1217 * 1232 *
1218 * @param enc encoded public key 1233 * @param enc encoded private key
1219 * @param enclen number of bytes in @a enc (without 0-terminator) 1234 * @param enclen number of bytes in @a enc (without 0-terminator)
1220 * @param priv where to store the private key 1235 * @param priv where to store the private key
1221 * @return #GNUNET_OK on success 1236 * @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..7d9d39dce
--- /dev/null
+++ b/src/include/gnunet_escrow_lib.h
@@ -0,0 +1,421 @@
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 GNUNET_ESCROW_SHARES_MISSING
64};
65
66
67/**
68 * Struct for the escrow anchor
69 */
70struct GNUNET_ESCROW_Anchor
71{
72 /**
73 * The escrow method.
74 */
75 enum GNUNET_ESCROW_Key_Escrow_Method method;
76
77 /**
78 * The size of the anchor data.
79 */
80 uint32_t size;
81};
82
83
84/**
85 * Struct for the escrow status
86 */
87struct GNUNET_ESCROW_Status
88{
89 /**
90 * The time of the last successful escrow.
91 */
92 struct GNUNET_TIME_Absolute last_escrow_time;
93
94 /**
95 * The time of the next recommended escrow.
96 */
97 struct GNUNET_TIME_Absolute next_recommended_escrow_time;
98
99 /**
100 * The used escrow method.
101 */
102 enum GNUNET_ESCROW_Key_Escrow_Method last_method;
103};
104
105
106/**
107 * Function called after the initialization of the identity service.
108 * Passed via cls to the callback of GNUNET_IDENTITY_connect
109 */
110typedef void (*GNUNET_ESCROW_IdentityInitContinuation) ();
111
112/**
113 * Function called after the creation of an ego in case that happened
114 * because of an escrow GET operation.
115 */
116typedef void (*GNUNET_ESCROW_EgoCreateContinuation) (
117 const struct GNUNET_IDENTITY_Ego *ego);
118
119/**
120 * Continuation for PUT operations.
121 *
122 * @param cls closure
123 * @param escrowAnchor the escrow anchor needed to get the data back
124 * @param emsg error message, NULL on success
125 */
126typedef void (*GNUNET_ESCROW_AnchorContinuation) (
127 void *cls,
128 struct GNUNET_ESCROW_Anchor *escrowAnchor,
129 const char *emsg);
130
131/**
132 * Continuation for a GET operation.
133 *
134 * @param cls closure
135 * @param ego a new identity ego restored from the escrow
136 * @param emsg error message, NULL on success
137 */
138typedef void (*GNUNET_ESCROW_EgoContinuation) (
139 void *cls,
140 const struct GNUNET_IDENTITY_Ego *ego,
141 const char *emsg);
142
143/**
144 * Continuation for a VERIFY operation.
145 *
146 * @param cls closure
147 * @param verificationResult the result of the verification, i.e.
148 * GNUNET_ESCROW_VALID if the escrow could successfully by restored,
149 * GNUNET_ESCROW_SHARES_MISSING if it could be restored, but some of
150 * the shares are missing
151 * GNUNET_ESCROW_INVALID otherwise
152 * @param emsg error message, NULL on success
153 */
154typedef void (*GNUNET_ESCROW_VerifyContinuation) (
155 void *cls,
156 int verificationResult,
157 const char *emsg);
158
159
160/**
161 * Handle for the escrow component.
162 */
163struct GNUNET_ESCROW_Handle
164{
165 /**
166 * Configuration to use.
167 */
168 struct GNUNET_CONFIGURATION_Handle *cfg;
169
170 /**
171 * Head of active operations.
172 */
173 struct GNUNET_ESCROW_Operation *op_head;
174
175 /**
176 * Tail of active operations.
177 */
178 struct GNUNET_ESCROW_Operation *op_tail;
179
180 /**
181 * The last operation id used for an ESCROW operation.
182 */
183 uint32_t last_op_id_used;
184};
185
186
187/**
188 * Handle for an operation with the escrow component.
189 */
190struct GNUNET_ESCROW_Operation
191{
192 /**
193 * Main escrow handle.
194 */
195 struct GNUNET_ESCROW_Handle *h;
196
197 /**
198 * ID of the operation.
199 */
200 uint32_t id;
201
202 /**
203 * We keep operations in a DLL.
204 */
205 struct GNUNET_ESCROW_Operation *next;
206
207 /**
208 * We keep operations in a DLL.
209 */
210 struct GNUNET_ESCROW_Operation *prev;
211
212 /**
213 * The used escrow method.
214 */
215 enum GNUNET_ESCROW_Key_Escrow_Method method;
216
217 /**
218 * The respective plugin operation
219 */
220 struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
221
222 /**
223 * The escrow anchor.
224 */
225 struct GNUNET_ESCROW_Anchor *escrow_anchor;
226
227 /**
228 * The ego.
229 */
230 const struct GNUNET_IDENTITY_Ego *ego;
231
232 /**
233 * The verification result.
234 */
235 enum GNUNET_ESCROW_Verification_Result verification_result;
236
237 /**
238 * Continuation for a PUT operation.
239 */
240 GNUNET_ESCROW_AnchorContinuation cb_put;
241
242 /**
243 * Continuation for a GET operation.
244 */
245 GNUNET_ESCROW_EgoContinuation cb_get;
246
247 /**
248 * Continuation for a VERIFY operation.
249 */
250 GNUNET_ESCROW_VerifyContinuation cb_verify;
251
252 /**
253 * Closure for the callback
254 */
255 void *cb_cls;
256};
257
258
259/**
260 * Initialize the escrow component.
261 *
262 * @param cfg the configuration to use
263 *
264 * @return handle to use
265 */
266struct GNUNET_ESCROW_Handle *
267GNUNET_ESCROW_init (
268 const struct GNUNET_CONFIGURATION_Handle *cfg);
269
270
271/**
272 * Unload all loaded plugins on destruction.
273 *
274 * @param h the escrow handle
275 */
276void
277GNUNET_ESCROW_fini (
278 struct GNUNET_ESCROW_Handle *h);
279
280
281/**
282 * Put some data in escrow using the specified escrow method
283 *
284 * @param h the handle for the escrow component
285 * @param ego the identity ego to put in escrow
286 * @param userSecret the user secret (e.g. for derivation of escrow identities)
287 * for GNS escrow, this has to be UNIQUE in the whole network!
288 * @param method the escrow method to use
289 * @param cb function to call with the escrow anchor on completion
290 * @param cb_cls closure for @a cb
291 *
292 * @return handle to abort the operation
293 */
294struct GNUNET_ESCROW_Operation *
295GNUNET_ESCROW_put (
296 struct GNUNET_ESCROW_Handle *h,
297 struct GNUNET_IDENTITY_Ego *ego,
298 const char *userSecret,
299 enum GNUNET_ESCROW_Key_Escrow_Method method,
300 GNUNET_ESCROW_AnchorContinuation cb,
301 void *cb_cls);
302
303
304/**
305 * Get the escrowed data back
306 *
307 * @param h the handle for the escrow component
308 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
309 * @param egoName the name of the ego to get back
310 * @param method the escrow method to use
311 * @param cb function to call with the restored ego on completion
312 * @param cb_cls closure for @a cb
313 *
314 * @return handle to abort the operation
315 */
316struct GNUNET_ESCROW_Operation *
317GNUNET_ESCROW_get (
318 struct GNUNET_ESCROW_Handle *h,
319 struct GNUNET_ESCROW_Anchor *escrowAnchor,
320 const char *egoName,
321 enum GNUNET_ESCROW_Key_Escrow_Method method,
322 GNUNET_ESCROW_EgoContinuation cb,
323 void *cb_cls);
324
325
326/**
327 * Verify the escrowed data
328 *
329 * @param h the handle for the escrow component
330 * @param ego the identity ego that was put into escrow
331 * @param escrowAnchor the escrow anchor returned by the GNUNET_ESCROW_put method
332 * @param method the escrow method to use
333 * @param cb function to call with the verification result on completion
334 * @param cb_cls closure for @a cb
335 *
336 * @return handle to abort the operation
337 */
338struct GNUNET_ESCROW_Operation *
339GNUNET_ESCROW_verify (
340 struct GNUNET_ESCROW_Handle *h,
341 struct GNUNET_IDENTITY_Ego *ego,
342 struct GNUNET_ESCROW_Anchor *escrowAnchor,
343 enum GNUNET_ESCROW_Key_Escrow_Method method,
344 GNUNET_ESCROW_VerifyContinuation cb,
345 void *cb_cls);
346
347
348/**
349 * Get the status of an escrow, i.e.
350 * -> when the last escrow was
351 * -> when the next escrow is recommended
352 *
353 * @param h the handle for the escrow component
354 * @param ego the identity ego of which the escrow status has to be determined
355 * @param method the escrow method to use
356 *
357 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
358 */
359struct GNUNET_ESCROW_Status *
360GNUNET_ESCROW_get_status (
361 struct GNUNET_ESCROW_Handle *h,
362 struct GNUNET_IDENTITY_Ego *ego,
363 enum GNUNET_ESCROW_Key_Escrow_Method method);
364
365
366/**
367 * Deserialize an escrow anchor string (e.g. from command line) into a
368 * GNUNET_ESCROW_Anchor struct
369 *
370 * @param h the handle for the escrow component
371 * @param anchorString the encoded escrow anchor string
372 * @param method the escrow method to use
373 *
374 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
375 */
376struct GNUNET_ESCROW_Anchor *
377GNUNET_ESCROW_anchor_string_to_data (
378 struct GNUNET_ESCROW_Handle *h,
379 char *anchorString,
380 enum GNUNET_ESCROW_Key_Escrow_Method method);
381
382
383/**
384 * Serialize an escrow anchor (struct GNUNET_ESCROW_Anchor) into a string
385 *
386 * @param h the handle for the escrow component
387 * @param escrowAnchor the escrow anchor struct
388 * @param method the escrow method to use
389 *
390 * @return the encoded escrow anchor string
391 */
392char *
393GNUNET_ESCROW_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
394 struct GNUNET_ESCROW_Anchor *escrowAnchor,
395 enum GNUNET_ESCROW_Key_Escrow_Method method);
396
397
398/**
399 * Cancel an escrow operation. Note that the operation MAY still
400 * be executed; this merely cancels the continuation.
401 *
402 * @param op operation to cancel
403 */
404void
405GNUNET_ESCROW_cancel (struct GNUNET_ESCROW_Operation *op);
406
407
408#if 0 /* keep Emacsens' auto-indent happy */
409{
410#endif
411#ifdef __cplusplus
412}
413#endif
414
415
416/* ifndef GNUNET_ESCROW_LIB_H */
417#endif
418
419/** @} */ /* end of group escrow */
420
421/* 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..b54506970
--- /dev/null
+++ b/src/include/gnunet_escrow_plugin.h
@@ -0,0 +1,211 @@
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 * for GNS escrow, this has to be UNIQUE in the whole network!
54 * @param cb the function called upon completion
55 * @param op_id unique ID of the respective ESCROW_Operation
56 *
57 * @return a wrapper for the plugin operation
58 */
59typedef struct ESCROW_PluginOperationWrapper *(*GNUNET_ESCROW_StartKeyEscrowFunction) (
60 struct GNUNET_ESCROW_Handle *h,
61 struct GNUNET_IDENTITY_Ego *ego,
62 const char *userSecret,
63 GNUNET_SCHEDULER_TaskCallback cb,
64 uint32_t op_id);
65
66/**
67 * Function called to verify the escrow of the key
68 *
69 * @param h the handle for the escrow component
70 * @param ego the identity ego containing the private key
71 * @param escrowAnchor the escrow anchor needed to restore the key
72 * @param cb the function called upon completion
73 * @param op_id unique ID of the respective ESCROW_Operation
74 *
75 * @return a wrapper for the plugin operation
76 */
77typedef struct ESCROW_PluginOperationWrapper *(*GNUNET_ESCROW_VerifyKeyEscrowFunction) (
78 struct GNUNET_ESCROW_Handle *h,
79 struct GNUNET_IDENTITY_Ego *ego,
80 struct GNUNET_ESCROW_Anchor *escrowAnchor,
81 GNUNET_SCHEDULER_TaskCallback cb,
82 uint32_t op_id);
83
84/**
85 * Function called to restore a key from an escrow
86 *
87 * @param h the handle for the escrow component
88 * @param escrowAnchor the escrow anchor needed to restore the key
89 * @param egoName the name of the ego to restore
90 * @param cb the function called upon completion
91 * @param op_id unique ID of the respective ESCROW_Operation
92 *
93 * @return a wrapper for the plugin operation
94 */
95typedef struct ESCROW_PluginOperationWrapper *(*GNUNET_ESCROW_RestoreKeyFunction) (
96 struct GNUNET_ESCROW_Handle *h,
97 struct GNUNET_ESCROW_Anchor *escrowAnchor,
98 const char *egoName,
99 GNUNET_SCHEDULER_TaskCallback cb,
100 uint32_t op_id);
101
102
103/**
104 * Function called to get the status of an escrow, i.e.
105 * -> when the last successful escrow was
106 * -> when the next recommended escrow is
107 *
108 * @param h the handle for the escrow component
109 * @param ego the identity ego of which the status has to be obtained
110 *
111 * @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
112 */
113typedef struct GNUNET_ESCROW_Status *(*GNUNET_ESCROW_GetEscrowStatusFunction) (
114 struct GNUNET_ESCROW_Handle *h,
115 struct GNUNET_IDENTITY_Ego *ego);
116
117
118/**
119 * Function called to deserialize an escrow anchor string into a
120 * GNUNET_ESCROW_Anchor struct
121 *
122 * @param h the handle for the escrow component
123 * @param anchorString the encoded escrow anchor string
124 *
125 * @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
126 */
127typedef struct GNUNET_ESCROW_Anchor *(*GNUNET_ESCROW_AnchorStringToDataFunction) (
128 struct GNUNET_ESCROW_Handle *h,
129 char *anchorString);
130
131
132/**
133 * Function called to serialize an escrow anchor struct into a string
134 *
135 * @param h the handle for the escrow component
136 * @param escrowAnchor the escrow anchor struct
137 *
138 * @return the encoded escrow anchor string
139 */
140typedef char *(*GNUNET_ESCROW_AnchorDataToStringFunction) (
141 struct GNUNET_ESCROW_Handle *h,
142 struct GNUNET_ESCROW_Anchor *escrowAnchor);
143
144
145/**
146 * Function called to cancel a plugin operation
147 *
148 * @param plugin_op_wrap plugin operation wrapper containing the plugin operation
149 */
150typedef void (*GNUNET_ESCROW_CancelPluginOperationFunction) (
151 struct ESCROW_PluginOperationWrapper *plugin_op_wrap);
152
153
154/**
155 * Each plugin is required to return a pointer to a struct of this
156 * type as the return value from its entry point.
157 */
158struct GNUNET_ESCROW_KeyPluginFunctions
159{
160 /**
161 * Closure for all of the callbacks.
162 */
163 void *cls;
164
165 /**
166 * Start key escrow
167 */
168 GNUNET_ESCROW_StartKeyEscrowFunction start_key_escrow;
169
170 /**
171 * Verify key escrow
172 */
173 GNUNET_ESCROW_VerifyKeyEscrowFunction verify_key_escrow;
174
175 /**
176 * Restore key escrow
177 */
178 GNUNET_ESCROW_RestoreKeyFunction restore_key;
179
180 /**
181 * Get the status of an escrow
182 */
183 GNUNET_ESCROW_GetEscrowStatusFunction get_status;
184
185 /**
186 * Deserialize anchor string to data
187 */
188 GNUNET_ESCROW_AnchorStringToDataFunction anchor_string_to_data;
189
190 /**
191 * Serialize anchor data to string
192 */
193 GNUNET_ESCROW_AnchorDataToStringFunction anchor_data_to_string;
194
195 /**
196 * Cancel plugin operation
197 */
198 GNUNET_ESCROW_CancelPluginOperationFunction cancel_plugin_operation;
199};
200
201
202#if 0 /* keep Emacsens' auto-indent happy */
203{
204#endif
205#ifdef __cplusplus
206}
207#endif
208
209#endif
210
211/** @} */ /* end of group */
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index 960203fb1..db524ec5b 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -151,6 +151,11 @@ extern "C" {
151 */ 151 */
152#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555 152#define GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION 65555
153 153
154/**
155 * Record type for an escrow key share (escrow component)
156 */
157#define GNUNET_GNSRECORD_TYPE_ESCROW_KEYSHARE 65556
158
154 159
155/** 160/**
156 * Flags that can be set for a record. 161 * 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 2ba8fc8a0..ed6663bb5 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