aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/pabc_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/pabc_helper.c')
-rw-r--r--src/reclaim/pabc_helper.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/src/reclaim/pabc_helper.c b/src/reclaim/pabc_helper.c
new file mode 100644
index 000000000..1b1dbea0f
--- /dev/null
+++ b/src/reclaim/pabc_helper.c
@@ -0,0 +1,364 @@
1// maximilian.kaul@aisec.fraunhofer.de
2
3// WIP implementation of
4// https://github.com/ontio/ontology-crypto/wiki/Anonymous-Credential
5// using the relic library https://github.com/relic-toolkit/relic/
6
7#include "pabc_helper.h"
8#include <pwd.h>
9#include <stdlib.h>
10#include <unistd.h>
11
12static char pabc_dir[PATH_MAX + 1];
13
14static const char *
15get_homedir ()
16{
17 const char *homedir;
18 if ((homedir = getenv ("HOME")) == NULL)
19 {
20 homedir = getpwuid (getuid ())->pw_dir;
21 }
22 return homedir;
23}
24
25
26static enum GNUNET_GenericReturnValue
27write_file (char const *const filename, const char *buffer)
28{
29 struct GNUNET_DISK_FileHandle *fh;
30 fh = GNUNET_DISK_file_open (filename,
31 GNUNET_DISK_OPEN_WRITE
32 | GNUNET_DISK_OPEN_TRUNCATE
33 | GNUNET_DISK_OPEN_CREATE,
34 GNUNET_DISK_PERM_USER_WRITE
35 | GNUNET_DISK_PERM_USER_READ);
36 if (fh == NULL)
37 return GNUNET_SYSERR;
38 if (GNUNET_SYSERR == GNUNET_DISK_file_write (fh,
39 buffer, strlen (buffer) + 1))
40 goto fail;
41 GNUNET_DISK_file_close (fh);
42 return GNUNET_OK;
43
44fail:
45 GNUNET_DISK_file_close (fh);
46 return GNUNET_SYSERR;
47}
48
49
50static enum GNUNET_GenericReturnValue
51init_pabc_dir ()
52{
53 size_t filename_size = strlen (get_homedir ()) + 1 + strlen (".local") + 1
54 + strlen ("pabc-reclaim") + 1;
55 snprintf (pabc_dir, filename_size, "%s/%s/%s",
56 get_homedir (), ".local", "pabc-reclaim");
57 return GNUNET_DISK_directory_create (pabc_dir);
58}
59
60
61static const char *
62get_pabcdir ()
63{
64 init_pabc_dir ();
65 return pabc_dir;
66}
67
68
69enum GNUNET_GenericReturnValue
70read_file (char const *const filename, char **buffer)
71{
72 struct GNUNET_DISK_FileHandle *fh;
73 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
74 return GNUNET_SYSERR;
75
76 fh = GNUNET_DISK_file_open (filename,
77 GNUNET_DISK_OPEN_READ,
78 GNUNET_DISK_PERM_USER_READ);
79 if (fh == NULL)
80 return GNUNET_SYSERR;
81 long lSize = GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_END);
82 if (lSize < 0)
83 goto fail;
84 GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET);
85 *buffer = calloc ((size_t) lSize + 1, sizeof(char));
86 if (*buffer == NULL)
87 goto fail;
88
89 // copy the file into the buffer:
90 size_t r = GNUNET_DISK_file_read (fh, *buffer, (size_t) lSize);
91 if (r != (size_t) lSize)
92 goto fail;
93
94 GNUNET_DISK_file_close (fh);
95 return GNUNET_OK;
96
97fail:
98 GNUNET_DISK_file_close (fh);
99 return GNUNET_SYSERR;
100}
101
102
103struct pabc_public_parameters *
104PABC_read_issuer_ppfile (const char *f, struct pabc_context *const ctx)
105{
106 if (NULL == ctx)
107 {
108 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No global context provided\n");
109 return NULL;
110 }
111 struct pabc_public_parameters *pp;
112 char *buffer;
113 int r;
114 r = read_file (f, &buffer);
115 if (GNUNET_OK != r)
116 {
117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading file\n");
118 return NULL;
119 }
120 if (PABC_OK != pabc_decode_and_new_public_parameters (ctx, &pp, buffer))
121 {
122 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
123 "Failed to decode public parameters\n");
124 PABC_FREE_NULL (buffer);
125 return NULL;
126 }
127 PABC_FREE_NULL (buffer);
128 return pp;
129}
130
131
132enum GNUNET_GenericReturnValue
133PABC_load_public_parameters (struct pabc_context *const ctx,
134 char const *const pp_name,
135 struct pabc_public_parameters **pp)
136{
137 char fname[PATH_MAX];
138 char *pp_filename;
139 const char *pdir = get_pabcdir ();
140
141 if (ctx == NULL)
142 return GNUNET_SYSERR;
143 if (pp_name == NULL)
144 return GNUNET_SYSERR;
145
146 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
147 if (GNUNET_YES != GNUNET_DISK_directory_test (pdir, GNUNET_YES))
148 {
149 GNUNET_free (pp_filename);
150 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading %s\n", pdir);
151 return GNUNET_SYSERR;
152 }
153 snprintf (fname, PATH_MAX, "%s/%s%s", pdir, pp_filename, PABC_PP_EXT);
154 if (GNUNET_YES != GNUNET_DISK_file_test (fname))
155 {
156 GNUNET_free (pp_filename);
157 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error testing %s\n", fname);
158 return GNUNET_SYSERR;
159 }
160 *pp = PABC_read_issuer_ppfile (fname, ctx);
161 if (*pp)
162 return GNUNET_OK;
163 else
164 return GNUNET_SYSERR;
165}
166
167
168enum GNUNET_GenericReturnValue
169PABC_write_public_parameters (char const *const pp_name,
170 struct pabc_public_parameters *const pp)
171{
172 char *json;
173 char *filename;
174 char *pp_filename;
175 enum pabc_status status;
176 struct pabc_context *ctx = NULL;
177
178 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
179 PABC_ASSERT (pabc_new_ctx (&ctx));
180 // store in json file
181 status = pabc_encode_public_parameters (ctx, pp, &json);
182 if (status != PABC_OK)
183 {
184 GNUNET_free (pp_filename);
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 "Failed to encode public parameters.\n");
187 pabc_free_ctx (&ctx);
188 return GNUNET_SYSERR;
189 }
190
191 size_t filename_size =
192 strlen (get_pabcdir ()) + 1 + strlen (pp_filename) + strlen (PABC_PP_EXT)
193 + 1;
194 filename = GNUNET_malloc (filename_size);
195 if (! filename)
196 {
197 GNUNET_free (pp_filename);
198 PABC_FREE_NULL (json);
199 pabc_free_ctx (&ctx);
200 return GNUNET_SYSERR;
201 }
202 snprintf (filename, filename_size, "%s/%s%s", get_pabcdir (), pp_filename,
203 PABC_PP_EXT);
204
205 GNUNET_free (pp_filename);
206 if (GNUNET_OK != write_file (filename, json))
207 {
208 PABC_FREE_NULL (filename);
209 PABC_FREE_NULL (json);
210 pabc_free_ctx (&ctx);
211 return GNUNET_SYSERR;
212 }
213 PABC_FREE_NULL (filename);
214 PABC_FREE_NULL (json);
215 pabc_free_ctx (&ctx);
216 return GNUNET_OK;
217}
218
219
220enum GNUNET_GenericReturnValue
221PABC_write_usr_ctx (char const *const usr_name,
222 char const *const pp_name,
223 struct pabc_context const *const ctx,
224 struct pabc_public_parameters const *const pp,
225 struct pabc_user_context *const usr_ctx)
226{
227
228 char *pp_filename;
229 char *json = NULL;
230 enum pabc_status status;
231 char *fname = NULL;
232
233 if (NULL == usr_name)
234 {
235 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
236 return GNUNET_SYSERR;
237 }
238 if (NULL == pp_name)
239 {
240 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
241 return GNUNET_SYSERR;
242 }
243 if (NULL == ctx)
244 {
245 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
246 return GNUNET_SYSERR;
247 }
248 if (NULL == pp)
249 {
250 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
251 return GNUNET_SYSERR;
252 }
253 if (NULL == usr_ctx)
254 {
255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
256 return GNUNET_SYSERR;
257 }
258
259 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
260 status = pabc_encode_user_ctx (ctx, pp, usr_ctx, &json);
261 if (PABC_OK != status)
262 {
263 GNUNET_free (pp_filename);
264 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
265 return status;
266 }
267
268 size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
269 + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
270 fname = GNUNET_malloc (fname_size);
271
272 snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
273 pp_filename,
274 PABC_USR_EXT);
275
276 GNUNET_free (pp_filename);
277 if (GNUNET_OK == write_file (fname, json))
278 {
279 GNUNET_free (fname);
280 GNUNET_free (json);
281 return GNUNET_OK;
282 }
283 else
284 {
285 GNUNET_free (fname);
286 GNUNET_free (json);
287 return GNUNET_SYSERR;
288 }
289}
290
291
292enum GNUNET_GenericReturnValue
293PABC_read_usr_ctx (char const *const usr_name,
294 char const *const pp_name,
295 struct pabc_context const *const ctx,
296 struct pabc_public_parameters const *const pp,
297 struct pabc_user_context **usr_ctx)
298{
299 char *json = NULL;
300 char *pp_filename;
301 enum pabc_status status;
302
303 char *fname = NULL;
304
305 if (NULL == usr_name)
306 {
307 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
308 return GNUNET_SYSERR;
309 }
310 if (NULL == pp_name)
311 {
312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
313 return GNUNET_SYSERR;
314 }
315 if (NULL == ctx)
316 {
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
318 return GNUNET_SYSERR;
319 }
320 if (NULL == pp)
321 {
322 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
323 return GNUNET_SYSERR;
324 }
325 if (NULL == usr_ctx)
326 {
327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
328 return GNUNET_SYSERR;
329 }
330 GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
331
332 size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
333 + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
334 fname = GNUNET_malloc (fname_size);
335 snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
336 pp_filename,
337 PABC_USR_EXT);
338 GNUNET_free (pp_filename);
339 if (GNUNET_OK != read_file (fname, &json))
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
342 "Failed to read `%s'\n", fname);
343 PABC_FREE_NULL (fname);
344 return GNUNET_SYSERR;
345 }
346 GNUNET_free (fname);
347
348 status = pabc_new_user_context (ctx, pp, usr_ctx);
349 if (PABC_OK != status)
350 {
351 GNUNET_free (json);
352 return GNUNET_SYSERR;
353 }
354 status = pabc_decode_user_ctx (ctx, pp, *usr_ctx, json);
355 GNUNET_free (json);
356 if (PABC_OK != status)
357 {
358 pabc_free_user_context (ctx, pp, usr_ctx);
359 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
360 return GNUNET_SYSERR;
361 }
362
363 return GNUNET_OK;
364}