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 and credential
39 * @param d_count number of delegation chain entries
40 * @param dd array of #GNUNET_CREDENTIAL_Delegation
41 * @param cd a #GNUNET_CREDENTIAL_Credential
42 * @return the required size to serialize
45 GNUNET_CREDENTIAL_delegation_set_get_size (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 dd array of #GNUNET_CREDENTIAL_Delegation
66 * @param cd a #GNUNET_CREDENTIAL_Credential
67 * @param dest_size size of the destination
68 * @param dest where to store the result
69 * @return the size of the data, -1 on failure
72 GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
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],
92 if (0 == dsr[i].subject_attribute_len)
94 if (off + dsr[i].subject_attribute_len > dest_size)
96 GNUNET_memcpy (&dest[off],
97 dsr[i].subject_attribute,
98 dsr[i].subject_attribute_len);
99 off += dsr[i].subject_attribute_len;
106 * Deserialize the given destination
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 dd where to put the delegation chain entries
112 * @param cd where to put the credential data
113 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
116 GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
118 unsigned int d_count,
119 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
121 struct DelegationRecordData rec;
126 for (i=0;i<d_count;i++)
128 if (off + sizeof (rec) > len)
129 return GNUNET_SYSERR;
130 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
131 dsr[i].subject_key = rec.subject_key;
133 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
134 if (off + dsr[i].subject_attribute_len > len)
135 return GNUNET_SYSERR;
136 dsr[i].subject_attribute = (char*)&src[off];
137 off += dsr[i].subject_attribute_len;
144 * Calculate how many bytes we will need to serialize
147 * @param c_count number of credential entries
148 * @param cd a #GNUNET_CREDENTIAL_Credential
149 * @return the required size to serialize
152 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
153 const struct GNUNET_CREDENTIAL_Credential *cd)
158 ret = sizeof (struct CredentialEntry) * (c_count);
160 for (i=0; i<c_count;i++)
162 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
163 ret += cd[i].issuer_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_credentials_serialize (unsigned int c_count,
178 const struct GNUNET_CREDENTIAL_Credential *cd,
182 struct CredentialEntry c_rec;
187 for (i=0;i<c_count;i++)
189 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
190 c_rec.issuer_key = cd[i].issuer_key;
191 c_rec.subject_key = cd[i].subject_key;
192 c_rec.signature = cd[i].signature;
193 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
194 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
195 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
196 if (off + sizeof (c_rec) > dest_size)
198 GNUNET_memcpy (&dest[off],
201 off += sizeof (c_rec);
202 if (off + cd[i].issuer_attribute_len > dest_size)
204 GNUNET_memcpy (&dest[off],
205 cd[i].issuer_attribute,
206 cd[i].issuer_attribute_len);
207 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_credentials_deserialize (size_t len,
227 unsigned int c_count,
228 struct GNUNET_CREDENTIAL_Credential *cd)
230 struct CredentialEntry 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;
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 (unsigned int d_count,
268 const struct GNUNET_CREDENTIAL_Delegation *dd,
269 unsigned int c_count,
270 const struct GNUNET_CREDENTIAL_Credential *cd)
275 ret = sizeof (struct ChainEntry) * (d_count);
277 for (i=0; i<d_count;i++)
279 GNUNET_assert ((ret +
280 dd[i].issuer_attribute_len +
281 dd[i].subject_attribute_len) >= ret);
282 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
284 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
289 * Serizalize the given delegation chain entries and credential
291 * @param d_count number of delegation chain entries
292 * @param dd array of #GNUNET_CREDENTIAL_Delegation
293 * @param c_count number of credential entries
294 * @param cd a #GNUNET_CREDENTIAL_Credential
295 * @param dest_size size of the destination
296 * @param dest where to store the result
297 * @return the size of the data, -1 on failure
300 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
301 const struct GNUNET_CREDENTIAL_Delegation *dd,
302 unsigned int c_count,
303 const struct GNUNET_CREDENTIAL_Credential *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],
324 if (off + dd[i].issuer_attribute_len > dest_size)
326 GNUNET_memcpy (&dest[off],
327 dd[i].issuer_attribute,
328 dd[i].issuer_attribute_len);
329 off += dd[i].issuer_attribute_len;
330 if (0 == dd[i].subject_attribute_len)
332 if (off + dd[i].subject_attribute_len > dest_size)
334 GNUNET_memcpy (&dest[off],
335 dd[i].subject_attribute,
336 dd[i].subject_attribute_len);
337 off += dd[i].subject_attribute_len;
339 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
347 * Deserialize the given destination
349 * @param len size of the serialized delegation chain and cred
350 * @param src the serialized data
351 * @param d_count the number of delegation chain entries
352 * @param dd where to put the delegation chain entries
353 * @param c_count the number of credential entries
354 * @param cd where to put the credential data
355 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
358 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
360 unsigned int d_count,
361 struct GNUNET_CREDENTIAL_Delegation *dd,
362 unsigned int c_count,
363 struct GNUNET_CREDENTIAL_Credential *cd)
365 struct ChainEntry rec;
370 for (i=0;i<d_count;i++)
372 if (off + sizeof (rec) > len)
373 return GNUNET_SYSERR;
374 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
375 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
376 dd[i].issuer_key = rec.issuer_key;
377 dd[i].subject_key = rec.subject_key;
379 if (off + dd[i].issuer_attribute_len > len)
380 return GNUNET_SYSERR;
381 dd[i].issuer_attribute = &src[off];
382 off += dd[i].issuer_attribute_len;
383 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
384 if (off + dd[i].subject_attribute_len > len)
385 return GNUNET_SYSERR;
386 dd[i].subject_attribute = &src[off];
387 off += dd[i].subject_attribute_len;
389 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
395 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
399 struct CredentialEntry *cdata;
401 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
402 *data = GNUNET_malloc (size);
403 cdata = (struct CredentialEntry*)*data;
404 cdata->subject_key = cred->subject_key;
405 cdata->issuer_key = cred->issuer_key;
406 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
407 cdata->signature = cred->signature;
408 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
409 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
410 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
411 GNUNET_memcpy (&cdata[1],
412 cred->issuer_attribute,
413 strlen (cred->issuer_attribute));
415 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
420 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
421 "Invalid credential\n");
427 struct GNUNET_CREDENTIAL_Credential*
428 GNUNET_CREDENTIAL_credential_deserialize (const char* data,
431 struct GNUNET_CREDENTIAL_Credential *cred;
432 struct CredentialEntry *cdata;
433 char *issuer_attribute;
435 if (data_size < sizeof (struct CredentialEntry))
437 cdata = (struct CredentialEntry*)data;
438 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
443 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
444 "Invalid credential\n");
447 issuer_attribute = (char*)&cdata[1];
449 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
451 cred->issuer_key = cdata->issuer_key;
452 cred->subject_key = cdata->subject_key;
453 GNUNET_memcpy (&cred[1],
455 ntohl (cdata->issuer_attribute_len));
456 cred->signature = cdata->signature;
457 cred->issuer_attribute = (char*)&cred[1];
458 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
463 /* end of credential_serialization.c */