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/>.
21 * @file credential/credential_serialization.c
22 * @brief API to serialize and deserialize delegation chains
24 * @author Martin Schanzenbach
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_credential_service.h"
30 #include "gnunet_signatures.h"
31 #include "credential.h"
34 * Calculate how many bytes we will need to serialize
35 * the given delegation chain
37 * @param ds_count number of delegation chain entries
38 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
39 * @return the required size to serialize
42 GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
43 const struct GNUNET_CREDENTIAL_DelegationSet *dsr)
48 ret = sizeof (struct DelegationRecordData) * (ds_count);
50 for (i=0; i<ds_count;i++)
52 GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
53 ret += dsr[i].subject_attribute_len;
59 * Serizalize the given delegation chain entries and credential
61 * @param d_count number of delegation chain entries
62 * @param dsr array of #GNUNET_CREDENTIAL_DelegationSet
63 * @param dest_size size of the destination
64 * @param dest where to store the result
65 * @return the size of the data, -1 on failure
68 GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
69 const struct GNUNET_CREDENTIAL_DelegationSet *dsr,
73 struct DelegationRecordData rec;
78 for (i=0;i<d_count;i++)
80 rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
81 rec.subject_key = dsr[i].subject_key;
82 if (off + sizeof (rec) > dest_size)
84 GNUNET_memcpy (&dest[off],
88 if (0 == dsr[i].subject_attribute_len)
90 if (off + dsr[i].subject_attribute_len > dest_size)
92 GNUNET_memcpy (&dest[off],
93 dsr[i].subject_attribute,
94 dsr[i].subject_attribute_len);
95 off += dsr[i].subject_attribute_len;
102 * Deserialize the given destination
104 * @param len size of the serialized delegation chain and cred
105 * @param src the serialized data
106 * @param d_count the number of delegation chain entries
107 * @param dsr where to put the delegation chain entries
108 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
111 GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
113 unsigned int d_count,
114 struct GNUNET_CREDENTIAL_DelegationSet *dsr)
116 struct DelegationRecordData rec;
121 for (i=0;i<d_count;i++)
123 if (off + sizeof (rec) > len)
124 return GNUNET_SYSERR;
125 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
126 dsr[i].subject_key = rec.subject_key;
128 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
129 if (off + dsr[i].subject_attribute_len > len)
130 return GNUNET_SYSERR;
131 dsr[i].subject_attribute = (char*)&src[off];
132 off += dsr[i].subject_attribute_len;
139 * Calculate how many bytes we will need to serialize
142 * @param c_count number of credential entries
143 * @param cd a #GNUNET_CREDENTIAL_Credential
144 * @return the required size to serialize
147 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
148 const struct GNUNET_CREDENTIAL_Credential *cd)
153 ret = sizeof (struct CredentialEntry) * (c_count);
155 for (i=0; i<c_count;i++)
157 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
158 ret += cd[i].issuer_attribute_len;
163 * Serizalize the given credentials
165 * @param c_count number of credential entries
166 * @param cd a #GNUNET_CREDENTIAL_Credential
167 * @param dest_size size of the destination
168 * @param dest where to store the result
169 * @return the size of the data, -1 on failure
172 GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
173 const struct GNUNET_CREDENTIAL_Credential *cd,
177 struct CredentialEntry c_rec;
182 for (i=0;i<c_count;i++)
184 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
185 c_rec.issuer_key = cd[i].issuer_key;
186 c_rec.subject_key = cd[i].subject_key;
187 c_rec.signature = cd[i].signature;
188 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
189 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
190 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
191 if (off + sizeof (c_rec) > dest_size)
193 GNUNET_memcpy (&dest[off],
196 off += sizeof (c_rec);
197 if (off + cd[i].issuer_attribute_len > dest_size)
199 GNUNET_memcpy (&dest[off],
200 cd[i].issuer_attribute,
201 cd[i].issuer_attribute_len);
202 off += cd[i].issuer_attribute_len;
211 * Deserialize the given destination
213 * @param len size of the serialized creds
214 * @param src the serialized data
215 * @param c_count the number of credential entries
216 * @param cd where to put the credential data
217 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
220 GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
222 unsigned int c_count,
223 struct GNUNET_CREDENTIAL_Credential *cd)
225 struct CredentialEntry c_rec;
230 for (i=0;i<c_count;i++)
232 if (off + sizeof (c_rec) > len)
233 return GNUNET_SYSERR;
234 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
235 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
236 cd[i].issuer_key = c_rec.issuer_key;
237 cd[i].subject_key = c_rec.subject_key;
238 cd[i].signature = c_rec.signature;
239 cd[i].expiration.abs_value_us = GNUNET_ntohll(c_rec.expiration);
240 off += sizeof (c_rec);
241 if (off + cd[i].issuer_attribute_len > len)
242 return GNUNET_SYSERR;
243 cd[i].issuer_attribute = &src[off];
244 off += cd[i].issuer_attribute_len;
252 * Calculate how many bytes we will need to serialize
253 * the given delegation chain and credential
255 * @param d_count number of delegation chain entries
256 * @param dd array of #GNUNET_CREDENTIAL_Delegation
257 * @param c_count number of credential entries
258 * @param cd a #GNUNET_CREDENTIAL_Credential
259 * @return the required size to serialize
262 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
263 const struct GNUNET_CREDENTIAL_Delegation *dd,
264 unsigned int c_count,
265 const struct GNUNET_CREDENTIAL_Credential *cd)
270 ret = sizeof (struct ChainEntry) * (d_count);
272 for (i=0; i<d_count;i++)
274 GNUNET_assert ((ret +
275 dd[i].issuer_attribute_len +
276 dd[i].subject_attribute_len) >= ret);
277 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
279 return ret+GNUNET_CREDENTIAL_credentials_get_size(c_count, cd);
283 * Serizalize the given delegation chain entries and credential
285 * @param d_count number of delegation chain entries
286 * @param dd array of #GNUNET_CREDENTIAL_Delegation
287 * @param c_count number of credential entries
288 * @param cd a #GNUNET_CREDENTIAL_Credential
289 * @param dest_size size of the destination
290 * @param dest where to store the result
291 * @return the size of the data, -1 on failure
294 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
295 const struct GNUNET_CREDENTIAL_Delegation *dd,
296 unsigned int c_count,
297 const struct GNUNET_CREDENTIAL_Credential *cd,
301 struct ChainEntry rec;
306 for (i=0;i<d_count;i++)
308 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
309 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
310 rec.issuer_key = dd[i].issuer_key;
311 rec.subject_key = dd[i].subject_key;
312 if (off + sizeof (rec) > dest_size)
314 GNUNET_memcpy (&dest[off],
318 if (off + dd[i].issuer_attribute_len > dest_size)
320 GNUNET_memcpy (&dest[off],
321 dd[i].issuer_attribute,
322 dd[i].issuer_attribute_len);
323 off += dd[i].issuer_attribute_len;
324 if (0 == dd[i].subject_attribute_len)
326 if (off + dd[i].subject_attribute_len > dest_size)
328 GNUNET_memcpy (&dest[off],
329 dd[i].subject_attribute,
330 dd[i].subject_attribute_len);
331 off += dd[i].subject_attribute_len;
333 return off+GNUNET_CREDENTIAL_credentials_serialize (c_count,
341 * Deserialize the given destination
343 * @param len size of the serialized delegation chain and cred
344 * @param src the serialized data
345 * @param d_count the number of delegation chain entries
346 * @param dd where to put the delegation chain entries
347 * @param c_count the number of credential entries
348 * @param cd where to put the credential data
349 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
352 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
354 unsigned int d_count,
355 struct GNUNET_CREDENTIAL_Delegation *dd,
356 unsigned int c_count,
357 struct GNUNET_CREDENTIAL_Credential *cd)
359 struct ChainEntry rec;
364 for (i=0;i<d_count;i++)
366 if (off + sizeof (rec) > len)
367 return GNUNET_SYSERR;
368 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
369 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
370 dd[i].issuer_key = rec.issuer_key;
371 dd[i].subject_key = rec.subject_key;
373 if (off + dd[i].issuer_attribute_len > len)
374 return GNUNET_SYSERR;
375 dd[i].issuer_attribute = &src[off];
376 off += dd[i].issuer_attribute_len;
377 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
378 if (off + dd[i].subject_attribute_len > len)
379 return GNUNET_SYSERR;
380 dd[i].subject_attribute = &src[off];
381 off += dd[i].subject_attribute_len;
383 return GNUNET_CREDENTIAL_credentials_deserialize (len-off,
389 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
393 struct CredentialEntry *cdata;
395 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
396 *data = GNUNET_malloc (size);
397 cdata = (struct CredentialEntry*)*data;
398 cdata->subject_key = cred->subject_key;
399 cdata->issuer_key = cred->issuer_key;
400 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
401 cdata->signature = cred->signature;
402 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
403 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
404 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
405 GNUNET_memcpy (&cdata[1],
406 cred->issuer_attribute,
407 strlen (cred->issuer_attribute));
409 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
414 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
415 "Invalid credential\n");
421 struct GNUNET_CREDENTIAL_Credential*
422 GNUNET_CREDENTIAL_credential_deserialize (const char* data,
425 struct GNUNET_CREDENTIAL_Credential *cred;
426 struct CredentialEntry *cdata;
427 char *issuer_attribute;
429 if (data_size < sizeof (struct CredentialEntry))
431 cdata = (struct CredentialEntry*)data;
432 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
437 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
438 "Invalid credential\n");
441 issuer_attribute = (char*)&cdata[1];
443 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
445 cred->issuer_key = cdata->issuer_key;
446 cred->subject_key = cdata->subject_key;
447 GNUNET_memcpy (&cred[1],
449 ntohl (cdata->issuer_attribute_len));
450 cred->signature = cdata->signature;
451 cred->issuer_attribute = (char*)&cred[1];
452 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
457 /* end of credential_serialization.c */