aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/plugin_reclaim_credential_pabc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/plugin_reclaim_credential_pabc.c')
-rw-r--r--src/reclaim/plugin_reclaim_credential_pabc.c639
1 files changed, 639 insertions, 0 deletions
diff --git a/src/reclaim/plugin_reclaim_credential_pabc.c b/src/reclaim/plugin_reclaim_credential_pabc.c
new file mode 100644
index 000000000..2f6b7b8c4
--- /dev/null
+++ b/src/reclaim/plugin_reclaim_credential_pabc.c
@@ -0,0 +1,639 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014, 2016 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file reclaim/plugin_reclaim_credential_pabc.c
23 * @brief reclaim-credential-plugin-pabc attribute plugin to provide the API for
24 * pabc credentials.
25 *
26 * @author Martin Schanzenbach
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_reclaim_plugin.h"
31#include <inttypes.h>
32#include <jansson.h>
33#include <pabc/pabc.h>
34#include "pabc_helper.h"
35
36/**
37 * Convert the 'value' of an credential to a string.
38 *
39 * @param cls closure, unused
40 * @param type type of the credential
41 * @param data value in binary encoding
42 * @param data_size number of bytes in @a data
43 * @return NULL on error, otherwise human-readable representation of the value
44 */
45static char *
46pabc_value_to_string (void *cls,
47 uint32_t type,
48 const void *data,
49 size_t data_size)
50{
51 switch (type)
52 {
53 case GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC:
54 return GNUNET_strndup (data, data_size);
55
56 default:
57 return NULL;
58 }
59}
60
61
62/**
63 * Convert human-readable version of a 'value' of an credential to the binary
64 * representation.
65 *
66 * @param cls closure, unused
67 * @param type type of the credential
68 * @param s human-readable string
69 * @param data set to value in binary encoding (will be allocated)
70 * @param data_size set to number of bytes in @a data
71 * @return #GNUNET_OK on success
72 */
73static int
74pabc_string_to_value (void *cls,
75 uint32_t type,
76 const char *s,
77 void **data,
78 size_t *data_size)
79{
80 if (NULL == s)
81 return GNUNET_SYSERR;
82 switch (type)
83 {
84 case GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC:
85 *data = GNUNET_strdup (s);
86 *data_size = strlen (s) + 1;
87 return GNUNET_OK;
88
89 default:
90 return GNUNET_SYSERR;
91 }
92}
93
94
95/**
96 * Mapping of credential type numbers to human-readable
97 * credential type names.
98 */
99static struct
100{
101 const char *name;
102 uint32_t number;
103} pabc_cred_name_map[] = { { "PABC", GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC },
104 { NULL, UINT32_MAX } };
105
106/**
107 * Convert a type name to the corresponding number.
108 *
109 * @param cls closure, unused
110 * @param pabc_typename name to convert
111 * @return corresponding number, UINT32_MAX on error
112 */
113static uint32_t
114pabc_typename_to_number (void *cls, const char *pabc_typename)
115{
116 unsigned int i;
117
118 i = 0;
119 while ((NULL != pabc_cred_name_map[i].name) &&
120 (0 != strcasecmp (pabc_typename, pabc_cred_name_map[i].name)))
121 i++;
122 return pabc_cred_name_map[i].number;
123}
124
125
126/**
127 * Convert a type number (i.e. 1) to the corresponding type string
128 *
129 * @param cls closure, unused
130 * @param type number of a type to convert
131 * @return corresponding typestring, NULL on error
132 */
133static const char *
134pabc_number_to_typename (void *cls, uint32_t type)
135{
136 unsigned int i;
137
138 i = 0;
139 while ((NULL != pabc_cred_name_map[i].name) && (type !=
140 pabc_cred_name_map[i].
141 number))
142 i++;
143 return pabc_cred_name_map[i].name;
144}
145
146
147static void
148inspect_attrs (char const *const key,
149 char const *const value,
150 void *ctx)
151{
152 struct GNUNET_RECLAIM_AttributeList *attrs = ctx;
153
154 if (NULL == value)
155 return;
156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
157 "Found attribue in PABC credential: `%s': `%s'\n",
158 key, value);
159 if (0 == strcmp (key, "expiration"))
160 return;
161 if (0 == strcmp (key, "issuer"))
162 return;
163 if (0 == strcmp (key, "subject"))
164 return;
165 GNUNET_RECLAIM_attribute_list_add (attrs,
166 key,
167 NULL,
168 GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING,
169 value,
170 strlen (value));
171}
172
173
174/**
175 * Parse a pabc and return the respective claim value as Attribute
176 *
177 * @param cls the plugin
178 * @param cred the pabc credential
179 * @return a GNUNET_RECLAIM_Attribute, containing the new value
180 */
181struct GNUNET_RECLAIM_AttributeList *
182pabc_parse_attributes (void *cls,
183 const char *data,
184 size_t data_size)
185{
186 struct GNUNET_RECLAIM_AttributeList *attrs;
187
188 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189 "Collecting PABC attributes...\n");
190 attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
191 GNUNET_assert (PABC_OK ==
192 pabc_cred_inspect_credential (data,
193 &inspect_attrs, attrs));
194 return attrs;
195}
196
197
198/**
199 * Parse a pabc and return the respective claim value as Attribute
200 *
201 * @param cls the plugin
202 * @param cred the pabc credential
203 * @return a GNUNET_RECLAIM_Attribute, containing the new value
204 */
205struct GNUNET_RECLAIM_AttributeList *
206pabc_parse_attributes_c (void *cls,
207 const struct GNUNET_RECLAIM_Credential *cred)
208{
209 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
210 return NULL;
211 return pabc_parse_attributes (cls, cred->data, cred->data_size);
212}
213
214
215/**
216 * Parse a pabc and return the respective claim value as Attribute
217 *
218 * @param cls the plugin
219 * @param cred the pabc credential
220 * @return a GNUNET_RECLAIM_Attribute, containing the new value
221 */
222struct GNUNET_RECLAIM_AttributeList *
223pabc_parse_attributes_p (void *cls,
224 const struct GNUNET_RECLAIM_Presentation *cred)
225{
226 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
227 return NULL;
228 return pabc_parse_attributes (cls, cred->data, cred->data_size);
229}
230
231struct Finder
232{
233 const char* target;
234 char *result;
235};
236
237static void
238find_attr (char const *const key,
239 char const *const value,
240 void *ctx)
241{
242 struct Finder *fdr = ctx;
243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
244 "Found `%s', looking for `%s'\n",
245 key, fdr->target);
246 if (0 == strcmp (key, fdr->target))
247 fdr->result = GNUNET_strdup (value);
248}
249
250
251
252/**
253 * Parse a pabc and return an attribute value.
254 *
255 * @param cls the plugin
256 * @param data the pabc credential data
257 * @param data_size the pabc credential size
258 * @param skey the attribute key to look for.
259 * @return a string, containing the isser
260 */
261char *
262pabc_get_attribute (void *cls,
263 const char *data,
264 size_t data_size,
265 const char *skey)
266{
267
268 struct Finder fdr;
269 memset (&fdr, 0, sizeof (fdr));
270 fdr.target = skey;
271 pabc_cred_inspect_credential (data, &find_attr, &fdr);
272 return fdr.result;
273}
274
275
276/**
277 * Parse a pabc and return the issuer
278 *
279 * @param cls the plugin
280 * @param cred the pabc credential
281 * @return a string, containing the isser
282 */
283char*
284pabc_get_issuer (void *cls,
285 const char *data,
286 size_t data_size)
287{
288 char *res;
289 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (data,
290 "issuer",
291 &res))
292 return NULL;
293 return res;
294}
295
296
297/**
298 * Parse a pabc and return the issuer
299 *
300 * @param cls the plugin
301 * @param cred the pabc credential
302 * @return a string, containing the isser
303 */
304char*
305pabc_get_issuer (void *cls,
306 const char *data,
307 size_t data_size)
308{
309 return pabc_get_attribute (cls, data, data_size, "issuer");
310}
311
312
313/**
314 * Parse a pabc and return the issuer
315 *
316 * @param cls the plugin
317 * @param cred the pabc credential
318 * @return a string, containing the isser
319 */
320char *
321pabc_get_issuer_c (void *cls,
322 const struct GNUNET_RECLAIM_Credential *cred)
323{
324 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type)
325 return NULL;
326 return pabc_get_issuer (cls, cred->data, cred->data_size);
327}
328
329
330/**
331 * Parse a pabc and return the issuer
332 *
333 * @param cls the plugin
334 * @param cred the pabc credential
335 * @return a string, containing the isser
336 */
337char *
338pabc_get_issuer_p (void *cls,
339 const struct GNUNET_RECLAIM_Presentation *cred)
340{
341 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != cred->type)
342 return NULL;
343 return pabc_get_issuer (cls, cred->data, cred->data_size);
344}
345
346
347/**
348 * Parse a pabc and return the expiration
349 *
350 * @param cls the plugin
351 * @param cred the pabc credential
352 * @return a string, containing the isser
353 */
354int
355pabc_get_expiration (void *cls,
356 const char *data,
357 size_t data_size,
358 struct GNUNET_TIME_Absolute *exp)
359{
360 json_t *json_root;
361 json_t *json_attrs;
362 json_t *value;
363 json_t *exp_j;
364 json_error_t *json_err = NULL;
365 const char*key;
366
367 json_root = json_loads (data, JSON_DECODE_ANY, json_err);
368 if ((NULL == json_root) ||
369 (! json_is_object (json_root)))
370 {
371 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
372 "Unable to retrive expiration from credential\n");
373 return GNUNET_SYSERR;
374 }
375
376 if (1 != sscanf (exp_str, "%llu", &exp_i))
377 {
378 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
379 "Invalid expiration `%s'\n", exp_str);
380 GNUNET_free (exp_str);
381 return GNUNET_SYSERR;
382 }
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "Converted expiration string `%s' to %llu",
385 exp_str, exp_i);
386
387 GNUNET_free (exp_str);
388 exp->abs_value_us = exp_i * 1000 * 1000;
389 return GNUNET_OK;
390}
391
392
393/**
394 * Parse a pabc and return the expiration
395 *
396 * @param cls the plugin
397 * @param cred the pabc credential
398 * @return a string, containing the isser
399 */
400enum GNUNET_GenericReturnValue
401pabc_get_expiration_c (void *cls,
402 const struct GNUNET_RECLAIM_Credential *cred,
403 struct GNUNET_TIME_Absolute *exp)
404{
405 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
406 return GNUNET_NO;
407 return pabc_get_expiration (cls, cred->data, cred->data_size, exp);
408}
409
410
411/**
412 * Parse a pabc and return the expiration
413 *
414 * @param cls the plugin
415 * @param cred the pabc credential
416 * @return a string, containing the isser
417 */
418enum GNUNET_GenericReturnValue
419pabc_get_expiration_p (void *cls,
420 const struct GNUNET_RECLAIM_Presentation *cred,
421 struct GNUNET_TIME_Absolute *exp)
422{
423 if (cred->type != GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC)
424 return GNUNET_NO;
425 return pabc_get_expiration (cls, cred->data, cred->data_size, exp);
426}
427
428
429int
430pabc_create_presentation (void *cls,
431 const struct GNUNET_RECLAIM_Credential *credential,
432 const struct GNUNET_RECLAIM_AttributeList *attrs,
433 struct GNUNET_RECLAIM_Presentation **pres)
434{
435 struct pabc_context *ctx = NULL;
436 struct pabc_user_context *usr_ctx = NULL;
437 struct pabc_public_parameters *pp = NULL;
438 struct pabc_credential *cred = NULL;
439 struct pabc_blinded_proof *proof = NULL;
440 struct GNUNET_RECLAIM_AttributeListEntry *ale;
441 char *issuer;
442 char *subject;
443 enum pabc_status status;
444
445 if (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC != credential->type)
446 return GNUNET_NO;
447
448
449 PABC_ASSERT (pabc_new_ctx (&ctx));
450 issuer = pabc_get_issuer_c (cls, credential);
451 if (NULL == issuer)
452 {
453 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
454 "No issuer found in credential\n");
455 pabc_free_ctx (&ctx);
456 return GNUNET_SYSERR;
457 }
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
459 "Got issuer for credential: %s\n", issuer);
460 status = PABC_load_public_parameters (ctx, issuer, &pp);
461 if (status != PABC_OK)
462 {
463 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
464 "Failed to read public parameters.\n");
465 pabc_free_ctx (&ctx);
466 GNUNET_free (issuer);
467 return GNUNET_SYSERR;
468 }
469 if (PABC_OK != pabc_cred_get_attr_by_name_from_cred (credential->data,
470 "subject",
471 &subject))
472 {
473 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
474 "Failed to get subject.\n");
475 pabc_free_ctx (&ctx);
476 GNUNET_free (issuer);
477 return GNUNET_SYSERR;
478 }
479 status = PABC_read_usr_ctx (subject, issuer, ctx, pp, &usr_ctx);
480 GNUNET_free (issuer);
481 GNUNET_free (subject);
482 if (PABC_OK != status)
483 {
484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
485 "Failed to read user context.\n");
486 pabc_free_public_parameters (ctx, &pp);
487 return GNUNET_SYSERR;
488 }
489
490 status = pabc_new_credential (ctx, pp, &cred);
491 if (status != PABC_OK)
492 {
493 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
494 "Failed to allocate credential.\n");
495 pabc_free_user_context (ctx, pp, &usr_ctx);
496 pabc_free_public_parameters (ctx, &pp);
497 return GNUNET_SYSERR;
498 }
499
500 status = pabc_decode_credential (ctx, pp, cred, credential->data);
501 if (status != PABC_OK)
502 {
503 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
504 "Failed to decode credential.\n");
505 pabc_free_credential (ctx, pp, &cred);
506 pabc_free_user_context (ctx, pp, &usr_ctx);
507 pabc_free_public_parameters (ctx, &pp);
508 return GNUNET_SYSERR;
509 }
510
511 status = pabc_new_proof (ctx, pp, &proof);
512 if (status != PABC_OK)
513 {
514 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
515 "Failed to allocate proof.\n");
516 pabc_free_credential (ctx, pp, &cred);
517 pabc_free_user_context (ctx, pp, &usr_ctx);
518 pabc_free_public_parameters (ctx, &pp);
519 return GNUNET_SYSERR;
520 }
521
522 // now we can parse the attributes to disclose and configure the proof
523 for (ale = attrs->list_head; NULL != ale; ale = ale->next)
524 {
525 status = pabc_set_disclosure_by_attribute_name (ctx, pp, proof,
526 ale->attribute->name,
527 PABC_DISCLOSED, cred);
528 if (status != PABC_OK)
529 {
530 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
531 "Failed to configure proof.\n");
532 pabc_free_credential (ctx, pp, &cred);
533 pabc_free_user_context (ctx, pp, &usr_ctx);
534 pabc_free_public_parameters (ctx, &pp);
535 return GNUNET_SYSERR;
536 }
537 }
538
539 // and finally -> sign the proof
540 status = pabc_gen_proof (ctx, usr_ctx, pp, proof, cred);
541 if (status != PABC_OK)
542 {
543 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
544 "Failed to sign proof.\n");
545 pabc_free_proof (ctx, pp, &proof);
546 pabc_free_credential (ctx, pp, &cred);
547 pabc_free_user_context (ctx, pp, &usr_ctx);
548 pabc_free_public_parameters (ctx, &pp);
549 return GNUNET_SYSERR;
550 }
551 // print the result
552 char *json = NULL;
553 char *ppid = NULL;
554 char *userid = NULL;
555 GNUNET_assert (PABC_OK == pabc_cred_get_userid_from_cred (credential->data,
556 &userid));
557 GNUNET_assert (PABC_OK == pabc_cred_get_ppid_from_cred (credential->data,
558 &ppid));
559 pabc_cred_encode_proof (ctx, pp, proof, userid, ppid, &json);
560 GNUNET_free (ppid);
561 GNUNET_free (userid);
562 if (PABC_OK != status)
563 {
564 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
565 "Failed to serialize proof.\n");
566 pabc_free_proof (ctx, pp, &proof);
567 pabc_free_credential (ctx, pp, &cred);
568 pabc_free_user_context (ctx, pp, &usr_ctx);
569 pabc_free_public_parameters (ctx, &pp);
570 return GNUNET_SYSERR;
571 }
572 char *json_enc;
573 GNUNET_STRINGS_base64_encode (json,
574 strlen (json) + 1,
575 &json_enc);
576 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
577 "Presentation: %s\n", json_enc);
578 // clean up
579 *pres = GNUNET_RECLAIM_presentation_new (GNUNET_RECLAIM_CREDENTIAL_TYPE_PABC,
580 json_enc,
581 strlen (json_enc) + 1);
582 GNUNET_free (json_enc);
583 PABC_FREE_NULL (json);
584 pabc_free_proof (ctx, pp, &proof);
585 pabc_free_credential (ctx, pp, &cred);
586 pabc_free_user_context (ctx, pp, &usr_ctx);
587 pabc_free_public_parameters (ctx, &pp);
588 return GNUNET_OK;
589}
590
591
592/**
593 * Entry point for the plugin.
594 *
595 * @param cls NULL
596 * @return the exported block API
597 */
598void *
599libgnunet_plugin_reclaim_credential_pabc_init (void *cls)
600{
601 struct GNUNET_RECLAIM_CredentialPluginFunctions *api;
602
603 api = GNUNET_new (struct GNUNET_RECLAIM_CredentialPluginFunctions);
604 api->value_to_string = &pabc_value_to_string;
605 api->string_to_value = &pabc_string_to_value;
606 api->typename_to_number = &pabc_typename_to_number;
607 api->number_to_typename = &pabc_number_to_typename;
608 api->get_attributes = &pabc_parse_attributes_c;
609 api->get_issuer = &pabc_get_issuer_c;
610 api->get_expiration = &pabc_get_expiration_c;
611 api->value_to_string_p = &pabc_value_to_string;
612 api->string_to_value_p = &pabc_string_to_value;
613 api->typename_to_number_p = &pabc_typename_to_number;
614 api->number_to_typename_p = &pabc_number_to_typename;
615 api->get_attributes_p = &pabc_parse_attributes_p;
616 api->get_issuer_p = &pabc_get_issuer_p;
617 api->get_expiration_p = &pabc_get_expiration_p;
618 api->create_presentation = &pabc_create_presentation;
619 return api;
620}
621
622
623/**
624 * Exit point from the plugin.
625 *
626 * @param cls the return value from #libgnunet_plugin_block_test_init()
627 * @return NULL
628 */
629void *
630libgnunet_plugin_reclaim_credential_pabc_done (void *cls)
631{
632 struct GNUNET_RECLAIM_CredentialPluginFunctions *api = cls;
633
634 GNUNET_free (api);
635 return NULL;
636}
637
638
639/* end of plugin_reclaim_credential_type_pabc.c */