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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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,
46 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 dsr array of #GNUNET_CREDENTIAL_DelegationSet
66 * @param dest_size size of the destination
67 * @param dest where to store the result
68 * @return the size of the data, -1 on failure
71 GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
73 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 dsr where to put the delegation chain entries
112 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
115 GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
117 unsigned int d_count,
119 GNUNET_CREDENTIAL_DelegationSet *
122 struct DelegationRecordData rec;
127 for (i = 0; i < d_count; i++)
129 if (off + sizeof(rec) > len)
130 return GNUNET_SYSERR;
131 GNUNET_memcpy (&rec, &src[off], sizeof(rec));
132 dsr[i].subject_key = rec.subject_key;
134 dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
135 if (off + dsr[i].subject_attribute_len > len)
136 return GNUNET_SYSERR;
137 dsr[i].subject_attribute = (char*) &src[off];
138 off += dsr[i].subject_attribute_len;
145 * Calculate how many bytes we will need to serialize
148 * @param c_count number of credential entries
149 * @param cd a #GNUNET_CREDENTIAL_Credential
150 * @return the required size to serialize
153 GNUNET_CREDENTIAL_credentials_get_size (unsigned int c_count,
155 GNUNET_CREDENTIAL_Credential *cd)
160 ret = sizeof(struct CredentialEntry) * (c_count);
162 for (i = 0; i < c_count; i++)
164 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
165 ret += cd[i].issuer_attribute_len;
170 * Serizalize the given credentials
172 * @param c_count number of credential entries
173 * @param cd a #GNUNET_CREDENTIAL_Credential
174 * @param dest_size size of the destination
175 * @param dest where to store the result
176 * @return the size of the data, -1 on failure
179 GNUNET_CREDENTIAL_credentials_serialize (unsigned int c_count,
181 GNUNET_CREDENTIAL_Credential *cd,
185 struct CredentialEntry c_rec;
190 for (i = 0; i < c_count; i++)
192 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
193 c_rec.issuer_key = cd[i].issuer_key;
194 c_rec.subject_key = cd[i].subject_key;
195 c_rec.signature = cd[i].signature;
196 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
197 c_rec.purpose.size = htonl ((sizeof(struct CredentialEntry)
198 + cd[i].issuer_attribute_len) - sizeof(struct
199 GNUNET_CRYPTO_EcdsaSignature));
200 c_rec.expiration = GNUNET_htonll (cd[i].expiration.abs_value_us);
201 if (off + sizeof(c_rec) > dest_size)
203 GNUNET_memcpy (&dest[off],
206 off += sizeof(c_rec);
207 if (off + cd[i].issuer_attribute_len > dest_size)
209 GNUNET_memcpy (&dest[off],
210 cd[i].issuer_attribute,
211 cd[i].issuer_attribute_len);
212 off += cd[i].issuer_attribute_len;
221 * Deserialize the given destination
223 * @param len size of the serialized creds
224 * @param src the serialized data
225 * @param c_count the number of credential entries
226 * @param cd where to put the credential data
227 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
230 GNUNET_CREDENTIAL_credentials_deserialize (size_t len,
232 unsigned int c_count,
233 struct GNUNET_CREDENTIAL_Credential *
236 struct CredentialEntry c_rec;
241 for (i = 0; i < c_count; i++)
243 if (off + sizeof(c_rec) > len)
244 return GNUNET_SYSERR;
245 GNUNET_memcpy (&c_rec, &src[off], sizeof(c_rec));
246 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
247 cd[i].issuer_key = c_rec.issuer_key;
248 cd[i].subject_key = c_rec.subject_key;
249 cd[i].signature = c_rec.signature;
250 cd[i].expiration.abs_value_us = GNUNET_ntohll (c_rec.expiration);
251 off += sizeof(c_rec);
252 if (off + cd[i].issuer_attribute_len > len)
253 return GNUNET_SYSERR;
254 cd[i].issuer_attribute = &src[off];
255 off += cd[i].issuer_attribute_len;
263 * Calculate how many bytes we will need to serialize
264 * the given delegation chain and credential
266 * @param d_count number of delegation chain entries
267 * @param dd array of #GNUNET_CREDENTIAL_Delegation
268 * @param c_count number of credential entries
269 * @param cd a #GNUNET_CREDENTIAL_Credential
270 * @return the required size to serialize
273 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
275 GNUNET_CREDENTIAL_Delegation *dd,
276 unsigned int c_count,
278 GNUNET_CREDENTIAL_Credential *cd)
283 ret = sizeof(struct ChainEntry) * (d_count);
285 for (i = 0; i < d_count; i++)
288 + dd[i].issuer_attribute_len
289 + dd[i].subject_attribute_len) >= ret);
290 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
292 return ret + GNUNET_CREDENTIAL_credentials_get_size (c_count, cd);
296 * Serizalize the given delegation chain entries and credential
298 * @param d_count number of delegation chain entries
299 * @param dd array of #GNUNET_CREDENTIAL_Delegation
300 * @param c_count number of credential entries
301 * @param cd a #GNUNET_CREDENTIAL_Credential
302 * @param dest_size size of the destination
303 * @param dest where to store the result
304 * @return the size of the data, -1 on failure
307 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
309 GNUNET_CREDENTIAL_Delegation *dd,
310 unsigned int c_count,
312 GNUNET_CREDENTIAL_Credential *cd,
316 struct ChainEntry rec;
321 for (i = 0; i < d_count; i++)
323 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
324 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
325 rec.issuer_key = dd[i].issuer_key;
326 rec.subject_key = dd[i].subject_key;
327 if (off + sizeof(rec) > dest_size)
329 GNUNET_memcpy (&dest[off],
333 if (off + dd[i].issuer_attribute_len > dest_size)
335 GNUNET_memcpy (&dest[off],
336 dd[i].issuer_attribute,
337 dd[i].issuer_attribute_len);
338 off += dd[i].issuer_attribute_len;
339 if (0 == dd[i].subject_attribute_len)
341 if (off + dd[i].subject_attribute_len > dest_size)
343 GNUNET_memcpy (&dest[off],
344 dd[i].subject_attribute,
345 dd[i].subject_attribute_len);
346 off += dd[i].subject_attribute_len;
348 return off + GNUNET_CREDENTIAL_credentials_serialize (c_count,
356 * Deserialize the given destination
358 * @param len size of the serialized delegation chain and cred
359 * @param src the serialized data
360 * @param d_count the number of delegation chain entries
361 * @param dd where to put the delegation chain entries
362 * @param c_count the number of credential entries
363 * @param cd where to put the credential data
364 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
367 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
369 unsigned int d_count,
371 GNUNET_CREDENTIAL_Delegation *dd,
372 unsigned int c_count,
374 GNUNET_CREDENTIAL_Credential *cd)
376 struct ChainEntry rec;
381 for (i = 0; i < d_count; i++)
383 if (off + sizeof(rec) > len)
384 return GNUNET_SYSERR;
385 GNUNET_memcpy (&rec, &src[off], sizeof(rec));
386 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
387 dd[i].issuer_key = rec.issuer_key;
388 dd[i].subject_key = rec.subject_key;
390 if (off + dd[i].issuer_attribute_len > len)
391 return GNUNET_SYSERR;
392 dd[i].issuer_attribute = &src[off];
393 off += dd[i].issuer_attribute_len;
394 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
395 if (off + dd[i].subject_attribute_len > len)
396 return GNUNET_SYSERR;
397 dd[i].subject_attribute = &src[off];
398 off += dd[i].subject_attribute_len;
400 return GNUNET_CREDENTIAL_credentials_deserialize (len - off,
406 GNUNET_CREDENTIAL_credential_serialize (struct
407 GNUNET_CREDENTIAL_Credential *cred,
411 struct CredentialEntry *cdata;
413 size = sizeof(struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
414 *data = GNUNET_malloc (size);
415 cdata = (struct CredentialEntry*) *data;
416 cdata->subject_key = cred->subject_key;
417 cdata->issuer_key = cred->issuer_key;
418 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
419 cdata->signature = cred->signature;
420 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
421 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
422 cdata->purpose.size = htonl (size - sizeof(struct
423 GNUNET_CRYPTO_EcdsaSignature));
424 GNUNET_memcpy (&cdata[1],
425 cred->issuer_attribute,
426 strlen (cred->issuer_attribute));
428 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (
429 GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
434 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
435 "Invalid credential\n");
441 struct GNUNET_CREDENTIAL_Credential*
442 GNUNET_CREDENTIAL_credential_deserialize (const char*data,
445 struct GNUNET_CREDENTIAL_Credential *cred;
446 struct CredentialEntry *cdata;
447 char *issuer_attribute;
449 if (data_size < sizeof(struct CredentialEntry))
451 cdata = (struct CredentialEntry*) data;
452 if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (
453 GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
458 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
459 "Invalid credential\n");
462 issuer_attribute = (char*) &cdata[1];
464 cred = GNUNET_malloc (sizeof(struct GNUNET_CREDENTIAL_Credential) + ntohl (
465 cdata->issuer_attribute_len));
467 cred->issuer_key = cdata->issuer_key;
468 cred->subject_key = cdata->subject_key;
469 GNUNET_memcpy (&cred[1],
471 ntohl (cdata->issuer_attribute_len));
472 cred->signature = cdata->signature;
473 cred->issuer_attribute = (char*) &cred[1];
474 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
479 /* end of credential_serialization.c */