tighten formatting rules
[oweals/gnunet.git] / src / abd / abd_serialization.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013, 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 /**
23  * @file abd/abd_serialization.c
24  * @brief API to serialize and deserialize delegation chains
25  * and abds
26  * @author Martin Schanzenbach
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_abd_service.h"
32 #include "gnunet_signatures.h"
33 #include "abd.h"
34
35 /**
36  * Calculate how many bytes we will need to serialize
37  * the given delegation chain
38  *
39  * @param ds_count number of delegation chain entries
40  * @param dsr array of #GNUNET_ABD_DelegationSet
41  * @return the required size to serialize
42  */
43 size_t
44 GNUNET_ABD_delegation_set_get_size (
45   unsigned int ds_count,
46   const struct GNUNET_ABD_DelegationSet *dsr)
47 {
48   unsigned int i;
49   size_t ret;
50
51   ret = sizeof (struct DelegationRecordData) * (ds_count);
52
53   for (i = 0; i < ds_count; i++)
54   {
55     GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
56     ret += dsr[i].subject_attribute_len;
57   }
58   return ret;
59 }
60
61
62 /**
63  * Serizalize the given delegation chain entries and abd
64  *
65  * @param d_count number of delegation chain entries
66  * @param dsr array of #GNUNET_ABD_DelegationSet
67  * @param dest_size size of the destination
68  * @param dest where to store the result
69  * @return the size of the data, -1 on failure
70  */
71 ssize_t
72 GNUNET_ABD_delegation_set_serialize (
73   unsigned int d_count,
74   const struct GNUNET_ABD_DelegationSet *dsr,
75   size_t dest_size,
76   char *dest)
77 {
78   struct DelegationRecordData rec;
79   unsigned int i;
80   size_t off;
81
82   off = 0;
83   for (i = 0; i < d_count; i++)
84   {
85     rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
86     rec.subject_key = dsr[i].subject_key;
87     if (off + sizeof (rec) > dest_size)
88       return -1;
89     GNUNET_memcpy (&dest[off], &rec, sizeof (rec));
90     off += sizeof (rec);
91     if (0 == dsr[i].subject_attribute_len)
92       continue;
93     if (off + dsr[i].subject_attribute_len > dest_size)
94       return -1;
95     GNUNET_memcpy (&dest[off],
96                    dsr[i].subject_attribute,
97                    dsr[i].subject_attribute_len);
98     off += dsr[i].subject_attribute_len;
99   }
100   return off;
101 }
102
103
104 /**
105  * Deserialize the given destination
106  *
107  * @param len size of the serialized delegation chain and cred
108  * @param src the serialized data
109  * @param d_count the number of delegation chain entries
110  * @param dsr where to put the delegation chain entries
111  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
112  */
113 int
114 GNUNET_ABD_delegation_set_deserialize (
115   size_t len,
116   const char *src,
117   unsigned int d_count,
118   struct GNUNET_ABD_DelegationSet *dsr)
119 {
120   struct DelegationRecordData rec;
121   unsigned int i;
122   size_t off;
123
124   off = 0;
125   for (i = 0; i < d_count; i++)
126   {
127     if (off + sizeof (rec) > len)
128       return GNUNET_SYSERR;
129     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
130     dsr[i].subject_key = rec.subject_key;
131     off += sizeof (rec);
132     dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
133     if (off + dsr[i].subject_attribute_len > len)
134       return GNUNET_SYSERR;
135     dsr[i].subject_attribute = (char *) &src[off];
136     off += dsr[i].subject_attribute_len;
137   }
138   return GNUNET_OK;
139 }
140
141
142 /**
143  * Calculate how many bytes we will need to serialize
144  * the abds
145  *
146  * @param c_count number of abd entries
147  * @param cd a #GNUNET_ABD_Credential
148  * @return the required size to serialize
149  */
150 size_t
151 GNUNET_ABD_delegates_get_size (
152   unsigned int c_count,
153   const struct GNUNET_ABD_Delegate *cd)
154 {
155   unsigned int i;
156   size_t ret;
157
158   ret = sizeof (struct DelegateEntry) * (c_count);
159
160   for (i = 0; i < c_count; i++)
161   {
162     GNUNET_assert ((ret + cd[i].issuer_attribute_len
163                     + cd[i].subject_attribute_len) >= ret);
164     // subject_attribute_len should be 0
165     ret += cd[i].issuer_attribute_len + cd[i].subject_attribute_len;
166   }
167   return ret;
168 }
169
170
171 /**
172  * Serizalize the given abds
173  *
174  * @param c_count number of abd entries
175  * @param cd a #GNUNET_ABD_Credential
176  * @param dest_size size of the destination
177  * @param dest where to store the result
178  * @return the size of the data, -1 on failure
179  */
180 ssize_t
181 GNUNET_ABD_delegates_serialize (
182   unsigned int c_count,
183   const struct GNUNET_ABD_Delegate *cd,
184   size_t dest_size,
185   char *dest)
186 {
187   struct DelegateEntry c_rec;
188   unsigned int i;
189   size_t off;
190
191   off = 0;
192   for (i = 0; i < c_count; i++)
193   {
194     // c_rec.subject_attribute_len = htonl ((uint32_t) cd[i].subject_attribute_len);
195     c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
196     c_rec.issuer_key = cd[i].issuer_key;
197     c_rec.subject_key = cd[i].subject_key;
198     c_rec.signature = cd[i].signature;
199     c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE);
200     c_rec.purpose.size =
201       htonl ((sizeof (struct DelegateEntry) + cd[i].issuer_attribute_len)
202              - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
203     c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
204     if (off + sizeof (c_rec) > dest_size)
205       return -1;
206     GNUNET_memcpy (&dest[off], &c_rec, sizeof (c_rec));
207     off += sizeof (c_rec);
208     if (off + cd[i].issuer_attribute_len > dest_size)
209       return -1;
210     GNUNET_memcpy (&dest[off],
211                    cd[i].issuer_attribute,
212                    cd[i].issuer_attribute_len);
213     off += cd[i].issuer_attribute_len;
214   }
215
216   return off;
217 }
218
219
220 /**
221  * Deserialize the given destination
222  *
223  * @param len size of the serialized creds
224  * @param src the serialized data
225  * @param c_count the number of abd entries
226  * @param cd where to put the abd data
227  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
228  */
229 int
230 GNUNET_ABD_delegates_deserialize (size_t len,
231                                   const char *src,
232                                   unsigned int c_count,
233                                   struct GNUNET_ABD_Delegate *cd)
234 {
235   struct DelegateEntry c_rec;
236   unsigned int i;
237   size_t off;
238
239   off = 0;
240   for (i = 0; i < c_count; i++)
241   {
242     if (off + sizeof (c_rec) > len)
243       return GNUNET_SYSERR;
244     GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
245     cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
246     cd[i].issuer_key = c_rec.issuer_key;
247     cd[i].subject_key = c_rec.subject_key;
248     cd[i].signature = c_rec.signature;
249     cd[i].expiration.abs_value_us = GNUNET_ntohll (c_rec.expiration);
250     off += sizeof (c_rec);
251     if (off + cd[i].issuer_attribute_len > len)
252       return GNUNET_SYSERR;
253     cd[i].issuer_attribute = &src[off];
254     off += cd[i].issuer_attribute_len;
255     cd[i].subject_attribute_len = 0;
256   }
257   return GNUNET_OK;
258 }
259
260
261 /**
262  * Calculate how many bytes we will need to serialize
263  * the given delegation chain and abd
264  *
265  * @param d_count number of delegation chain entries
266  * @param dd array of #GNUNET_ABD_Delegation
267  * @param c_count number of abd entries
268  * @param cd a #GNUNET_ABD_Credential
269  * @return the required size to serialize
270  */
271 size_t
272 GNUNET_ABD_delegation_chain_get_size (
273   unsigned int d_count,
274   const struct GNUNET_ABD_Delegation *dd,
275   unsigned int c_count,
276   const struct GNUNET_ABD_Delegate *cd)
277 {
278   unsigned int i;
279   size_t ret;
280
281   ret = sizeof (struct ChainEntry) * (d_count);
282
283   for (i = 0; i < d_count; i++)
284   {
285     GNUNET_assert (
286       (ret + dd[i].issuer_attribute_len + dd[i].subject_attribute_len) >= ret);
287     ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
288   }
289   return ret + GNUNET_ABD_delegates_get_size (c_count, cd);
290 }
291
292
293 /**
294  * Serizalize the given delegation chain entries and abd
295  *
296  * @param d_count number of delegation chain entries
297  * @param dd array of #GNUNET_ABD_Delegation
298  * @param c_count number of abd entries
299  * @param cd a #GNUNET_ABD_Credential
300  * @param dest_size size of the destination
301  * @param dest where to store the result
302  * @return the size of the data, -1 on failure
303  */
304 ssize_t
305 GNUNET_ABD_delegation_chain_serialize (
306   unsigned int d_count,
307   const struct GNUNET_ABD_Delegation *dd,
308   unsigned int c_count,
309   const struct GNUNET_ABD_Delegate *cd,
310   size_t dest_size,
311   char *dest)
312 {
313   struct ChainEntry rec;
314   unsigned int i;
315   size_t off;
316
317   off = 0;
318   for (i = 0; i < d_count; i++)
319   {
320     rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
321     rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
322     rec.issuer_key = dd[i].issuer_key;
323     rec.subject_key = dd[i].subject_key;
324     if (off + sizeof (rec) > dest_size)
325       return -1;
326     GNUNET_memcpy (&dest[off], &rec, sizeof (rec));
327     off += sizeof (rec);
328     if (off + dd[i].issuer_attribute_len > dest_size)
329       return -1;
330     GNUNET_memcpy (&dest[off],
331                    dd[i].issuer_attribute,
332                    dd[i].issuer_attribute_len);
333     off += dd[i].issuer_attribute_len;
334     if (0 == dd[i].subject_attribute_len)
335       continue;
336     if (off + dd[i].subject_attribute_len > dest_size)
337       return -1;
338     GNUNET_memcpy (&dest[off],
339                    dd[i].subject_attribute,
340                    dd[i].subject_attribute_len);
341     off += dd[i].subject_attribute_len;
342   }
343   return off + GNUNET_ABD_delegates_serialize (c_count,
344                                                cd,
345                                                dest_size - off,
346                                                &dest[off]);
347 }
348
349
350 /**
351  * Deserialize the given destination
352  *
353  * @param len size of the serialized delegation chain and cred
354  * @param src the serialized data
355  * @param d_count the number of delegation chain entries
356  * @param dd where to put the delegation chain entries
357  * @param c_count the number of abd entries
358  * @param cd where to put the abd data
359  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
360  */
361 int
362 GNUNET_ABD_delegation_chain_deserialize (
363   size_t len,
364   const char *src,
365   unsigned int d_count,
366   struct GNUNET_ABD_Delegation *dd,
367   unsigned int c_count,
368   struct GNUNET_ABD_Delegate *cd)
369 {
370   struct ChainEntry rec;
371   unsigned int i;
372   size_t off;
373
374   off = 0;
375   for (i = 0; i < d_count; i++)
376   {
377     if (off + sizeof (rec) > len)
378       return GNUNET_SYSERR;
379     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
380     dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
381     dd[i].issuer_key = rec.issuer_key;
382     dd[i].subject_key = rec.subject_key;
383     off += sizeof (rec);
384     if (off + dd[i].issuer_attribute_len > len)
385       return GNUNET_SYSERR;
386     dd[i].issuer_attribute = &src[off];
387     off += dd[i].issuer_attribute_len;
388     dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
389     if (off + dd[i].subject_attribute_len > len)
390       return GNUNET_SYSERR;
391     dd[i].subject_attribute = &src[off];
392     off += dd[i].subject_attribute_len;
393   }
394   return GNUNET_ABD_delegates_deserialize (len - off,
395                                            &src[off],
396                                            c_count,
397                                            cd);
398 }
399
400
401 int
402 GNUNET_ABD_delegate_serialize (struct GNUNET_ABD_Delegate *dele,
403                                char **data)
404 {
405   size_t size;
406   struct DelegateEntry *cdata;
407   int attr_len;
408
409   // +1 for \0
410   if (0 == dele->subject_attribute_len)
411   {
412     attr_len = dele->issuer_attribute_len + 1;
413   }
414   else
415   {
416     attr_len = dele->issuer_attribute_len + dele->subject_attribute_len + 2;
417   }
418   size = sizeof (struct DelegateEntry) + attr_len;
419
420   char tmp_str[attr_len];
421   GNUNET_memcpy (tmp_str, dele->issuer_attribute, dele->issuer_attribute_len);
422   if (0 != dele->subject_attribute_len)
423   {
424     tmp_str[dele->issuer_attribute_len] = '\0';
425     GNUNET_memcpy (tmp_str + dele->issuer_attribute_len + 1,
426                    dele->subject_attribute,
427                    dele->subject_attribute_len);
428   }
429   tmp_str[attr_len - 1] = '\0';
430
431   *data = GNUNET_malloc (size);
432   cdata = (struct DelegateEntry *) *data;
433   cdata->subject_key = dele->subject_key;
434   cdata->issuer_key = dele->issuer_key;
435   cdata->expiration = GNUNET_htonll (dele->expiration.abs_value_us);
436   cdata->signature = dele->signature;
437   cdata->issuer_attribute_len = htonl (dele->issuer_attribute_len + 1);
438   if (0 == dele->subject_attribute_len)
439   {
440     cdata->subject_attribute_len = htonl (0);
441   }
442   else
443   {
444     cdata->subject_attribute_len = htonl (dele->subject_attribute_len + 1);
445   }
446   cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE);
447   cdata->purpose.size =
448     htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
449
450   GNUNET_memcpy (&cdata[1], tmp_str, attr_len);
451
452   if (GNUNET_OK !=
453       GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
454                                   &cdata->purpose,
455                                   &cdata->signature,
456                                   &cdata->issuer_key))
457   {
458     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Serialize: Invalid delegate\n");
459     return 0;
460   }
461   return size;
462 }
463
464
465 struct GNUNET_ABD_Delegate *
466 GNUNET_ABD_delegate_deserialize (const char *data, size_t data_size)
467 {
468   struct GNUNET_ABD_Delegate *dele;
469   struct DelegateEntry *cdata;
470   char *attr_combo_str;
471
472   if (data_size < sizeof (struct DelegateEntry))
473     return NULL;
474   cdata = (struct DelegateEntry *) data;
475   if (GNUNET_OK !=
476       GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
477                                   &cdata->purpose,
478                                   &cdata->signature,
479                                   &cdata->issuer_key))
480   {
481     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Deserialize: Invalid delegate\n");
482     return NULL;
483   }
484   attr_combo_str = (char *) &cdata[1];
485   int iss_len = ntohl (cdata->issuer_attribute_len);
486   int sub_len = ntohl (cdata->subject_attribute_len);
487   int attr_combo_len = iss_len + sub_len;
488
489   dele =
490     GNUNET_malloc (sizeof (struct GNUNET_ABD_Delegate) + attr_combo_len);
491
492   dele->issuer_key = cdata->issuer_key;
493   dele->subject_key = cdata->subject_key;
494   GNUNET_memcpy (&dele[1], attr_combo_str, attr_combo_len);
495   dele->signature = cdata->signature;
496
497   // Set the pointers for the attributes
498   dele->issuer_attribute = (char *) &dele[1];
499   dele->issuer_attribute_len = iss_len;
500   dele->subject_attribute_len = sub_len;
501   if (0 == sub_len)
502   {
503     dele->subject_attribute = NULL;
504   }
505   else
506   {
507     dele->subject_attribute = (char *) &dele[1] + iss_len;
508   }
509
510   dele->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
511
512   return dele;
513 }
514
515
516 /* end of abd_serialization.c */