2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
23 * @file credential/credential_serialization.c
24 * @brief API to serialize and deserialize delegation chains
26 * @author Martin Schanzenbach
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"
36 * Calculate how many bytes we will need to serialize
37 * the given delegation chain
39 * @param ds_count number of delegation chain entries
40 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
41 * @return the required size to serialize
44 GNUNET_CREDENTIAL_delegation_set_get_size (
45 unsigned int ds_count,
46 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
51 ret = sizeof (struct DelegationRecordData) * (ds_count);
53 for (i = 0; i < ds_count; i++)
55 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
56 ret += dsr[i].subject_attribute_len;
62 * Serizalize the given delegation chain entries and credential
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
71 GNUNET_CREDENTIAL_delegation_set_serialize (
73 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
77 struct DelegationRecordData rec;
82 for (i = 0; i < d_count; i++)
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)
88 GNUNET_memcpy (&dest[off], &rec, sizeof (rec));
90 if (0 == dsr[i].subject_attribute_len)
92 if (off + dsr[i].subject_attribute_len > dest_size)
94 GNUNET_memcpy (&dest[off],
95 dsr[i].subject_attribute,
96 dsr[i].subject_attribute_len);
97 off += dsr[i].subject_attribute_len;
104 * Deserialize the given destination
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
113 GNUNET_CREDENTIAL_delegation_set_deserialize (
116 unsigned int d_count,
117 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
119 struct DelegationRecordData rec;
124 for (i = 0; i < d_count; i++)
126 if (off + sizeof (rec) > len)
127 return GNUNET_SYSERR;
128 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
129 dsr[i].subject_key = rec.subject_key;
131 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
132 if (off + dsr[i].subject_attribute_len > len)
133 return GNUNET_SYSERR;
134 dsr[i].subject_attribute = (char *) &src[off];
135 off += dsr[i].subject_attribute_len;
142 * Calculate how many bytes we will need to serialize
145 * @param c_count number of credential entries
146 * @param cd a #GNUNET_CREDENTIAL_Credential
147 * @return the required size to serialize
150 GNUNET_CREDENTIAL_delegates_get_size (
151 unsigned int c_count,
152 const struct GNUNET_CREDENTIAL_Delegate *cd)
157 ret = sizeof (struct DelegateEntry) * (c_count);
159 for (i = 0; i < c_count; i++)
161 GNUNET_assert ((ret + cd[i].issuer_attribute_len + cd[i].subject_attribute_len) >= ret);
162 // subject_attribute_len should be 0
163 ret += cd[i].issuer_attribute_len + cd[i].subject_attribute_len;
168 * Serizalize the given credentials
170 * @param c_count number of credential entries
171 * @param cd a #GNUNET_CREDENTIAL_Credential
172 * @param dest_size size of the destination
173 * @param dest where to store the result
174 * @return the size of the data, -1 on failure
177 GNUNET_CREDENTIAL_delegates_serialize (
178 unsigned int c_count,
179 const struct GNUNET_CREDENTIAL_Delegate *cd,
183 struct DelegateEntry c_rec;
188 for (i = 0; i < c_count; i++)
190 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
191 c_rec.issuer_key = cd[i].issuer_key;
192 c_rec.subject_key = cd[i].subject_key;
193 c_rec.signature = cd[i].signature;
194 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE);
196 htonl ((sizeof (struct DelegateEntry) + cd[i].issuer_attribute_len) -
197 sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
198 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
199 if (off + sizeof (c_rec) > dest_size)
201 GNUNET_memcpy (&dest[off], &c_rec, sizeof (c_rec));
202 off += sizeof (c_rec);
203 if (off + cd[i].issuer_attribute_len > dest_size)
205 GNUNET_memcpy (&dest[off],
206 cd[i].issuer_attribute,
207 cd[i].issuer_attribute_len);
208 off += cd[i].issuer_attribute_len;
216 * Deserialize the given destination
218 * @param len size of the serialized creds
219 * @param src the serialized data
220 * @param c_count the number of credential entries
221 * @param cd where to put the credential data
222 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
225 GNUNET_CREDENTIAL_delegates_deserialize (size_t len,
227 unsigned int c_count,
228 struct GNUNET_CREDENTIAL_Delegate *cd)
230 struct DelegateEntry c_rec;
235 for (i = 0; i < c_count; i++)
237 if (off + sizeof (c_rec) > len)
238 return GNUNET_SYSERR;
239 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
240 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
241 cd[i].issuer_key = c_rec.issuer_key;
242 cd[i].subject_key = c_rec.subject_key;
243 cd[i].signature = c_rec.signature;
244 cd[i].expiration.abs_value_us = GNUNET_ntohll (c_rec.expiration);
245 off += sizeof (c_rec);
246 if (off + cd[i].issuer_attribute_len > len)
247 return GNUNET_SYSERR;
248 cd[i].issuer_attribute = &src[off];
249 off += cd[i].issuer_attribute_len;
250 cd[i].subject_attribute_len = 0;
257 * Calculate how many bytes we will need to serialize
258 * the given delegation chain and credential
260 * @param d_count number of delegation chain entries
261 * @param dd array of #GNUNET_CREDENTIAL_Delegation
262 * @param c_count number of credential entries
263 * @param cd a #GNUNET_CREDENTIAL_Credential
264 * @return the required size to serialize
267 GNUNET_CREDENTIAL_delegation_chain_get_size (
268 unsigned int d_count,
269 const struct GNUNET_CREDENTIAL_Delegation *dd,
270 unsigned int c_count,
271 const struct GNUNET_CREDENTIAL_Delegate *cd)
276 ret = sizeof (struct ChainEntry) * (d_count);
278 for (i = 0; i < d_count; i++)
281 (ret + dd[i].issuer_attribute_len + dd[i].subject_attribute_len) >= ret);
282 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
284 return ret + GNUNET_CREDENTIAL_delegates_get_size (c_count, cd);
288 * Serizalize the given delegation chain entries and credential
290 * @param d_count number of delegation chain entries
291 * @param dd array of #GNUNET_CREDENTIAL_Delegation
292 * @param c_count number of credential entries
293 * @param cd a #GNUNET_CREDENTIAL_Credential
294 * @param dest_size size of the destination
295 * @param dest where to store the result
296 * @return the size of the data, -1 on failure
299 GNUNET_CREDENTIAL_delegation_chain_serialize (
300 unsigned int d_count,
301 const struct GNUNET_CREDENTIAL_Delegation *dd,
302 unsigned int c_count,
303 const struct GNUNET_CREDENTIAL_Delegate *cd,
307 struct ChainEntry rec;
312 for (i = 0; i < d_count; i++)
314 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
315 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
316 rec.issuer_key = dd[i].issuer_key;
317 rec.subject_key = dd[i].subject_key;
318 if (off + sizeof (rec) > dest_size)
320 GNUNET_memcpy (&dest[off], &rec, sizeof (rec));
322 if (off + dd[i].issuer_attribute_len > dest_size)
324 GNUNET_memcpy (&dest[off],
325 dd[i].issuer_attribute,
326 dd[i].issuer_attribute_len);
327 off += dd[i].issuer_attribute_len;
328 if (0 == dd[i].subject_attribute_len)
330 if (off + dd[i].subject_attribute_len > dest_size)
332 GNUNET_memcpy (&dest[off],
333 dd[i].subject_attribute,
334 dd[i].subject_attribute_len);
335 off += dd[i].subject_attribute_len;
337 return off + GNUNET_CREDENTIAL_delegates_serialize (c_count,
345 * Deserialize the given destination
347 * @param len size of the serialized delegation chain and cred
348 * @param src the serialized data
349 * @param d_count the number of delegation chain entries
350 * @param dd where to put the delegation chain entries
351 * @param c_count the number of credential entries
352 * @param cd where to put the credential data
353 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
356 GNUNET_CREDENTIAL_delegation_chain_deserialize (
359 unsigned int d_count,
360 struct GNUNET_CREDENTIAL_Delegation *dd,
361 unsigned int c_count,
362 struct GNUNET_CREDENTIAL_Delegate *cd)
364 struct ChainEntry rec;
369 for (i = 0; i < d_count; i++)
371 if (off + sizeof (rec) > len)
372 return GNUNET_SYSERR;
373 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
374 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
375 dd[i].issuer_key = rec.issuer_key;
376 dd[i].subject_key = rec.subject_key;
378 if (off + dd[i].issuer_attribute_len > len)
379 return GNUNET_SYSERR;
380 dd[i].issuer_attribute = &src[off];
381 off += dd[i].issuer_attribute_len;
382 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
383 if (off + dd[i].subject_attribute_len > len)
384 return GNUNET_SYSERR;
385 dd[i].subject_attribute = &src[off];
386 off += dd[i].subject_attribute_len;
388 return GNUNET_CREDENTIAL_delegates_deserialize (len - off,
395 GNUNET_CREDENTIAL_delegate_serialize (struct GNUNET_CREDENTIAL_Delegate *dele,
399 struct DelegateEntry *cdata;
403 if (0 == dele->subject_attribute_len)
405 attr_len = dele->issuer_attribute_len + 1;
409 attr_len = dele->issuer_attribute_len + dele->subject_attribute_len + 2;
411 size = sizeof (struct DelegateEntry) + attr_len;
413 char tmp_str[attr_len];
414 GNUNET_memcpy (tmp_str, dele->issuer_attribute, dele->issuer_attribute_len);
415 if (0 != dele->subject_attribute_len)
417 tmp_str[dele->issuer_attribute_len] = '\0';
418 GNUNET_memcpy (tmp_str + dele->issuer_attribute_len + 1,
419 dele->subject_attribute,
420 dele->subject_attribute_len);
422 tmp_str[attr_len - 1] = '\0';
424 *data = GNUNET_malloc (size);
425 cdata = (struct DelegateEntry *) *data;
426 cdata->subject_key = dele->subject_key;
427 cdata->issuer_key = dele->issuer_key;
428 cdata->expiration = GNUNET_htonll (dele->expiration.abs_value_us);
429 cdata->signature = dele->signature;
430 cdata->issuer_attribute_len = htonl (dele->issuer_attribute_len + 1);
431 if (0 == dele->subject_attribute_len)
433 cdata->subject_attribute_len = htonl (0);
437 cdata->subject_attribute_len = htonl (dele->subject_attribute_len + 1);
439 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DELEGATE);
440 cdata->purpose.size =
441 htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
443 GNUNET_memcpy (&cdata[1], tmp_str, attr_len);
446 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
451 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Serialize: Invalid delegate\n");
457 struct GNUNET_CREDENTIAL_Delegate *
458 GNUNET_CREDENTIAL_delegate_deserialize (const char *data, size_t data_size)
460 struct GNUNET_CREDENTIAL_Delegate *dele;
461 struct DelegateEntry *cdata;
462 char *attr_combo_str;
464 if (data_size < sizeof (struct DelegateEntry))
466 cdata = (struct DelegateEntry *) data;
468 GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_DELEGATE,
473 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Deserialize: Invalid delegate\n");
476 attr_combo_str = (char *) &cdata[1];
477 int iss_len = ntohl (cdata->issuer_attribute_len);
478 int sub_len = ntohl (cdata->subject_attribute_len);
479 int attr_combo_len = iss_len + sub_len;
482 GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Delegate) + attr_combo_len);
484 dele->issuer_key = cdata->issuer_key;
485 dele->subject_key = cdata->subject_key;
486 GNUNET_memcpy (&dele[1], attr_combo_str, attr_combo_len);
487 dele->signature = cdata->signature;
489 // Set the pointers for the attributes
490 dele->issuer_attribute = (char *) &dele[1];
491 dele->issuer_attribute_len = iss_len;
492 dele->subject_attribute_len = sub_len;
495 dele->subject_attribute = NULL;
499 dele->subject_attribute = (char *) &dele[1] + iss_len;
502 dele->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
507 /* end of credential_serialization.c */