JWT Plugin, Prepared Ticketing
[oweals/gnunet.git] / src / reclaim-attribute / reclaim_attribute.c
1 /*
2    This file is part of GNUnet
3    Copyright (C) 2010-2015 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-attribute/reclaim_attribute.c
23  * @brief helper library to manage identity attributes
24  * @author Martin Schanzenbach
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_reclaim_attribute_plugin.h"
29 #include "reclaim_attribute.h"
30
31
32 /**
33  * Handle for a plugin
34  */
35 struct Plugin
36 {
37   /**
38    * Name of the plugin
39    */
40   char *library_name;
41
42   /**
43    * Plugin API
44    */
45   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api;
46 };
47
48
49 /**
50  * Plugins
51  */
52 static struct Plugin **attr_plugins;
53
54
55 /**
56  * Number of plugins
57  */
58 static unsigned int num_plugins;
59
60
61 /**
62  * Init canary
63  */
64 static int initialized;
65
66
67 /**
68  * Add a plugin
69  *
70  * @param cls closure
71  * @param library_name name of the API library
72  * @param lib_ret the plugin API pointer
73  */
74 static void
75 add_plugin (void *cls, const char *library_name, void *lib_ret)
76 {
77   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = lib_ret;
78   struct Plugin *plugin;
79
80   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
81               "Loading attribute plugin `%s'\n",
82               library_name);
83   plugin = GNUNET_new (struct Plugin);
84   plugin->api = api;
85   plugin->library_name = GNUNET_strdup (library_name);
86   GNUNET_array_append (attr_plugins, num_plugins, plugin);
87 }
88
89
90 /**
91  * Load plugins
92  */
93 static void
94 init ()
95 {
96   if (GNUNET_YES == initialized)
97     return;
98   initialized = GNUNET_YES;
99   GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_",
100                           NULL,
101                           &add_plugin,
102                           NULL);
103 }
104
105
106 /**
107  * Convert a type name to the corresponding number
108  *
109  * @param typename name to convert
110  * @return corresponding number, UINT32_MAX on error
111  */
112 uint32_t
113 GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename)
114 {
115   unsigned int i;
116   struct Plugin *plugin;
117   uint32_t ret;
118
119   init ();
120   for (i = 0; i < num_plugins; i++)
121   {
122     plugin = attr_plugins[i];
123     if (UINT32_MAX !=
124         (ret = plugin->api->typename_to_number (plugin->api->cls, typename)))
125       return ret;
126   }
127   return UINT32_MAX;
128 }
129
130
131 /**
132  * Convert a type number to the corresponding type string
133  *
134  * @param type number of a type
135  * @return corresponding typestring, NULL on error
136  */
137 const char *
138 GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type)
139 {
140   unsigned int i;
141   struct Plugin *plugin;
142   const char *ret;
143
144   init ();
145   for (i = 0; i < num_plugins; i++)
146   {
147     plugin = attr_plugins[i];
148     if (NULL !=
149         (ret = plugin->api->number_to_typename (plugin->api->cls, type)))
150       return ret;
151   }
152   return NULL;
153 }
154
155
156 /**
157  * Convert human-readable version of a 'claim' of an attribute to the binary
158  * representation
159  *
160  * @param type type of the claim
161  * @param s human-readable string
162  * @param data set to value in binary encoding (will be allocated)
163  * @param data_size set to number of bytes in @a data
164  * @return #GNUNET_OK on success
165  */
166 int
167 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type,
168                                           const char *s,
169                                           void **data,
170                                           size_t *data_size)
171 {
172   unsigned int i;
173   struct Plugin *plugin;
174
175   init ();
176   for (i = 0; i < num_plugins; i++)
177   {
178     plugin = attr_plugins[i];
179     if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
180                                                    type,
181                                                    s,
182                                                    data,
183                                                    data_size))
184       return GNUNET_OK;
185   }
186   return GNUNET_SYSERR;
187 }
188
189
190 /**
191  * Convert the 'claim' of an attribute to a string
192  *
193  * @param type the type of attribute
194  * @param data claim in binary encoding
195  * @param data_size number of bytes in @a data
196  * @return NULL on error, otherwise human-readable representation of the claim
197  */
198 char *
199 GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
200                                           const void *data,
201                                           size_t data_size)
202 {
203   unsigned int i;
204   struct Plugin *plugin;
205   char *ret;
206
207   init ();
208   for (i = 0; i < num_plugins; i++)
209   {
210     plugin = attr_plugins[i];
211     if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
212                                                      type,
213                                                      data,
214                                                      data_size)))
215       return ret;
216   }
217   return NULL;
218 }
219
220 /**
221    * Convert an attestation type name to the corresponding number
222    *
223    * @param typename name to convert
224    * @return corresponding number, UINT32_MAX on error
225    */
226 uint32_t
227 GNUNET_RECLAIM_ATTESTATION_typename_to_number (const char *typename)
228 {
229   unsigned int i;
230   struct Plugin *plugin;
231   uint32_t ret;
232   init ();
233   for (i = 0; i < num_plugins; i++)
234   {
235     plugin = attr_plugins[i];
236     if (UINT32_MAX !=
237         (ret = plugin->api->typename_to_number_attest (plugin->api->cls,
238                                                        typename)))
239       return ret;
240   }
241   return UINT32_MAX;
242 }
243
244 /**
245  * Convert an attestation type number to the corresponding attestation type string
246  *
247  * @param type number of a type
248  * @return corresponding typestring, NULL on error
249  */
250 const char *
251 GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type)
252 {
253   unsigned int i;
254   struct Plugin *plugin;
255   const char *ret;
256
257   init ();
258   for (i = 0; i < num_plugins; i++)
259   {
260     plugin = attr_plugins[i];
261     if (NULL !=
262         (ret = plugin->api->number_to_typename_attest (plugin->api->cls, type)))
263       return ret;
264   }
265   return NULL;
266 }
267 /**
268  * Convert human-readable version of a 'claim' of an attestation to the binary
269  * representation
270  *
271  * @param type type of the claim
272  * @param s human-readable string
273  * @param data set to value in binary encoding (will be allocated)
274  * @param data_size set to number of bytes in @a data
275  * @return #GNUNET_OK on success
276  */
277 int
278 GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type,
279                                             const char *s,
280                                             void **data,
281                                             size_t *data_size)
282 {
283   unsigned int i;
284   struct Plugin *plugin;
285
286   init ();
287   for (i = 0; i < num_plugins; i++)
288   {
289     plugin = attr_plugins[i];
290     if (GNUNET_OK == plugin->api->string_to_value_attest (plugin->api->cls,
291                                                           type,
292                                                           s,
293                                                           data,
294                                                           data_size))
295       return GNUNET_OK;
296   }
297   return GNUNET_SYSERR;
298 }
299
300
301 /**
302  * Convert the 'claim' of an attestation to a string
303  *
304  * @param type the type of attestation
305  * @param data claim in binary encoding
306  * @param data_size number of bytes in @a data
307  * @return NULL on error, otherwise human-readable representation of the claim
308  */
309 char *
310 GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type,
311                                             const void *data,
312                                             size_t data_size)
313 {
314   unsigned int i;
315   struct Plugin *plugin;
316   char *ret;
317
318   init ();
319   for (i = 0; i < num_plugins; i++)
320   {
321     plugin = attr_plugins[i];
322     if (NULL != (ret = plugin->api->value_to_string_attest (plugin->api->cls,
323                                                             type,
324                                                             data,
325                                                             data_size)))
326       return ret;
327   }
328   return NULL;
329 }
330
331 /**
332  * Create a new attribute.
333  *
334  * @param attr_name the attribute name
335  * @param type the attribute type
336  * @param data the attribute value
337  * @param data_size the attribute value size
338  * @return the new attribute
339  */
340 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
341 GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
342                                     uint32_t type,
343                                     const void *data,
344                                     size_t data_size)
345 {
346   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
347   char *write_ptr;
348   char *attr_name_tmp = GNUNET_strdup (attr_name);
349
350   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
351
352   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
353                         + strlen (attr_name_tmp) + 1 + data_size);
354   attr->type = type;
355   attr->data_size = data_size;
356   attr->flag = 0;
357   write_ptr = (char *) &attr[1];
358   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
359   attr->name = write_ptr;
360   write_ptr += strlen (attr->name) + 1;
361   GNUNET_memcpy (write_ptr, data, data_size);
362   attr->data = write_ptr;
363   GNUNET_free (attr_name_tmp);
364   return attr;
365 }
366
367 /**
368    * Create a new attestation.
369    *
370    * @param attr_name the attestation name
371    * @param type the attestation type
372    * @param data the attestation value
373    * @param data_size the attestation value size
374    * @return the new attestation
375    */
376 struct GNUNET_RECLAIM_ATTESTATION_Claim *
377 GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name,
378                                       uint32_t type,
379                                       const void *data,
380                                       size_t data_size)
381 {
382   struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
383   char *write_ptr;
384   char *attr_name_tmp = GNUNET_strdup (attr_name);
385
386   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
387
388   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
389                         + strlen (attr_name_tmp) + 1 + data_size);
390   attr->type = type;
391   attr->data_size = data_size;
392   attr->version = 0;
393   write_ptr = (char *) &attr[1];
394   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
395   attr->name = write_ptr;
396   write_ptr += strlen (attr->name) + 1;
397   GNUNET_memcpy (write_ptr, data, data_size);
398   attr->data = write_ptr;
399   GNUNET_free (attr_name_tmp);
400   return attr;
401 }
402
403 /**
404  * Create a new attestation reference.
405  *
406  * @param attr_name the referenced claim name
407  * @param ref_value the claim name in the attestation
408  * @return the new reference
409  */
410 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
411 GNUNET_RECLAIM_ATTESTATION_reference_new (const char *attr_name,
412                                           const char *ref_value)
413 {
414   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
415   char *write_ptr;
416   char *attr_name_tmp = GNUNET_strdup (attr_name);
417   char *ref_value_tmp = GNUNET_strdup (ref_value);
418
419   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
420   GNUNET_STRINGS_utf8_tolower (ref_value, ref_value_tmp);
421
422   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
423                         + strlen (attr_name_tmp) + strlen (ref_value_tmp) + 2);
424
425   write_ptr = (char *) &attr[1];
426   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
427   attr->name = write_ptr;
428
429   write_ptr += strlen (attr_name) + 1;
430   GNUNET_memcpy (write_ptr, ref_value_tmp, strlen (ref_value_tmp) + 1);
431   attr->reference_value = write_ptr;
432
433   GNUNET_free (attr_name_tmp);
434   GNUNET_free (ref_value_tmp);
435   return attr;
436 }
437
438 /**
439  * Add a new attribute to a claim list
440  *
441  * @param attr_name the name of the new attribute claim
442  * @param type the type of the claim
443  * @param data claim payload
444  * @param data_size claim payload size
445  */
446 void
447 GNUNET_RECLAIM_ATTRIBUTE_list_add (
448   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
449   const char *attr_name,
450   uint32_t type,
451   const void *data,
452   size_t data_size)
453 {
454   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
455
456   le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
457   le->claim =
458     GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
459   GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
460                                claim_list->list_tail,
461                                le);
462 }
463
464
465 /**
466  * Get required size for serialization buffer
467  *
468  * @param attrs the attribute list to serialize
469  * @return the required buffer size
470  */
471 size_t
472 GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (
473   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
474 {
475   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
476   size_t len = 0;
477
478   for (le = attrs->list_head; NULL != le; le = le->next)
479     len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
480   return len;
481 }
482
483
484 /**
485  * Serialize an attribute list
486  *
487  * @param attrs the attribute list to serialize
488  * @param result the serialized attribute
489  * @return length of serialized data
490  */
491 size_t
492 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
493   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
494   char *result)
495 {
496   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
497   size_t len;
498   size_t total_len;
499   char *write_ptr;
500
501   write_ptr = result;
502   total_len = 0;
503   for (le = attrs->list_head; NULL != le; le = le->next)
504   {
505     len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
506     total_len += len;
507     write_ptr += len;
508   }
509   return total_len;
510 }
511
512
513 /**
514  * Deserialize an attribute list
515  *
516  * @param data the serialized attribute list
517  * @param data_size the length of the serialized data
518  * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
519  */
520 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
521 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size)
522 {
523   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
524   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
525   size_t attr_len;
526   const char *read_ptr;
527
528   if (data_size < sizeof(struct Attribute))
529     return NULL;
530
531   attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
532   read_ptr = data;
533   while (((data + data_size) - read_ptr) >= sizeof(struct Attribute))
534   {
535     le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
536     le->claim =
537       GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
538                                             data_size - (read_ptr - data));
539     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
540                 "Deserialized attribute %s\n",
541                 le->claim->name);
542     GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
543     attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
544     read_ptr += attr_len;
545   }
546   return attrs;
547 }
548
549
550 /**
551  * Make a (deep) copy of a claim list
552  * @param attrs claim list to copy
553  * @return copied claim list
554  */
555 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
556 GNUNET_RECLAIM_ATTRIBUTE_list_dup (
557   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
558 {
559   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
560   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
561   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
562
563   result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
564   for (le = attrs->list_head; NULL != le; le = le->next)
565   {
566     result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
567     result_le->claim =
568       GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
569                                           le->claim->type,
570                                           le->claim->data,
571                                           le->claim->data_size);
572     result_le->claim->id = le->claim->id;
573     result_le->claim->flag = le->claim->flag;
574     GNUNET_CONTAINER_DLL_insert (result->list_head,
575                                  result->list_tail,
576                                  result_le);
577   }
578   return result;
579 }
580
581
582 /**
583  * Destroy claim list
584  *
585  * @param attrs list to destroy
586  */
587 void
588 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
589   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
590 {
591   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
592   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
593
594   for (le = attrs->list_head; NULL != le;)
595   {
596     GNUNET_free (le->claim);
597     tmp_le = le;
598     le = le->next;
599     GNUNET_free (tmp_le);
600   }
601   GNUNET_free (attrs);
602 }
603
604
605 /**
606  * Get required size for serialization buffer
607  *
608  * @param attr the attribute to serialize
609  * @return the required buffer size
610  */
611 size_t
612 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (
613   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
614 {
615   return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
616 }
617
618
619 /**
620  * Serialize an attribute
621  *
622  * @param attr the attribute to serialize
623  * @param result the serialized attribute
624  * @return length of serialized data
625  */
626 size_t
627 GNUNET_RECLAIM_ATTRIBUTE_serialize (
628   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
629   char *result)
630 {
631   size_t data_len_ser;
632   size_t name_len;
633   struct Attribute *attr_ser;
634   char *write_ptr;
635
636   attr_ser = (struct Attribute *) result;
637   attr_ser->attribute_type = htons (attr->type);
638   attr_ser->attribute_version = htonl (attr->flag);
639   attr_ser->attribute_id = GNUNET_htonll (attr->id);
640   name_len = strlen (attr->name);
641   attr_ser->name_len = htons (name_len);
642   write_ptr = (char *) &attr_ser[1];
643   GNUNET_memcpy (write_ptr, attr->name, name_len);
644   write_ptr += name_len;
645   // TODO plugin-ize
646   // data_len_ser = plugin->serialize_attribute_value (attr,
647   //                                                  &attr_ser[1]);
648   data_len_ser = attr->data_size;
649   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
650   attr_ser->data_size = htons (data_len_ser);
651
652   return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
653 }
654
655
656 /**
657  * Deserialize an attribute
658  *
659  * @param data the serialized attribute
660  * @param data_size the length of the serialized data
661  *
662  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
663  */
664 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
665 GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
666 {
667   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
668   struct Attribute *attr_ser;
669   size_t data_len;
670   size_t name_len;
671   char *write_ptr;
672
673   if (data_size < sizeof(struct Attribute))
674     return NULL;
675
676   attr_ser = (struct Attribute *) data;
677   data_len = ntohs (attr_ser->data_size);
678   name_len = ntohs (attr_ser->name_len);
679   if (data_size < sizeof(struct Attribute) + data_len + name_len)
680   {
681     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
682                 "Buffer too small to deserialize\n");
683     return NULL;
684   }
685   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
686                         + data_len + name_len + 1);
687   attr->type = ntohs (attr_ser->attribute_type);
688   attr->flag = ntohl (attr_ser->attribute_version);
689   attr->id = GNUNET_ntohll (attr_ser->attribute_id);
690   attr->data_size = data_len;
691
692   write_ptr = (char *) &attr[1];
693   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
694   write_ptr[name_len] = '\0';
695   attr->name = write_ptr;
696
697   write_ptr += name_len + 1;
698   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
699   attr->data = write_ptr;
700   return attr;
701 }
702
703
704 /**
705  * Get required size for serialization buffer
706  *
707  * @param attr the attestation to serialize
708  * @return the required buffer size
709  */
710 size_t
711 GNUNET_RECLAIM_ATTESTATION_serialize_get_size (
712   const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr)
713 {
714   return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
715 }
716
717 /**
718  * Serialize an attestation
719  *
720  * @param attr the attestation to serialize
721  * @param result the serialized attestation
722  * @return length of serialized data
723  */
724 size_t
725 GNUNET_RECLAIM_ATTESTATION_serialize (
726   const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
727   char *result)
728 {
729   size_t data_len_ser;
730   size_t name_len;
731   struct Attestation *attr_ser;
732   char *write_ptr;
733
734   attr_ser = (struct Attestation *) result;
735   attr_ser->attestation_type = htons (attr->type);
736   attr_ser->attestation_version = htonl (attr->version);
737   attr_ser->attestation_id = GNUNET_htonll (attr->id);
738   name_len = strlen (attr->name);
739   attr_ser->name_len = htons (name_len);
740   write_ptr = (char *) &attr_ser[1];
741   GNUNET_memcpy (write_ptr, attr->name, name_len);
742   write_ptr += name_len;
743   // TODO plugin-ize
744   // data_len_ser = plugin->serialize_attribute_value (attr,
745   //                                                  &attr_ser[1]);
746   data_len_ser = attr->data_size;
747   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
748   attr_ser->data_size = htons (data_len_ser);
749
750   return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
751 }
752
753 /**
754  * Deserialize an attestation
755  *
756  * @param data the serialized attestation
757  * @param data_size the length of the serialized data
758  *
759  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
760  */
761 struct GNUNET_RECLAIM_ATTESTATION_Claim *
762 GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size)
763 {
764   struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
765   struct Attestation *attr_ser;
766   size_t data_len;
767   size_t name_len;
768   char *write_ptr;
769
770   if (data_size < sizeof(struct Attestation))
771     return NULL;
772
773   attr_ser = (struct Attestation *) data;
774   data_len = ntohs (attr_ser->data_size);
775   name_len = ntohs (attr_ser->name_len);
776   if (data_size < sizeof(struct Attestation) + data_len + name_len)
777   {
778     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
779                 "Buffer too small to deserialize\n");
780     return NULL;
781   }
782   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
783                         + data_len + name_len + 1);
784   attr->type = ntohs (attr_ser->attestation_type);
785   attr->version = ntohl (attr_ser->attestation_version);
786   attr->id = GNUNET_ntohll (attr_ser->attestation_id);
787   attr->data_size = data_len;
788
789   write_ptr = (char *) &attr[1];
790   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
791   write_ptr[name_len] = '\0';
792   attr->name = write_ptr;
793
794   write_ptr += name_len + 1;
795   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
796   attr->data = write_ptr;
797   return attr;
798 }
799
800 /**
801  * Get required size for serialization buffer
802  *
803  * @param attr the reference to serialize
804  * @return the required buffer size
805  */
806 size_t
807 GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (
808   const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr)
809 {
810   return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
811     attr->reference_value);
812 }
813
814
815 /**
816  * Serialize a reference
817  *
818  * @param attr the reference to serialize
819  * @param result the serialized reference
820  * @return length of serialized data
821  */
822 size_t
823 GNUNET_RECLAIM_ATTESTATION_REF_serialize (
824   const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
825   char *result)
826 {
827   size_t name_len;
828   size_t refval_len;
829   struct Attestation_Reference *attr_ser;
830   char *write_ptr;
831   attr_ser = (struct Attestation_Reference *) result;
832   attr_ser->reference_id = GNUNET_htonll (attr->id);
833   attr_ser->attestation_id = GNUNET_htonll (attr->id_attest);
834   name_len = strlen (attr->name);
835   refval_len = strlen (attr->reference_value);
836   attr_ser->name_len = htons (name_len);
837   attr_ser->ref_value_len = htons (refval_len);
838   write_ptr = (char *) &attr_ser[1];
839   GNUNET_memcpy (write_ptr, attr->name, name_len);
840   write_ptr += name_len;
841   GNUNET_memcpy (write_ptr, attr->reference_value, refval_len);
842
843   return sizeof(struct Attestation_Reference) + strlen (attr->name) + strlen (
844     attr->reference_value);
845 }
846
847
848 /**
849  * Deserialize a reference
850  *
851  * @param data the serialized reference
852  * @param data_size the length of the serialized data
853  *
854  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
855  */
856 struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *
857 GNUNET_RECLAIM_ATTESTATION_REF_deserialize (const char *data, size_t data_size)
858 {
859   struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
860   struct Attestation_Reference *attr_ser;
861   size_t name_len;
862   size_t refval_len;
863   char *write_ptr;
864
865   if (data_size < sizeof(struct Attestation_Reference))
866     return NULL;
867   attr_ser = (struct Attestation_Reference *) data;
868   name_len = ntohs (attr_ser->name_len);
869   refval_len = ntohs (attr_ser->ref_value_len);
870   if (data_size < sizeof(struct Attestation_Reference) + refval_len + name_len)
871   {
872     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
873                 "Buffer too small to deserialize\n");
874     return NULL;
875   }
876   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_REFERENCE)
877                         + refval_len + name_len + 2);
878
879   attr->id = GNUNET_ntohll (attr_ser->reference_id);
880   attr->id_attest = GNUNET_ntohll (attr_ser->attestation_id);
881
882   write_ptr = (char *) &attr[1];
883   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
884   write_ptr[name_len] = '\0';
885   attr->name = write_ptr;
886
887   write_ptr += name_len + 1;
888   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, refval_len);
889   write_ptr[refval_len] = '\0';
890   attr->reference_value = write_ptr;
891   return attr;
892 }
893 /* end of reclaim_attribute.c */