trying again to fix test_service timeout on v6 failure
[oweals/gnunet.git] / src / credential / credential_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
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21
22 /**
23  * @file credential/credential_serialization.c
24  * @brief API to serialize and deserialize delegation chains 
25  * and credentials
26  * @author Martin Schanzenbach
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_credential_service.h"
32 #include "gnunet_signatures.h"
33 #include "credential.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_CREDENTIAL_DelegationSet
41  * @return the required size to serialize
42  */
43 size_t
44 GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
45                                            const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
46 {
47   unsigned int i;
48   size_t ret;
49
50   ret = sizeof (struct DelegationRecordData) * (ds_count);
51
52   for (i=0; i<ds_count;i++)
53   {
54     GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
55     ret += dsr[i].subject_attribute_len;
56   }
57   return ret;
58 }
59
60 /**
61  * Serizalize the given delegation chain entries and credential
62  *
63  * @param d_count number of delegation chain entries
64  * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
65  * @param dest_size size of the destination
66  * @param dest where to store the result
67  * @return the size of the data, -1 on failure
68  */
69 ssize_t
70 GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
71                                             const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
72                                             size_t dest_size,
73                                             char *dest)
74 {
75   struct DelegationRecordData rec;
76   unsigned int i;
77   size_t off;
78
79   off = 0;
80   for (i=0;i<d_count;i++)
81   {
82     rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
83     rec.subject_key = dsr[i].subject_key;
84     if (off + sizeof (rec) > dest_size)
85       return -1;
86     GNUNET_memcpy (&dest[off],
87                    &rec,
88                    sizeof (rec));
89     off += sizeof (rec);
90     if (0 == dsr[i].subject_attribute_len)
91       continue;
92     if (off + dsr[i].subject_attribute_len > dest_size)
93       return -1;
94     GNUNET_memcpy (&dest[off],
95                    dsr[i].subject_attribute,
96                    dsr[i].subject_attribute_len);
97     off += dsr[i].subject_attribute_len;
98   }
99   return off;
100 }
101
102
103 /**
104  * Deserialize the given destination
105  *
106  * @param len size of the serialized delegation chain and cred
107  * @param src the serialized data
108  * @param d_count the number of delegation chain entries
109  * @param dsr where to put the delegation chain entries
110  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
111  */
112 int
113 GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
114                                               const char *src,
115                                               unsigned int d_count,
116                                               struct GNUNET_CREDENTIAL_DelegationSet *dsr)
117 {
118   struct DelegationRecordData rec;
119   unsigned int i;
120   size_t off;
121
122   off = 0;
123   for (i=0;i<d_count;i++)
124   {
125     if (off + sizeof (rec) > len)
126       return GNUNET_SYSERR;
127     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
128     dsr[i].subject_key = rec.subject_key;
129     off += sizeof (rec);
130     dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
131     if (off + dsr[i].subject_attribute_len > len)
132       return GNUNET_SYSERR;
133     dsr[i].subject_attribute = (char*)&src[off];
134     off += dsr[i].subject_attribute_len;
135   }
136   return GNUNET_OK;
137 }
138
139
140 /**
141  * Calculate how many bytes we will need to serialize
142  * the credentials
143  *
144  * @param c_count number of credential entries
145  * @param cd a #GNUNET_CREDENTIAL_Credential
146  * @return the required size to serialize
147  */
148 size_t
149 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
150                                         const struct GNUNET_CREDENTIAL_Credential *cd)
151 {
152   unsigned int i;
153   size_t ret;
154
155   ret = sizeof (struct CredentialEntry) * (c_count);
156
157   for (i=0; i<c_count;i++)
158   {
159     GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
160     ret += cd[i].issuer_attribute_len;
161   }
162   return ret;
163 }
164 /**
165  * Serizalize the given credentials
166  *
167  * @param c_count number of credential entries
168  * @param cd a #GNUNET_CREDENTIAL_Credential
169  * @param dest_size size of the destination
170  * @param dest where to store the result
171  * @return the size of the data, -1 on failure
172  */
173 ssize_t
174 GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
175                                          const struct GNUNET_CREDENTIAL_Credential *cd,
176                                          size_t dest_size,
177                                          char *dest)
178 {
179   struct CredentialEntry c_rec;
180   unsigned int i;
181   size_t off;
182
183   off = 0;
184   for (i=0;i<c_count;i++)
185   {
186     c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
187     c_rec.issuer_key = cd[i].issuer_key;
188     c_rec.subject_key = cd[i].subject_key;
189     c_rec.signature = cd[i].signature;
190     c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
191     c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
192     c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
193     if (off + sizeof (c_rec) > dest_size)
194       return -1;
195     GNUNET_memcpy (&dest[off],
196                    &c_rec,
197                    sizeof (c_rec));
198     off += sizeof (c_rec);
199     if (off + cd[i].issuer_attribute_len > dest_size)
200       return -1;
201     GNUNET_memcpy (&dest[off],
202                    cd[i].issuer_attribute,
203                    cd[i].issuer_attribute_len);
204     off += cd[i].issuer_attribute_len;
205   }
206
207   return off;
208 }
209
210
211
212 /**
213  * Deserialize the given destination
214  *
215  * @param len size of the serialized creds
216  * @param src the serialized data
217  * @param c_count the number of credential entries
218  * @param cd where to put the credential data
219  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220  */
221 int
222 GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
223                                            const char *src,
224                                            unsigned int c_count,
225                                            struct GNUNET_CREDENTIAL_Credential *cd)
226 {
227   struct CredentialEntry c_rec;
228   unsigned int i;
229   size_t off;
230
231   off = 0;
232   for (i=0;i<c_count;i++)
233   {
234     if (off + sizeof (c_rec) > len)
235       return GNUNET_SYSERR;
236     GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
237     cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
238     cd[i].issuer_key = c_rec.issuer_key;
239     cd[i].subject_key = c_rec.subject_key;
240     cd[i].signature = c_rec.signature;
241     cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
242     off += sizeof (c_rec);
243     if (off + cd[i].issuer_attribute_len > len)
244       return GNUNET_SYSERR;
245     cd[i].issuer_attribute = &src[off];
246     off += cd[i].issuer_attribute_len;
247   }
248   return GNUNET_OK;
249 }
250
251
252
253 /**
254  * Calculate how many bytes we will need to serialize
255  * the given delegation chain and credential
256  *
257  * @param d_count number of delegation chain entries
258  * @param dd array of #GNUNET_CREDENTIAL_Delegation
259  * @param c_count number of credential entries
260  * @param cd a #GNUNET_CREDENTIAL_Credential
261  * @return the required size to serialize
262  */
263 size_t
264 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
265                                              const struct GNUNET_CREDENTIAL_Delegation *dd,
266                                              unsigned int c_count,
267                                              const struct GNUNET_CREDENTIAL_Credential *cd)
268 {
269   unsigned int i;
270   size_t ret;
271
272   ret = sizeof (struct ChainEntry) * (d_count);
273
274   for (i=0; i<d_count;i++)
275   {
276     GNUNET_assert ((ret +
277                     dd[i].issuer_attribute_len +
278                     dd[i].subject_attribute_len) >= ret);
279     ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
280   }
281   return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
282   return ret;
283 }
284
285 /**
286  * Serizalize the given delegation chain entries and credential
287  *
288  * @param d_count number of delegation chain entries
289  * @param dd array of #GNUNET_CREDENTIAL_Delegation
290  * @param c_count number of credential entries
291  * @param cd a #GNUNET_CREDENTIAL_Credential
292  * @param dest_size size of the destination
293  * @param dest where to store the result
294  * @return the size of the data, -1 on failure
295  */
296 ssize_t
297 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
298                                               const struct GNUNET_CREDENTIAL_Delegation *dd,
299                                               unsigned int c_count,
300                                               const struct GNUNET_CREDENTIAL_Credential *cd,
301                                               size_t dest_size,
302                                               char *dest)
303 {
304   struct ChainEntry rec;
305   unsigned int i;
306   size_t off;
307
308   off = 0;
309   for (i=0;i<d_count;i++)
310   {
311     rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
312     rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
313     rec.issuer_key = dd[i].issuer_key;
314     rec.subject_key = dd[i].subject_key;
315     if (off + sizeof (rec) > dest_size)
316       return -1;
317     GNUNET_memcpy (&dest[off],
318                    &rec,
319                    sizeof (rec));
320     off += sizeof (rec);
321     if (off + dd[i].issuer_attribute_len > dest_size)
322       return -1;
323     GNUNET_memcpy (&dest[off],
324                    dd[i].issuer_attribute,
325                    dd[i].issuer_attribute_len);
326     off += dd[i].issuer_attribute_len;
327     if (0 == dd[i].subject_attribute_len)
328       continue;
329     if (off + dd[i].subject_attribute_len > dest_size)
330       return -1;
331     GNUNET_memcpy (&dest[off],
332                    dd[i].subject_attribute,
333                    dd[i].subject_attribute_len);
334     off += dd[i].subject_attribute_len;
335   }
336   return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
337                                                       cd,
338                                                       dest_size-off,
339                                                       &dest[off]);
340 }
341
342
343 /**
344  * Deserialize the given destination
345  *
346  * @param len size of the serialized delegation chain and cred
347  * @param src the serialized data
348  * @param d_count the number of delegation chain entries
349  * @param dd where to put the delegation chain entries
350  * @param c_count the number of credential entries
351  * @param cd where to put the credential data
352  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
353  */
354 int
355 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
356                                                 const char *src,
357                                                 unsigned int d_count,
358                                                 struct GNUNET_CREDENTIAL_Delegation *dd,
359                                                 unsigned int c_count,
360                                                 struct GNUNET_CREDENTIAL_Credential *cd)
361 {
362   struct ChainEntry rec;
363   unsigned int i;
364   size_t off;
365
366   off = 0;
367   for (i=0;i<d_count;i++)
368   {
369     if (off + sizeof (rec) > len)
370       return GNUNET_SYSERR;
371     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
372     dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
373     dd[i].issuer_key = rec.issuer_key;
374     dd[i].subject_key = rec.subject_key;
375     off += sizeof (rec);
376     if (off + dd[i].issuer_attribute_len > len)
377       return GNUNET_SYSERR;
378     dd[i].issuer_attribute = &src[off];
379     off += dd[i].issuer_attribute_len;
380     dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
381     if (off + dd[i].subject_attribute_len > len)
382       return GNUNET_SYSERR;
383     dd[i].subject_attribute = &src[off];
384     off += dd[i].subject_attribute_len;
385   }
386   return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
387                                                     &src[off],
388                                                     c_count,
389                                                     cd);
390 }
391 int
392 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
393                                         char **data)
394 {
395   size_t size;
396   struct CredentialEntry *cdata;
397
398   size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
399   *data = GNUNET_malloc (size);
400   cdata = (struct CredentialEntry*)*data;
401   cdata->subject_key = cred->subject_key;
402   cdata->issuer_key = cred->issuer_key;
403   cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
404   cdata->signature = cred->signature;
405   cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
406   cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
407   cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
408   GNUNET_memcpy (&cdata[1],
409                  cred->issuer_attribute,
410                  strlen (cred->issuer_attribute));
411
412   if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, 
413                                              &cdata->purpose,
414                                              &cdata->signature,
415                                              &cdata->issuer_key))
416   {
417     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
418                 "Invalid credential\n");
419     //return NULL;
420   }
421   return size;
422 }
423
424 struct GNUNET_CREDENTIAL_Credential*
425 GNUNET_CREDENTIAL_credential_deserialize (const char* data,
426                                           size_t data_size)
427 {
428   struct GNUNET_CREDENTIAL_Credential *cred;
429   struct CredentialEntry *cdata;
430   char *issuer_attribute;
431
432   if (data_size < sizeof (struct CredentialEntry))
433     return NULL;
434   cdata = (struct CredentialEntry*)data;
435   if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL, 
436                                              &cdata->purpose,
437                                              &cdata->signature,
438                                              &cdata->issuer_key))
439   {
440     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
441                 "Invalid credential\n");
442     //return NULL;
443   }
444   issuer_attribute = (char*)&cdata[1];
445
446   cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
447
448   cred->issuer_key = cdata->issuer_key;
449   cred->subject_key = cdata->subject_key;
450   GNUNET_memcpy (&cred[1],
451                  issuer_attribute,
452                  ntohl (cdata->issuer_attribute_len));
453   cred->signature = cdata->signature;
454   cred->issuer_attribute = (char*)&cred[1];
455   cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
456   return cred;
457 }
458
459
460 /* end of credential_serialization.c */