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 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.
18 * @file credential/credential_serialization.c
19 * @brief API to serialize and deserialize delegation chains
21 * @author Martin Schanzenbach
24 #include "gnunet_util_lib.h"
25 #include "gnunet_constants.h"
26 #include "gnunet_credential_service.h"
27 #include "gnunet_signatures.h"
28 #include "credential.h"
31 * Calculate how many bytes we will need to serialize
32 * the given delegation chain
34 * @param ds_count number of delegation chain entries
35 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
36 * @return the required size to serialize
39 GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
40 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
45 ret = sizeof (struct DelegationRecordData) * (ds_count);
47 for (i=0; i<ds_count;i++)
49 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
50 ret += dsr[i].subject_attribute_len;
56 * Serizalize the given delegation chain entries and credential
58 * @param d_count number of delegation chain entries
59 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
60 * @param dest_size size of the destination
61 * @param dest where to store the result
62 * @return the size of the data, -1 on failure
65 GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
66 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
70 struct DelegationRecordData rec;
75 for (i=0;i<d_count;i++)
77 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
78 rec.subject_key = dsr[i].subject_key;
79 if (off + sizeof (rec) > dest_size)
81 GNUNET_memcpy (&dest[off],
85 if (0 == dsr[i].subject_attribute_len)
87 if (off + dsr[i].subject_attribute_len > dest_size)
89 GNUNET_memcpy (&dest[off],
90 dsr[i].subject_attribute,
91 dsr[i].subject_attribute_len);
92 off += dsr[i].subject_attribute_len;
99 * Deserialize the given destination
101 * @param len size of the serialized delegation chain and cred
102 * @param src the serialized data
103 * @param d_count the number of delegation chain entries
104 * @param dsr where to put the delegation chain entries
105 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
108 GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
110 unsigned int d_count,
111 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
113 struct DelegationRecordData rec;
118 for (i=0;i<d_count;i++)
120 if (off + sizeof (rec) > len)
121 return GNUNET_SYSERR;
122 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
123 dsr[i].subject_key = rec.subject_key;
125 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
126 if (off + dsr[i].subject_attribute_len > len)
127 return GNUNET_SYSERR;
128 dsr[i].subject_attribute = (char*)&src[off];
129 off += dsr[i].subject_attribute_len;
136 * Calculate how many bytes we will need to serialize
139 * @param c_count number of credential entries
140 * @param cd a #GNUNET_CREDENTIAL_Credential
141 * @return the required size to serialize
144 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
145 const struct GNUNET_CREDENTIAL_Credential *cd)
150 ret = sizeof (struct CredentialEntry) * (c_count);
152 for (i=0; i<c_count;i++)
154 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
155 ret += cd[i].issuer_attribute_len;
160 * Serizalize the given credentials
162 * @param c_count number of credential entries
163 * @param cd a #GNUNET_CREDENTIAL_Credential
164 * @param dest_size size of the destination
165 * @param dest where to store the result
166 * @return the size of the data, -1 on failure
169 GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
170 const struct GNUNET_CREDENTIAL_Credential *cd,
174 struct CredentialEntry c_rec;
179 for (i=0;i<c_count;i++)
181 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
182 c_rec.issuer_key = cd[i].issuer_key;
183 c_rec.subject_key = cd[i].subject_key;
184 c_rec.signature = cd[i].signature;
185 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
186 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
187 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
188 if (off + sizeof (c_rec) > dest_size)
190 GNUNET_memcpy (&dest[off],
193 off += sizeof (c_rec);
194 if (off + cd[i].issuer_attribute_len > dest_size)
196 GNUNET_memcpy (&dest[off],
197 cd[i].issuer_attribute,
198 cd[i].issuer_attribute_len);
199 off += cd[i].issuer_attribute_len;
208 * Deserialize the given destination
210 * @param len size of the serialized creds
211 * @param src the serialized data
212 * @param c_count the number of credential entries
213 * @param cd where to put the credential data
214 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
217 GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
219 unsigned int c_count,
220 struct GNUNET_CREDENTIAL_Credential *cd)
222 struct CredentialEntry c_rec;
227 for (i=0;i<c_count;i++)
229 if (off + sizeof (c_rec) > len)
230 return GNUNET_SYSERR;
231 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
232 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
233 cd[i].issuer_key = c_rec.issuer_key;
234 cd[i].subject_key = c_rec.subject_key;
235 cd[i].signature = c_rec.signature;
236 cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
237 off += sizeof (c_rec);
238 if (off + cd[i].issuer_attribute_len > len)
239 return GNUNET_SYSERR;
240 cd[i].issuer_attribute = &src[off];
241 off += cd[i].issuer_attribute_len;
249 * Calculate how many bytes we will need to serialize
250 * the given delegation chain and credential
252 * @param d_count number of delegation chain entries
253 * @param dd array of #GNUNET_CREDENTIAL_Delegation
254 * @param c_count number of credential entries
255 * @param cd a #GNUNET_CREDENTIAL_Credential
256 * @return the required size to serialize
259 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
260 const struct GNUNET_CREDENTIAL_Delegation *dd,
261 unsigned int c_count,
262 const struct GNUNET_CREDENTIAL_Credential *cd)
267 ret = sizeof (struct ChainEntry) * (d_count);
269 for (i=0; i<d_count;i++)
271 GNUNET_assert ((ret +
272 dd[i].issuer_attribute_len +
273 dd[i].subject_attribute_len) >= ret);
274 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
276 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
280 * Serizalize the given delegation chain entries and credential
282 * @param d_count number of delegation chain entries
283 * @param dd array of #GNUNET_CREDENTIAL_Delegation
284 * @param c_count number of credential entries
285 * @param cd a #GNUNET_CREDENTIAL_Credential
286 * @param dest_size size of the destination
287 * @param dest where to store the result
288 * @return the size of the data, -1 on failure
291 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
292 const struct GNUNET_CREDENTIAL_Delegation *dd,
293 unsigned int c_count,
294 const struct GNUNET_CREDENTIAL_Credential *cd,
298 struct ChainEntry rec;
303 for (i=0;i<d_count;i++)
305 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
306 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
307 rec.issuer_key = dd[i].issuer_key;
308 rec.subject_key = dd[i].subject_key;
309 if (off + sizeof (rec) > dest_size)
311 GNUNET_memcpy (&dest[off],
315 if (off + dd[i].issuer_attribute_len > dest_size)
317 GNUNET_memcpy (&dest[off],
318 dd[i].issuer_attribute,
319 dd[i].issuer_attribute_len);
320 off += dd[i].issuer_attribute_len;
321 if (0 == dd[i].subject_attribute_len)
323 if (off + dd[i].subject_attribute_len > dest_size)
325 GNUNET_memcpy (&dest[off],
326 dd[i].subject_attribute,
327 dd[i].subject_attribute_len);
328 off += dd[i].subject_attribute_len;
330 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
338 * Deserialize the given destination
340 * @param len size of the serialized delegation chain and cred
341 * @param src the serialized data
342 * @param d_count the number of delegation chain entries
343 * @param dd where to put the delegation chain entries
344 * @param c_count the number of credential entries
345 * @param cd where to put the credential data
346 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
349 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
351 unsigned int d_count,
352 struct GNUNET_CREDENTIAL_Delegation *dd,
353 unsigned int c_count,
354 struct GNUNET_CREDENTIAL_Credential *cd)
356 struct ChainEntry rec;
361 for (i=0;i<d_count;i++)
363 if (off + sizeof (rec) > len)
364 return GNUNET_SYSERR;
365 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
366 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
367 dd[i].issuer_key = rec.issuer_key;
368 dd[i].subject_key = rec.subject_key;
370 if (off + dd[i].issuer_attribute_len > len)
371 return GNUNET_SYSERR;
372 dd[i].issuer_attribute = &src[off];
373 off += dd[i].issuer_attribute_len;
374 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
375 if (off + dd[i].subject_attribute_len > len)
376 return GNUNET_SYSERR;
377 dd[i].subject_attribute = &src[off];
378 off += dd[i].subject_attribute_len;
380 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
386 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
390 struct CredentialEntry *cdata;
392 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
393 *data = GNUNET_malloc (size);
394 cdata = (struct CredentialEntry*)*data;
395 cdata->subject_key = cred->subject_key;
396 cdata->issuer_key = cred->issuer_key;
397 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
398 cdata->signature = cred->signature;
399 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
400 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
401 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
402 GNUNET_memcpy (&cdata[1],
403 cred->issuer_attribute,
404 strlen (cred->issuer_attribute));
406 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
411 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
412 "Invalid credential\n");
418 struct GNUNET_CREDENTIAL_Credential*
419 GNUNET_CREDENTIAL_credential_deserialize (const char* data,
422 struct GNUNET_CREDENTIAL_Credential *cred;
423 struct CredentialEntry *cdata;
424 char *issuer_attribute;
426 if (data_size < sizeof (struct CredentialEntry))
428 cdata = (struct CredentialEntry*)data;
429 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
434 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
435 "Invalid credential\n");
438 issuer_attribute = (char*)&cdata[1];
440 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
442 cred->issuer_key = cdata->issuer_key;
443 cred->subject_key = cdata->subject_key;
444 GNUNET_memcpy (&cred[1],
446 ntohl (cdata->issuer_attribute_len));
447 cred->signature = cdata->signature;
448 cred->issuer_attribute = (char*)&cred[1];
449 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
454 /* end of credential_serialization.c */