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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
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 (unsigned int ds_count,
45 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
50 ret = sizeof (struct DelegationRecordData) * (ds_count);
52 for (i=0; i<ds_count;i++)
54 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
55 ret += dsr[i].subject_attribute_len;
61 * Serizalize the given delegation chain entries and credential
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
70 GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
71 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
75 struct DelegationRecordData rec;
80 for (i=0;i<d_count;i++)
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)
86 GNUNET_memcpy (&dest[off],
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 (size_t len,
115 unsigned int d_count,
116 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
118 struct DelegationRecordData rec;
123 for (i=0;i<d_count;i++)
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;
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;
141 * Calculate how many bytes we will need to serialize
144 * @param c_count number of credential entries
145 * @param cd a #GNUNET_CREDENTIAL_Credential
146 * @return the required size to serialize
149 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
150 const struct GNUNET_CREDENTIAL_Credential *cd)
155 ret = sizeof (struct CredentialEntry) * (c_count);
157 for (i=0; i<c_count;i++)
159 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
160 ret += cd[i].issuer_attribute_len;
165 * Serizalize the given credentials
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
174 GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
175 const struct GNUNET_CREDENTIAL_Credential *cd,
179 struct CredentialEntry c_rec;
184 for (i=0;i<c_count;i++)
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)
195 GNUNET_memcpy (&dest[off],
198 off += sizeof (c_rec);
199 if (off + cd[i].issuer_attribute_len > dest_size)
201 GNUNET_memcpy (&dest[off],
202 cd[i].issuer_attribute,
203 cd[i].issuer_attribute_len);
204 off += cd[i].issuer_attribute_len;
213 * Deserialize the given destination
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
222 GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
224 unsigned int c_count,
225 struct GNUNET_CREDENTIAL_Credential *cd)
227 struct CredentialEntry c_rec;
232 for (i=0;i<c_count;i++)
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;
254 * Calculate how many bytes we will need to serialize
255 * the given delegation chain and credential
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
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)
272 ret = sizeof (struct ChainEntry) * (d_count);
274 for (i=0; i<d_count;i++)
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;
281 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
286 * Serizalize the given delegation chain entries and credential
288 * @param d_count number of delegation chain entries
289 * @param dd array of #GNUNET_CREDENTIAL_Delegation
290 * @param c_count number of credential entries
291 * @param cd a #GNUNET_CREDENTIAL_Credential
292 * @param dest_size size of the destination
293 * @param dest where to store the result
294 * @return the size of the data, -1 on failure
297 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
298 const struct GNUNET_CREDENTIAL_Delegation *dd,
299 unsigned int c_count,
300 const struct GNUNET_CREDENTIAL_Credential *cd,
304 struct ChainEntry rec;
309 for (i=0;i<d_count;i++)
311 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
312 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
313 rec.issuer_key = dd[i].issuer_key;
314 rec.subject_key = dd[i].subject_key;
315 if (off + sizeof (rec) > dest_size)
317 GNUNET_memcpy (&dest[off],
321 if (off + dd[i].issuer_attribute_len > dest_size)
323 GNUNET_memcpy (&dest[off],
324 dd[i].issuer_attribute,
325 dd[i].issuer_attribute_len);
326 off += dd[i].issuer_attribute_len;
327 if (0 == dd[i].subject_attribute_len)
329 if (off + dd[i].subject_attribute_len > dest_size)
331 GNUNET_memcpy (&dest[off],
332 dd[i].subject_attribute,
333 dd[i].subject_attribute_len);
334 off += dd[i].subject_attribute_len;
336 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
344 * Deserialize the given destination
346 * @param len size of the serialized delegation chain and cred
347 * @param src the serialized data
348 * @param d_count the number of delegation chain entries
349 * @param dd where to put the delegation chain entries
350 * @param c_count the number of credential entries
351 * @param cd where to put the credential data
352 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
355 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
357 unsigned int d_count,
358 struct GNUNET_CREDENTIAL_Delegation *dd,
359 unsigned int c_count,
360 struct GNUNET_CREDENTIAL_Credential *cd)
362 struct ChainEntry rec;
367 for (i=0;i<d_count;i++)
369 if (off + sizeof (rec) > len)
370 return GNUNET_SYSERR;
371 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
372 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
373 dd[i].issuer_key = rec.issuer_key;
374 dd[i].subject_key = rec.subject_key;
376 if (off + dd[i].issuer_attribute_len > len)
377 return GNUNET_SYSERR;
378 dd[i].issuer_attribute = &src[off];
379 off += dd[i].issuer_attribute_len;
380 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
381 if (off + dd[i].subject_attribute_len > len)
382 return GNUNET_SYSERR;
383 dd[i].subject_attribute = &src[off];
384 off += dd[i].subject_attribute_len;
386 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
392 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
396 struct CredentialEntry *cdata;
398 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
399 *data = GNUNET_malloc (size);
400 cdata = (struct CredentialEntry*)*data;
401 cdata->subject_key = cred->subject_key;
402 cdata->issuer_key = cred->issuer_key;
403 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
404 cdata->signature = cred->signature;
405 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
406 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
407 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
408 GNUNET_memcpy (&cdata[1],
409 cred->issuer_attribute,
410 strlen (cred->issuer_attribute));
412 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
417 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
418 "Invalid credential\n");
424 struct GNUNET_CREDENTIAL_Credential*
425 GNUNET_CREDENTIAL_credential_deserialize (const char* data,
428 struct GNUNET_CREDENTIAL_Credential *cred;
429 struct CredentialEntry *cdata;
430 char *issuer_attribute;
432 if (data_size < sizeof (struct CredentialEntry))
434 cdata = (struct CredentialEntry*)data;
435 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
440 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
441 "Invalid credential\n");
444 issuer_attribute = (char*)&cdata[1];
446 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
448 cred->issuer_key = cdata->issuer_key;
449 cred->subject_key = cdata->subject_key;
450 GNUNET_memcpy (&cred[1],
452 ntohl (cdata->issuer_attribute_len));
453 cred->signature = cdata->signature;
454 cred->issuer_attribute = (char*)&cred[1];
455 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
460 /* end of credential_serialization.c */