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);
285 * Serizalize the given delegation chain entries and credential
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
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,
303 struct ChainEntry rec;
308 for (i=0;i<d_count;i++)
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)
316 GNUNET_memcpy (&dest[off],
320 if (off + dd[i].issuer_attribute_len > dest_size)
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)
328 if (off + dd[i].subject_attribute_len > dest_size)
330 GNUNET_memcpy (&dest[off],
331 dd[i].subject_attribute,
332 dd[i].subject_attribute_len);
333 off += dd[i].subject_attribute_len;
335 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
343 * Deserialize the given destination
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
354 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
356 unsigned int d_count,
357 struct GNUNET_CREDENTIAL_Delegation *dd,
358 unsigned int c_count,
359 struct GNUNET_CREDENTIAL_Credential *cd)
361 struct ChainEntry rec;
366 for (i=0;i<d_count;i++)
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;
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;
385 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
391 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
395 struct CredentialEntry *cdata;
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));
411 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
416 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
417 "Invalid credential\n");
423 struct GNUNET_CREDENTIAL_Credential*
424 GNUNET_CREDENTIAL_credential_deserialize (const char* data,
427 struct GNUNET_CREDENTIAL_Credential *cred;
428 struct CredentialEntry *cdata;
429 char *issuer_attribute;
431 if (data_size < sizeof (struct CredentialEntry))
433 cdata = (struct CredentialEntry*)data;
434 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
439 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
440 "Invalid credential\n");
443 issuer_attribute = (char*)&cdata[1];
445 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
447 cred->issuer_key = cdata->issuer_key;
448 cred->subject_key = cdata->subject_key;
449 GNUNET_memcpy (&cred[1],
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);
459 /* end of credential_serialization.c */