b08920d960bce911b585d0b5506eb0a769336a27
[oweals/gnunet.git] / src / credential / credential_serialization.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
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.
9
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.
14
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.
19 */
20
21
22 /**
23  * @file credential/credential_serialization.c
24  * @brief API to serialize and deserialize delegation chains 
25  * and credentials
26  * @author Martin Schanzenbach
27  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_credential_service.h"
32
33 GNUNET_NETWORK_STRUCT_BEGIN
34
35 struct DelegationRecordData
36 {
37   /**
38    * Subject key
39    */
40   struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
41   
42   /**
43    * Subject attributes
44    */
45   uint32_t subject_attribute_len GNUNET_PACKED;
46 };
47
48
49 struct ChainEntry
50 {
51   /**
52    * Issuer key
53    */
54   struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
55   
56   /**
57    * Subject key
58    */
59   struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
60   
61   /**
62    * Issuer attributes
63    */
64   uint32_t issuer_attribute_len GNUNET_PACKED;
65   
66   /**
67    * Subject attributes
68    */
69   uint32_t subject_attribute_len GNUNET_PACKED;
70 };
71
72 GNUNET_NETWORK_STRUCT_END
73
74
75 /**
76  * Calculate how many bytes we will need to serialize
77  * the given delegation chain and credential
78  *
79  * @param d_count number of delegation chain entries
80  * @param dd array of #GNUNET_CREDENTIAL_Delegation
81  * @param cd a #GNUNET_CREDENTIAL_Credential
82  * @return the required size to serialize
83  */
84 size_t
85 GNUNET_CREDENTIAL_delegation_set_get_size (unsigned int ds_count,
86                                            const struct GNUNET_CREDENTIAL_DelegationSetRecord *dsr)
87 {
88   unsigned int i;
89   size_t ret;
90
91   ret = sizeof (struct DelegationRecordData) * (ds_count);
92
93   for (i=0; i<ds_count;i++)
94   {
95     GNUNET_assert ((ret + dsr[i].subject_attribute_len) >= ret);
96     ret += dsr[i].subject_attribute_len;
97   }
98   return ret;
99 }
100
101 /**
102  * Serizalize the given delegation chain entries and credential
103  *
104  * @param d_count number of delegation chain entries
105  * @param dd array of #GNUNET_CREDENTIAL_Delegation
106  * @param cd a #GNUNET_CREDENTIAL_Credential
107  * @param dest_size size of the destination
108  * @param dest where to store the result
109  * @return the size of the data, -1 on failure
110  */
111 ssize_t
112 GNUNET_CREDENTIAL_delegation_set_serialize (unsigned int d_count,
113                                             const struct GNUNET_CREDENTIAL_DelegationSetRecord *dsr,
114                                             size_t dest_size,
115                                             char *dest)
116 {
117   struct DelegationRecordData rec;
118   unsigned int i;
119   size_t off;
120
121   off = 0;
122   for (i=0;i<d_count;i++)
123   {
124     rec.subject_attribute_len = htonl ((uint32_t) dsr[i].subject_attribute_len);
125     rec.subject_key = dsr[i].subject_key;
126     if (off + sizeof (rec) > dest_size)
127       return -1;
128     GNUNET_memcpy (&dest[off],
129                    &rec,
130                    sizeof (rec));
131     off += sizeof (rec);
132     if (0 == dsr[i].subject_attribute_len)
133       continue;
134     if (off + dsr[i].subject_attribute_len > dest_size)
135       return -1;
136     GNUNET_memcpy (&dest[off],
137                    dsr[i].subject_attribute,
138                    dsr[i].subject_attribute_len);
139     off += dsr[i].subject_attribute_len;
140   }
141   return off;
142 }
143
144
145 /**
146  * Deserialize the given destination
147  *
148  * @param len size of the serialized delegation chain and cred
149  * @param src the serialized data
150  * @param d_count the number of delegation chain entries
151  * @param dd where to put the delegation chain entries
152  * @param cd where to put the credential data
153  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
154  */
155 int
156 GNUNET_CREDENTIAL_delegation_set_deserialize (size_t len,
157                                               const char *src,
158                                               unsigned int d_count,
159                                               struct GNUNET_CREDENTIAL_DelegationSetRecord *dsr)
160 {
161   struct DelegationRecordData rec;
162   unsigned int i;
163   size_t off;
164
165   off = 0;
166   for (i=0;i<d_count;i++)
167   {
168     if (off + sizeof (rec) > len)
169       return GNUNET_SYSERR;
170     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
171     dsr[i].subject_key = rec.subject_key;
172     off += sizeof (rec);
173     dsr[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
174     if (off + dsr[i].subject_attribute_len > len)
175       return GNUNET_SYSERR;
176     dsr[i].subject_attribute = &src[off];
177     off += dsr[i].subject_attribute_len;
178   }
179   return GNUNET_OK;
180 }
181 /**
182  * Calculate how many bytes we will need to serialize
183  * the given delegation chain and credential
184  *
185  * @param d_count number of delegation chain entries
186  * @param dd array of #GNUNET_CREDENTIAL_Delegation
187  * @param c_count number of credential entries
188  * @param cd a #GNUNET_CREDENTIAL_Credential
189  * @return the required size to serialize
190  */
191 size_t
192 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
193                                              const struct GNUNET_CREDENTIAL_Delegation *dd,
194                                              unsigned int c_count,
195                                              const struct GNUNET_CREDENTIAL_Credential *cd)
196 {
197   unsigned int i;
198   size_t ret;
199
200   ret = sizeof (struct ChainEntry) * (d_count);
201   ret += sizeof (struct ChainEntry) * (c_count);
202
203   for (i=0; i<d_count;i++)
204   {
205     GNUNET_assert ((ret +
206                     dd[i].issuer_attribute_len +
207                     dd[i].subject_attribute_len) >= ret);
208     ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
209   }
210   for (i=0; i<c_count;i++)
211   {
212     GNUNET_assert ((ret + cd[i].issuer_attribute_len) >= ret);
213     ret += cd[i].issuer_attribute_len;
214   }
215   return ret;
216 }
217
218 /**
219  * Serizalize the given delegation chain entries and credential
220  *
221  * @param d_count number of delegation chain entries
222  * @param dd array of #GNUNET_CREDENTIAL_Delegation
223  * @param c_count number of credential entries
224  * @param cd a #GNUNET_CREDENTIAL_Credential
225  * @param dest_size size of the destination
226  * @param dest where to store the result
227  * @return the size of the data, -1 on failure
228  */
229 ssize_t
230 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
231                                               const struct GNUNET_CREDENTIAL_Delegation *dd,
232                                               unsigned int c_count,
233                                               const struct GNUNET_CREDENTIAL_Credential *cd,
234                                               size_t dest_size,
235                                               char *dest)
236 {
237   struct ChainEntry rec;
238   unsigned int i;
239   size_t off;
240
241   off = 0;
242   for (i=0;i<d_count;i++)
243   {
244     rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
245     rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
246     rec.issuer_key = dd[i].issuer_key;
247     rec.subject_key = dd[i].subject_key;
248     if (off + sizeof (rec) > dest_size)
249       return -1;
250     GNUNET_memcpy (&dest[off],
251                    &rec,
252                    sizeof (rec));
253     off += sizeof (rec);
254     if (off + dd[i].issuer_attribute_len > dest_size)
255       return -1;
256     GNUNET_memcpy (&dest[off],
257                    dd[i].issuer_attribute,
258                    dd[i].issuer_attribute_len);
259     off += dd[i].issuer_attribute_len;
260     if (0 == dd[i].subject_attribute_len)
261       continue;
262     if (off + dd[i].subject_attribute_len > dest_size)
263       return -1;
264     GNUNET_memcpy (&dest[off],
265                    dd[i].subject_attribute,
266                    dd[i].subject_attribute_len);
267     off += dd[i].subject_attribute_len;
268   }
269   for (i=0;i<c_count;i++)
270   {
271     rec.issuer_attribute_len = htonl ((uint32_t) cd[i].issuer_attribute_len);
272     rec.subject_attribute_len = htonl (0);
273     rec.issuer_key = cd[i].issuer_key;
274     rec.subject_key = cd[i].subject_key;
275     if (off + sizeof (rec) > dest_size)
276       return -1;
277     GNUNET_memcpy (&dest[off],
278                    &rec,
279                    sizeof (rec));
280     off += sizeof (rec);
281     if (off + cd[i].issuer_attribute_len > dest_size)
282       return -1;
283     GNUNET_memcpy (&dest[off],
284                    cd[i].issuer_attribute,
285                    cd[i].issuer_attribute_len);
286     off += cd[i].issuer_attribute_len;
287   }
288
289   return off;
290 }
291
292
293 /**
294  * Deserialize the given destination
295  *
296  * @param len size of the serialized delegation chain and cred
297  * @param src the serialized data
298  * @param d_count the number of delegation chain entries
299  * @param dd where to put the delegation chain entries
300  * @param c_count the number of credential entries
301  * @param cd where to put the credential data
302  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
303  */
304 int
305 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
306                                                 const char *src,
307                                                 unsigned int d_count,
308                                                 struct GNUNET_CREDENTIAL_Delegation *dd,
309                                                 unsigned int c_count,
310                                                 struct GNUNET_CREDENTIAL_Credential *cd)
311 {
312   struct ChainEntry rec;
313   unsigned int i;
314   size_t off;
315
316   off = 0;
317   for (i=0;i<d_count;i++)
318   {
319     if (off + sizeof (rec) > len)
320       return GNUNET_SYSERR;
321     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
322     dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
323     dd[i].issuer_key = rec.issuer_key;
324     dd[i].subject_key = rec.subject_key;
325     off += sizeof (rec);
326     if (off + dd[i].issuer_attribute_len > len)
327       return GNUNET_SYSERR;
328     dd[i].issuer_attribute = &src[off];
329     off += dd[i].issuer_attribute_len;
330     dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
331     if (off + dd[i].subject_attribute_len > len)
332       return GNUNET_SYSERR;
333     dd[i].subject_attribute = &src[off];
334     off += dd[i].subject_attribute_len;
335   }
336   for (i=0;i<c_count;i++)
337   {
338     if (off + sizeof (rec) > len)
339       return GNUNET_SYSERR;
340     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
341     cd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
342     cd[i].issuer_key = rec.issuer_key;
343     cd[i].subject_key = rec.subject_key;
344     off += sizeof (rec);
345     if (off + cd[i].issuer_attribute_len > len)
346       return GNUNET_SYSERR;
347     cd[i].issuer_attribute = &src[off];
348     off += cd[i].issuer_attribute_len;
349   }
350   return GNUNET_OK;
351 }
352
353 /* end of credential_serialization.c */