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;
142 * Calculate how many bytes we will need to serialize
143 * the given delegation chain and credential
145 * @param d_count number of delegation chain entries
146 * @param dd array of #GNUNET_CREDENTIAL_Delegation
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_delegation_chain_get_size (unsigned int d_count,
153 const struct GNUNET_CREDENTIAL_Delegation *dd,
154 unsigned int c_count,
155 const struct GNUNET_CREDENTIAL_Credential *cd)
160 ret = sizeof (struct ChainEntry) * (d_count);
161 ret += sizeof (struct CredentialEntry) * (c_count);
163 for (i=0; i<d_count;i++)
165 GNUNET_assert ((ret +
166 dd[i].issuer_attribute_len +
167 dd[i].subject_attribute_len) >= ret);
168 ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
170 for (i=0; i<c_count;i++)
172 GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
173 ret += cd[i].issuer_attribute_len;
179 * Serizalize the given delegation chain entries and credential
181 * @param d_count number of delegation chain entries
182 * @param dd array of #GNUNET_CREDENTIAL_Delegation
183 * @param c_count number of credential entries
184 * @param cd a #GNUNET_CREDENTIAL_Credential
185 * @param dest_size size of the destination
186 * @param dest where to store the result
187 * @return the size of the data, -1 on failure
190 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
191 const struct GNUNET_CREDENTIAL_Delegation *dd,
192 unsigned int c_count,
193 const struct GNUNET_CREDENTIAL_Credential *cd,
197 struct ChainEntry rec;
198 struct CredentialEntry c_rec;
203 for (i=0;i<d_count;i++)
205 rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
206 rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
207 rec.issuer_key = dd[i].issuer_key;
208 rec.subject_key = dd[i].subject_key;
209 if (off + sizeof (rec) > dest_size)
211 GNUNET_memcpy (&dest[off],
215 if (off + dd[i].issuer_attribute_len > dest_size)
217 GNUNET_memcpy (&dest[off],
218 dd[i].issuer_attribute,
219 dd[i].issuer_attribute_len);
220 off += dd[i].issuer_attribute_len;
221 if (0 == dd[i].subject_attribute_len)
223 if (off + dd[i].subject_attribute_len > dest_size)
225 GNUNET_memcpy (&dest[off],
226 dd[i].subject_attribute,
227 dd[i].subject_attribute_len);
228 off += dd[i].subject_attribute_len;
230 for (i=0;i<c_count;i++)
232 c_rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
233 c_rec.issuer_key = cd[i].issuer_key;
234 c_rec.subject_key = cd[i].subject_key;
235 c_rec.signature = cd[i].signature;
236 c_rec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
237 c_rec.purpose.size = htonl ((sizeof (struct CredentialEntry) + cd[i].issuer_attribute_len) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
238 c_rec.expiration = htonl ((uint32_t) cd[i].expiration.abs_value_us);
239 if (off + sizeof (c_rec) > dest_size)
241 GNUNET_memcpy (&dest[off],
244 off += sizeof (c_rec);
245 if (off + cd[i].issuer_attribute_len > dest_size)
247 GNUNET_memcpy (&dest[off],
248 cd[i].issuer_attribute,
249 cd[i].issuer_attribute_len);
250 off += cd[i].issuer_attribute_len;
258 * Deserialize the given destination
260 * @param len size of the serialized delegation chain and cred
261 * @param src the serialized data
262 * @param d_count the number of delegation chain entries
263 * @param dd where to put the delegation chain entries
264 * @param c_count the number of credential entries
265 * @param cd where to put the credential data
266 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
269 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
271 unsigned int d_count,
272 struct GNUNET_CREDENTIAL_Delegation *dd,
273 unsigned int c_count,
274 struct GNUNET_CREDENTIAL_Credential *cd)
276 struct ChainEntry rec;
277 struct CredentialEntry c_rec;
282 for (i=0;i<d_count;i++)
284 if (off + sizeof (rec) > len)
285 return GNUNET_SYSERR;
286 GNUNET_memcpy (&rec, &src[off], sizeof (rec));
287 dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
288 dd[i].issuer_key = rec.issuer_key;
289 dd[i].subject_key = rec.subject_key;
291 if (off + dd[i].issuer_attribute_len > len)
292 return GNUNET_SYSERR;
293 dd[i].issuer_attribute = &src[off];
294 off += dd[i].issuer_attribute_len;
295 dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
296 if (off + dd[i].subject_attribute_len > len)
297 return GNUNET_SYSERR;
298 dd[i].subject_attribute = &src[off];
299 off += dd[i].subject_attribute_len;
301 for (i=0;i<c_count;i++)
303 if (off + sizeof (c_rec) > len)
304 return GNUNET_SYSERR;
305 GNUNET_memcpy (&c_rec, &src[off], sizeof (c_rec));
306 cd[i].issuer_attribute_len = ntohl ((uint32_t) c_rec.issuer_attribute_len);
307 cd[i].issuer_key = c_rec.issuer_key;
308 cd[i].subject_key = c_rec.subject_key;
309 cd[i].signature = c_rec.signature;
310 cd[i].expiration.abs_value_us = ntohl((uint32_t) c_rec.expiration);
311 off += sizeof (c_rec);
312 if (off + cd[i].issuer_attribute_len > len)
313 return GNUNET_SYSERR;
314 cd[i].issuer_attribute = &src[off];
315 off += cd[i].issuer_attribute_len;
322 GNUNET_CREDENTIAL_credential_serialize (struct GNUNET_CREDENTIAL_Credential *cred,
326 struct CredentialEntry *cdata;
328 size = sizeof (struct CredentialEntry) + strlen (cred->issuer_attribute) + 1;
329 *data = GNUNET_malloc (size);
330 cdata = (struct CredentialEntry*)*data;
331 cdata->subject_key = cred->subject_key;
332 cdata->issuer_key = cred->issuer_key;
333 cdata->expiration = GNUNET_htonll (cred->expiration.abs_value_us);
334 cdata->signature = cred->signature;
335 cdata->issuer_attribute_len = htonl (strlen (cred->issuer_attribute) + 1);
336 cdata->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CREDENTIAL);
337 cdata->purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
338 GNUNET_memcpy (&cdata[1],
339 cred->issuer_attribute,
340 strlen (cred->issuer_attribute));
342 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
347 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
348 "Invalid credential\n");
354 struct GNUNET_CREDENTIAL_Credential*
355 GNUNET_CREDENTIAL_credential_deserialize (const char* data,
358 struct GNUNET_CREDENTIAL_Credential *cred;
359 struct CredentialEntry *cdata;
360 char *issuer_attribute;
362 if (data_size < sizeof (struct CredentialEntry))
364 cdata = (struct CredentialEntry*)data;
365 if(GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify(GNUNET_SIGNATURE_PURPOSE_CREDENTIAL,
370 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
371 "Invalid credential\n");
374 issuer_attribute = (char*)&cdata[1];
376 cred = GNUNET_malloc (sizeof (struct GNUNET_CREDENTIAL_Credential) + ntohl(cdata->issuer_attribute_len));
378 cred->issuer_key = cdata->issuer_key;
379 cred->subject_key = cdata->subject_key;
380 GNUNET_memcpy (&cred[1],
382 ntohl (cdata->issuer_attribute_len));
383 cred->signature = cdata->signature;
384 cred->issuer_attribute = (char*)&cred[1];
385 cred->expiration.abs_value_us = GNUNET_ntohll (cdata->expiration);
390 /* end of credential_serialization.c */