-towards type4
[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 cd a #GNUNET_CREDENTIAL_Credential
188  * @return the required size to serialize
189  */
190 size_t
191 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
192                                              const struct GNUNET_CREDENTIAL_Delegation *dd,
193                                              const struct GNUNET_CREDENTIAL_Credential *cd)
194 {
195   unsigned int i;
196   size_t ret;
197
198   ret = sizeof (struct ChainEntry) * (d_count + 1);
199
200   for (i=0; i<d_count;i++)
201   {
202     GNUNET_assert ((ret +
203                     dd[i].issuer_attribute_len +
204                     dd[i].subject_attribute_len) >= ret);
205     ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
206   }
207   GNUNET_assert ((ret + cd->issuer_attribute_len) >= ret);
208   ret += cd->issuer_attribute_len;
209   return ret;
210 }
211
212 /**
213  * Serizalize the given delegation chain entries and credential
214  *
215  * @param d_count number of delegation chain entries
216  * @param dd array of #GNUNET_CREDENTIAL_Delegation
217  * @param cd a #GNUNET_CREDENTIAL_Credential
218  * @param dest_size size of the destination
219  * @param dest where to store the result
220  * @return the size of the data, -1 on failure
221  */
222 ssize_t
223 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
224                                               const struct GNUNET_CREDENTIAL_Delegation *dd,
225                                               const struct GNUNET_CREDENTIAL_Credential *cd,
226                                               size_t dest_size,
227                                               char *dest)
228 {
229   struct ChainEntry rec;
230   unsigned int i;
231   size_t off;
232
233   off = 0;
234   for (i=0;i<d_count;i++)
235   {
236     rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
237     rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
238     rec.issuer_key = dd[i].issuer_key;
239     rec.subject_key = dd[i].subject_key;
240     if (off + sizeof (rec) > dest_size)
241       return -1;
242     GNUNET_memcpy (&dest[off],
243                    &rec,
244                    sizeof (rec));
245     off += sizeof (rec);
246     if (off + dd[i].issuer_attribute_len > dest_size)
247       return -1;
248     GNUNET_memcpy (&dest[off],
249                    dd[i].issuer_attribute,
250                    dd[i].issuer_attribute_len);
251     off += dd[i].issuer_attribute_len;
252     if (0 == dd[i].subject_attribute_len)
253       continue;
254     if (off + dd[i].subject_attribute_len > dest_size)
255       return -1;
256     GNUNET_memcpy (&dest[off],
257                    dd[i].subject_attribute,
258                    dd[i].subject_attribute_len);
259     off += dd[i].subject_attribute_len;
260   }
261   rec.issuer_attribute_len = htonl ((uint32_t) cd->issuer_attribute_len);
262   rec.subject_attribute_len = htonl (0);
263   rec.issuer_key = cd->issuer_key;
264   if (off + sizeof (rec) > dest_size)
265     return -1;
266   GNUNET_memcpy (&dest[off],
267                  &rec,
268                  sizeof (rec));
269   off += sizeof (rec);
270   if (off + cd->issuer_attribute_len > dest_size)
271     return -1;
272   GNUNET_memcpy (&dest[off],
273                  cd->issuer_attribute,
274                  cd->issuer_attribute_len);
275   off += cd->issuer_attribute_len;
276
277   return off;
278 }
279
280
281 /**
282  * Deserialize the given destination
283  *
284  * @param len size of the serialized delegation chain and cred
285  * @param src the serialized data
286  * @param d_count the number of delegation chain entries
287  * @param dd where to put the delegation chain entries
288  * @param cd where to put the credential data
289  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
290  */
291 int
292 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
293                                                 const char *src,
294                                                 unsigned int d_count,
295                                                 struct GNUNET_CREDENTIAL_Delegation *dd,
296                                                 struct GNUNET_CREDENTIAL_Credential *cd)
297 {
298   struct ChainEntry rec;
299   unsigned int i;
300   size_t off;
301
302   off = 0;
303   for (i=0;i<d_count;i++)
304   {
305     if (off + sizeof (rec) > len)
306       return GNUNET_SYSERR;
307     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
308     dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
309     dd[i].issuer_key = rec.issuer_key;
310     dd[i].subject_key = rec.subject_key;
311     off += sizeof (rec);
312     if (off + dd[i].issuer_attribute_len > len)
313       return GNUNET_SYSERR;
314     dd[i].issuer_attribute = &src[off];
315     off += dd[i].issuer_attribute_len;
316     dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
317     if (off + dd[i].subject_attribute_len > len)
318       return GNUNET_SYSERR;
319     dd[i].subject_attribute = &src[off];
320     off += dd[i].subject_attribute_len;
321   }
322   if (off + sizeof (rec) > len)
323     return GNUNET_SYSERR;
324   GNUNET_memcpy (&rec, &src[off], sizeof (rec));
325   cd->issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
326   cd->issuer_key = rec.issuer_key;
327   cd->subject_key = rec.subject_key;
328   off += sizeof (rec);
329   if (off + cd->issuer_attribute_len > len)
330     return GNUNET_SYSERR;
331   cd->issuer_attribute = &src[off];
332   off += cd->issuer_attribute_len;
333   return GNUNET_OK;
334 }
335
336 /* end of credential_serialization.c */