uncrustify as demanded.
[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 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 }
283
284 /**
285  * Serizalize the given delegation chain entries and credential
286  *
287  * @param d_count number of delegation chain entries
288  * @param dd array of #GNUNET_CREDENTIAL_Delegation
289  * @param c_count number of credential entries
290  * @param cd a #GNUNET_CREDENTIAL_Credential
291  * @param dest_size size of the destination
292  * @param dest where to store the result
293  * @return the size of the data, -1 on failure
294  */
295 ssize_t
296 GNUNET_CREDENTIAL_delegation_chain_serialize(unsigned int d_count,
297                                              const struct GNUNET_CREDENTIAL_Delegation *dd,
298                                              unsigned int c_count,
299                                              const struct GNUNET_CREDENTIAL_Credential *cd,
300                                              size_t dest_size,
301                                              char *dest)
302 {
303   struct ChainEntry rec;
304   unsigned int i;
305   size_t off;
306
307   off = 0;
308   for (i = 0; i < d_count; i++)
309     {
310       rec.issuer_attribute_len = htonl((uint32_t)dd[i].issuer_attribute_len);
311       rec.subject_attribute_len = htonl((uint32_t)dd[i].subject_attribute_len);
312       rec.issuer_key = dd[i].issuer_key;
313       rec.subject_key = dd[i].subject_key;
314       if (off + sizeof(rec) > dest_size)
315         return -1;
316       GNUNET_memcpy(&dest[off],
317                     &rec,
318                     sizeof(rec));
319       off += sizeof(rec);
320       if (off + dd[i].issuer_attribute_len > dest_size)
321         return -1;
322       GNUNET_memcpy(&dest[off],
323                     dd[i].issuer_attribute,
324                     dd[i].issuer_attribute_len);
325       off += dd[i].issuer_attribute_len;
326       if (0 == dd[i].subject_attribute_len)
327         continue;
328       if (off + dd[i].subject_attribute_len > dest_size)
329         return -1;
330       GNUNET_memcpy(&dest[off],
331                     dd[i].subject_attribute,
332                     dd[i].subject_attribute_len);
333       off += dd[i].subject_attribute_len;
334     }
335   return off + GNUNET_CREDENTIAL_credentials_serialize(c_count,
336                                                        cd,
337                                                        dest_size - off,
338                                                        &dest[off]);
339 }
340
341
342 /**
343  * Deserialize the given destination
344  *
345  * @param len size of the serialized delegation chain and cred
346  * @param src the serialized data
347  * @param d_count the number of delegation chain entries
348  * @param dd where to put the delegation chain entries
349  * @param c_count the number of credential entries
350  * @param cd where to put the credential data
351  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
352  */
353 int
354 GNUNET_CREDENTIAL_delegation_chain_deserialize(size_t len,
355                                                const char *src,
356                                                unsigned int d_count,
357                                                struct GNUNET_CREDENTIAL_Delegation *dd,
358                                                unsigned int c_count,
359                                                struct GNUNET_CREDENTIAL_Credential *cd)
360 {
361   struct ChainEntry rec;
362   unsigned int i;
363   size_t off;
364
365   off = 0;
366   for (i = 0; i < d_count; i++)
367     {
368       if (off + sizeof(rec) > len)
369         return GNUNET_SYSERR;
370       GNUNET_memcpy(&rec, &src[off], sizeof(rec));
371       dd[i].issuer_attribute_len = ntohl((uint32_t)rec.issuer_attribute_len);
372       dd[i].issuer_key = rec.issuer_key;
373       dd[i].subject_key = rec.subject_key;
374       off += sizeof(rec);
375       if (off + dd[i].issuer_attribute_len > len)
376         return GNUNET_SYSERR;
377       dd[i].issuer_attribute = &src[off];
378       off += dd[i].issuer_attribute_len;
379       dd[i].subject_attribute_len = ntohl((uint32_t)rec.subject_attribute_len);
380       if (off + dd[i].subject_attribute_len > len)
381         return GNUNET_SYSERR;
382       dd[i].subject_attribute = &src[off];
383       off += dd[i].subject_attribute_len;
384     }
385   return GNUNET_CREDENTIAL_credentials_deserialize(len - off,
386                                                    &src[off],
387                                                    c_count,
388                                                    cd);
389 }
390 int
391 GNUNET_CREDENTIAL_credential_serialize(struct GNUNET_CREDENTIAL_Credential *cred,
392                                        char **data)
393 {
394   size_t size;
395   struct CredentialEntry *cdata;
396
397   size = sizeof(struct CredentialEntry) + strlen(cred->issuer_attribute) + 1;
398   *data = GNUNET_malloc(size);
399   cdata = (struct CredentialEntry*)*data;
400   cdata->subject_key = cred->subject_key;
401   cdata->issuer_key = cred->issuer_key;
402   cdata->expiration = GNUNET_htonll(cred->expiration.abs_value_us);
403   cdata->signature = cred->signature;
404   cdata->issuer_attribute_len = htonl(strlen(cred->issuer_attribute) + 1);
405   cdata->purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
406   cdata->purpose.size = htonl(size - sizeof(struct GNUNET_CRYPTO_EcdsaSignature));
407   GNUNET_memcpy(&cdata[1],
408                 cred->issuer_attribute,
409                 strlen(cred->issuer_attribute));
410
411   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
412                                               &cdata->purpose,
413                                               &cdata->signature,
414                                               &cdata->issuer_key))
415     {
416       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
417                  "Invalid credential\n");
418       //return NULL;
419     }
420   return size;
421 }
422
423 struct GNUNET_CREDENTIAL_Credential*
424 GNUNET_CREDENTIAL_credential_deserialize(const char* data,
425                                          size_t data_size)
426 {
427   struct GNUNET_CREDENTIAL_Credential *cred;
428   struct CredentialEntry *cdata;
429   char *issuer_attribute;
430
431   if (data_size < sizeof(struct CredentialEntry))
432     return NULL;
433   cdata = (struct CredentialEntry*)data;
434   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
435                                               &cdata->purpose,
436                                               &cdata->signature,
437                                               &cdata->issuer_key))
438     {
439       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
440                  "Invalid credential\n");
441       //return NULL;
442     }
443   issuer_attribute = (char*)&cdata[1];
444
445   cred = GNUNET_malloc(sizeof(struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
446
447   cred->issuer_key = cdata->issuer_key;
448   cred->subject_key = cdata->subject_key;
449   GNUNET_memcpy(&cred[1],
450                 issuer_attribute,
451                 ntohl(cdata->issuer_attribute_len));
452   cred->signature = cdata->signature;
453   cred->issuer_attribute = (char*)&cred[1];
454   cred->expiration.abs_value_us = GNUNET_ntohll(cdata->expiration);
455   return cred;
456 }
457
458
459 /* end of credential_serialization.c */