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