Adapted JSON Conversion and Serialization
[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
233   init ();
234   for (i = 0; i < num_plugins; i++)
235   {
236     plugin = attr_plugins[i];
237     if (UINT32_MAX !=
238         (ret = plugin->api->typename_to_number_attest (plugin->api->cls,
239                                                        typename)))
240       return ret;
241   }
242   return UINT32_MAX;
243 }
244
245 /**
246  * Convert an attestation type number to the corresponding attestation type string
247  *
248  * @param type number of a type
249  * @return corresponding typestring, NULL on error
250  */
251 const char *
252 GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type)
253 {
254   unsigned int i;
255   struct Plugin *plugin;
256   const char *ret;
257
258   init ();
259   for (i = 0; i < num_plugins; i++)
260   {
261     plugin = attr_plugins[i];
262     if (NULL !=
263         (ret = plugin->api->number_to_typename_attest (plugin->api->cls, type)))
264       return ret;
265   }
266   return NULL;
267 }
268 /**
269  * Convert human-readable version of a 'claim' of an attestation to the binary
270  * representation
271  *
272  * @param type type of the claim
273  * @param s human-readable string
274  * @param data set to value in binary encoding (will be allocated)
275  * @param data_size set to number of bytes in @a data
276  * @return #GNUNET_OK on success
277  */
278 int
279 GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type,
280                                             const char *s,
281                                             void **data,
282                                             size_t *data_size)
283 {
284   unsigned int i;
285   struct Plugin *plugin;
286
287   init ();
288   for (i = 0; i < num_plugins; i++)
289   {
290     plugin = attr_plugins[i];
291     if (GNUNET_OK == plugin->api->string_to_value_attest (plugin->api->cls,
292                                                           type,
293                                                           s,
294                                                           data,
295                                                           data_size))
296       return GNUNET_OK;
297   }
298   return GNUNET_SYSERR;
299 }
300
301
302 /**
303  * Convert the 'claim' of an attestation to a string
304  *
305  * @param type the type of attestation
306  * @param data claim in binary encoding
307  * @param data_size number of bytes in @a data
308  * @return NULL on error, otherwise human-readable representation of the claim
309  */
310 char *
311 GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type,
312                                             const void *data,
313                                             size_t data_size)
314 {
315   unsigned int i;
316   struct Plugin *plugin;
317   char *ret;
318
319   init ();
320   for (i = 0; i < num_plugins; i++)
321   {
322     plugin = attr_plugins[i];
323     if (NULL != (ret = plugin->api->value_to_string_attest (plugin->api->cls,
324                                                             type,
325                                                             data,
326                                                             data_size)))
327       return ret;
328   }
329   return NULL;
330 }
331
332 /**
333  * Create a new attribute.
334  *
335  * @param attr_name the attribute name
336  * @param type the attribute type
337  * @param data the attribute value
338  * @param data_size the attribute value size
339  * @return the new attribute
340  */
341 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
342 GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name,
343                                     uint32_t type,
344                                     const void *data,
345                                     size_t data_size)
346 {
347   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
348   char *write_ptr;
349   char *attr_name_tmp = GNUNET_strdup (attr_name);
350
351   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
352
353   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
354                         + strlen (attr_name_tmp) + 1 + data_size);
355   attr->type = type;
356   attr->data_size = data_size;
357   attr->version = 0;
358   write_ptr = (char *) &attr[1];
359   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
360   attr->name = write_ptr;
361   write_ptr += strlen (attr->name) + 1;
362   GNUNET_memcpy (write_ptr, data, data_size);
363   attr->data = write_ptr;
364   GNUNET_free (attr_name_tmp);
365   return attr;
366 }
367
368 /**
369    * Create a new attestation.
370    *
371    * @param attr_name the attestation name
372    * @param type the attestation type
373    * @param data the attestation value
374    * @param data_size the attestation value size
375    * @return the new attestation
376    */
377 struct GNUNET_RECLAIM_ATTESTATION_Claim *
378 GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name,
379                                       uint32_t type,
380                                       const void *data,
381                                       size_t data_size)
382 {
383   struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
384   char *write_ptr;
385   char *attr_name_tmp = GNUNET_strdup (attr_name);
386
387   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
388
389   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
390                         + strlen (attr_name_tmp) + 1 + data_size);
391   attr->type = type;
392   attr->data_size = data_size;
393   attr->version = 0;
394   write_ptr = (char *) &attr[1];
395   GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1);
396   attr->name = write_ptr;
397   write_ptr += strlen (attr->name) + 1;
398   GNUNET_memcpy (write_ptr, data, data_size);
399   attr->data = write_ptr;
400   GNUNET_free (attr_name_tmp);
401   return attr;
402 }
403
404 /**
405  * Add a new attribute to a claim list
406  *
407  * @param attr_name the name of the new attribute claim
408  * @param type the type of the claim
409  * @param data claim payload
410  * @param data_size claim payload size
411  */
412 void
413 GNUNET_RECLAIM_ATTRIBUTE_list_add (
414   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
415   const char *attr_name,
416   uint32_t type,
417   const void *data,
418   size_t data_size)
419 {
420   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
421
422   le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
423   le->claim =
424     GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name, type, data, data_size);
425   GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
426                                claim_list->list_tail,
427                                le);
428 }
429
430
431 /**
432  * Get required size for serialization buffer
433  *
434  * @param attrs the attribute list to serialize
435  * @return the required buffer size
436  */
437 size_t
438 GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (
439   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
440 {
441   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
442   size_t len = 0;
443
444   for (le = attrs->list_head; NULL != le; le = le->next)
445     len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
446   return len;
447 }
448
449
450 /**
451  * Serialize an attribute list
452  *
453  * @param attrs the attribute list to serialize
454  * @param result the serialized attribute
455  * @return length of serialized data
456  */
457 size_t
458 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (
459   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
460   char *result)
461 {
462   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
463   size_t len;
464   size_t total_len;
465   char *write_ptr;
466
467   write_ptr = result;
468   total_len = 0;
469   for (le = attrs->list_head; NULL != le; le = le->next)
470   {
471     len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim, write_ptr);
472     total_len += len;
473     write_ptr += len;
474   }
475   return total_len;
476 }
477
478
479 /**
480  * Deserialize an attribute list
481  *
482  * @param data the serialized attribute list
483  * @param data_size the length of the serialized data
484  * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
485  */
486 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
487 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char *data, size_t data_size)
488 {
489   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
490   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
491   size_t attr_len;
492   const char *read_ptr;
493
494   if (data_size < sizeof(struct Attribute))
495     return NULL;
496
497   attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
498   read_ptr = data;
499   while (((data + data_size) - read_ptr) >= sizeof(struct Attribute))
500   {
501     le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
502     le->claim =
503       GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
504                                             data_size - (read_ptr - data));
505     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
506                 "Deserialized attribute %s\n",
507                 le->claim->name);
508     GNUNET_CONTAINER_DLL_insert (attrs->list_head, attrs->list_tail, le);
509     attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
510     read_ptr += attr_len;
511   }
512   return attrs;
513 }
514
515
516 /**
517  * Make a (deep) copy of a claim list
518  * @param attrs claim list to copy
519  * @return copied claim list
520  */
521 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
522 GNUNET_RECLAIM_ATTRIBUTE_list_dup (
523   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
524 {
525   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
526   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
527   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
528
529   result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
530   for (le = attrs->list_head; NULL != le; le = le->next)
531   {
532     result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
533     result_le->claim =
534       GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
535                                           le->claim->type,
536                                           le->claim->data,
537                                           le->claim->data_size);
538     result_le->claim->version = le->claim->version;
539     result_le->claim->id = le->claim->id;
540     GNUNET_CONTAINER_DLL_insert (result->list_head,
541                                  result->list_tail,
542                                  result_le);
543   }
544   return result;
545 }
546
547
548 /**
549  * Destroy claim list
550  *
551  * @param attrs list to destroy
552  */
553 void
554 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (
555   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
556 {
557   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
558   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
559
560   for (le = attrs->list_head; NULL != le;)
561   {
562     GNUNET_free (le->claim);
563     tmp_le = le;
564     le = le->next;
565     GNUNET_free (tmp_le);
566   }
567   GNUNET_free (attrs);
568 }
569
570
571 /**
572  * Get required size for serialization buffer
573  *
574  * @param attr the attribute to serialize
575  * @return the required buffer size
576  */
577 size_t
578 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (
579   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
580 {
581   return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
582 }
583
584
585 /**
586  * Serialize an attribute
587  *
588  * @param attr the attribute to serialize
589  * @param result the serialized attribute
590  * @return length of serialized data
591  */
592 size_t
593 GNUNET_RECLAIM_ATTRIBUTE_serialize (
594   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
595   char *result)
596 {
597   size_t data_len_ser;
598   size_t name_len;
599   struct Attribute *attr_ser;
600   char *write_ptr;
601
602   attr_ser = (struct Attribute *) result;
603   attr_ser->attribute_type = htons (attr->type);
604   attr_ser->attribute_version = htonl (attr->version);
605   attr_ser->attribute_id = GNUNET_htonll (attr->id);
606   name_len = strlen (attr->name);
607   attr_ser->name_len = htons (name_len);
608   write_ptr = (char *) &attr_ser[1];
609   GNUNET_memcpy (write_ptr, attr->name, name_len);
610   write_ptr += name_len;
611   // TODO plugin-ize
612   // data_len_ser = plugin->serialize_attribute_value (attr,
613   //                                                  &attr_ser[1]);
614   data_len_ser = attr->data_size;
615   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
616   attr_ser->data_size = htons (data_len_ser);
617
618   return sizeof(struct Attribute) + strlen (attr->name) + attr->data_size;
619 }
620
621
622 /**
623  * Deserialize an attribute
624  *
625  * @param data the serialized attribute
626  * @param data_size the length of the serialized data
627  *
628  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
629  */
630 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
631 GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size)
632 {
633   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
634   struct Attribute *attr_ser;
635   size_t data_len;
636   size_t name_len;
637   char *write_ptr;
638
639   if (data_size < sizeof(struct Attribute))
640     return NULL;
641
642   attr_ser = (struct Attribute *) data;
643   data_len = ntohs (attr_ser->data_size);
644   name_len = ntohs (attr_ser->name_len);
645   if (data_size < sizeof(struct Attribute) + data_len + name_len)
646   {
647     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
648                 "Buffer too small to deserialize\n");
649     return NULL;
650   }
651   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
652                         + data_len + name_len + 1);
653   attr->type = ntohs (attr_ser->attribute_type);
654   attr->version = ntohl (attr_ser->attribute_version);
655   attr->id = GNUNET_ntohll (attr_ser->attribute_id);
656   attr->data_size = data_len;
657
658   write_ptr = (char *) &attr[1];
659   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
660   write_ptr[name_len] = '\0';
661   attr->name = write_ptr;
662
663   write_ptr += name_len + 1;
664   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
665   attr->data = write_ptr;
666   return attr;
667 }
668
669
670 /**
671  * Get required size for serialization buffer
672  *
673  * @param attr the attestation to serialize
674  * @return the required buffer size
675  */
676 size_t
677 GNUNET_RECLAIM_ATTESTATION_serialize_get_size (
678   const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr)
679 {
680   return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
681 }
682
683 /**
684  * Serialize an attestation
685  *
686  * @param attr the attestation to serialize
687  * @param result the serialized attestation
688  * @return length of serialized data
689  */
690 size_t
691 GNUNET_RECLAIM_ATTESTATION_serialize (
692   const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
693   char *result)
694 {
695   size_t data_len_ser;
696   size_t name_len;
697   struct Attestation *attr_ser;
698   char *write_ptr;
699
700   attr_ser = (struct Attestation *) result;
701   attr_ser->attestation_type = htons (attr->type);
702   attr_ser->attestation_type = htonl (attr->version);
703   attr_ser->attestation_type = GNUNET_htonll (attr->id);
704   name_len = strlen (attr->name);
705   attr_ser->name_len = htons (name_len);
706   write_ptr = (char *) &attr_ser[1];
707   GNUNET_memcpy (write_ptr, attr->name, name_len);
708   write_ptr += name_len;
709   // TODO plugin-ize
710   // data_len_ser = plugin->serialize_attribute_value (attr,
711   //                                                  &attr_ser[1]);
712   data_len_ser = attr->data_size;
713   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
714   attr_ser->data_size = htons (data_len_ser);
715
716   return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size;
717 }
718
719 /**
720  * Deserialize an attestation
721  *
722  * @param data the serialized attestation
723  * @param data_size the length of the serialized data
724  *
725  * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
726  */
727 struct GNUNET_RECLAIM_ATTESTATION_Claim *
728 GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size)
729 {
730   struct GNUNET_RECLAIM_ATTESTATION_Claim *attr;
731   struct Attestation *attr_ser;
732   size_t data_len;
733   size_t name_len;
734   char *write_ptr;
735
736   if (data_size < sizeof(struct Attestation))
737     return NULL;
738
739   attr_ser = (struct Attestation *) data;
740   data_len = ntohs (attr_ser->data_size);
741   name_len = ntohs (attr_ser->name_len);
742   if (data_size < sizeof(struct Attestation) + data_len + name_len)
743   {
744     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
745                 "Buffer too small to deserialize\n");
746     return NULL;
747   }
748   attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim)
749                         + data_len + name_len + 1);
750   attr->type = ntohs (attr_ser->attestation_type);
751   attr->version = ntohl (attr_ser->attestation_version);
752   attr->id = GNUNET_ntohll (attr_ser->attestation_id);
753   attr->data_size = data_len;
754
755   write_ptr = (char *) &attr[1];
756   GNUNET_memcpy (write_ptr, &attr_ser[1], name_len);
757   write_ptr[name_len] = '\0';
758   attr->name = write_ptr;
759
760   write_ptr += name_len + 1;
761   GNUNET_memcpy (write_ptr, (char *) &attr_ser[1] + name_len, attr->data_size);
762   attr->data = write_ptr;
763   return attr;
764 }
765
766 /* end of reclaim_attribute.c */