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