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