2fbcebd9ff62bc86f1c03bf52ebf79c2a1d63479
[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 NetworkRecord
36 {
37   /**
38    * Issuer key
39    */
40   struct GNUNET_CRYPTO_EcdsaPublicKey issuer_key;
41   
42   /**
43    * Subject key
44    */
45   struct GNUNET_CRYPTO_EcdsaPublicKey subject_key;
46   
47   /**
48    * Issuer attributes
49    */
50   uint32_t issuer_attribute_len GNUNET_PACKED;
51   
52   /**
53    * Subject attributes
54    */
55   uint32_t subject_attribute_len GNUNET_PACKED;
56 };
57
58 GNUNET_NETWORK_STRUCT_END
59
60 /**
61  * Calculate how many bytes we will need to serialize
62  * the given delegation chain and credential
63  *
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  * @return the required size to serialize
68  */
69 size_t
70 GNUNET_CREDENTIAL_delegation_chain_get_size (unsigned int d_count,
71                                              const struct GNUNET_CREDENTIAL_Delegation *dd,
72                                              const struct GNUNET_CREDENTIAL_Credential *cd)
73 {
74   unsigned int i;
75   size_t ret;
76
77   ret = sizeof (struct NetworkRecord) * (d_count + 1);
78
79   for (i=0; i<d_count;i++)
80   {
81     GNUNET_assert ((ret +
82                     dd[i].issuer_attribute_len +
83                     dd[i].subject_attribute_len) >= ret);
84     ret += dd[i].issuer_attribute_len + dd[i].subject_attribute_len;
85   }
86   GNUNET_assert ((ret + cd->issuer_attribute_len) >= ret);
87   ret += cd->issuer_attribute_len;
88   return ret;
89 }
90
91 /**
92  * Serizalize the given delegation chain entries and credential
93  *
94  * @param d_count number of delegation chain entries
95  * @param dd array of #GNUNET_CREDENTIAL_Delegation
96  * @param cd a #GNUNET_CREDENTIAL_Credential
97  * @param dest_size size of the destination
98  * @param dest where to store the result
99  * @return the size of the data, -1 on failure
100  */
101 ssize_t
102 GNUNET_CREDENTIAL_delegation_chain_serialize (unsigned int d_count,
103                                               const struct GNUNET_CREDENTIAL_Delegation *dd,
104                                               const struct GNUNET_CREDENTIAL_Credential *cd,
105                                               size_t dest_size,
106                                               char *dest)
107 {
108   struct NetworkRecord rec;
109   unsigned int i;
110   size_t off;
111
112   off = 0;
113   for (i=0;i<d_count;i++)
114   {
115     rec.issuer_attribute_len = htonl ((uint32_t) dd[i].issuer_attribute_len);
116     rec.subject_attribute_len = htonl ((uint32_t) dd[i].subject_attribute_len);
117     rec.issuer_key = dd[i].issuer_key;
118     rec.subject_key = dd[i].subject_key;
119     if (off + sizeof (rec) > dest_size)
120       return -1;
121     GNUNET_memcpy (&dest[off],
122                    &rec,
123                    sizeof (rec));
124     off += sizeof (rec);
125     if (off + dd[i].issuer_attribute_len > dest_size)
126       return -1;
127     GNUNET_memcpy (&dest[off],
128                    dd[i].issuer_attribute,
129                    dd[i].issuer_attribute_len);
130     off += dd[i].issuer_attribute_len;
131     if (0 == dd[i].subject_attribute_len)
132       continue;
133     if (off + dd[i].subject_attribute_len > dest_size)
134       return -1;
135     GNUNET_memcpy (&dest[off],
136                    dd[i].subject_attribute,
137                    dd[i].subject_attribute_len);
138     off += dd[i].subject_attribute_len;
139   }
140   rec.issuer_attribute_len = htonl ((uint32_t) cd->issuer_attribute_len);
141   rec.subject_attribute_len = htonl (0);
142   rec.issuer_key = cd->issuer_key;
143   if (off + sizeof (rec) > dest_size)
144     return -1;
145   GNUNET_memcpy (&dest[off],
146                  &rec,
147                  sizeof (rec));
148   off += sizeof (rec);
149   if (off + cd->issuer_attribute_len > dest_size)
150     return -1;
151   GNUNET_memcpy (&dest[off],
152                  cd->issuer_attribute,
153                  cd->issuer_attribute_len);
154   off += cd->issuer_attribute_len;
155
156   return off;
157 }
158
159
160 /**
161  * Deserialize the given destination
162  *
163  * @param len size of the serialized delegation chain and cred
164  * @param src the serialized data
165  * @param d_count the number of delegation chain entries
166  * @param dd where to put the delegation chain entries
167  * @param cd where to put the credential data
168  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
169  */
170 int
171 GNUNET_CREDENTIAL_delegation_chain_deserialize (size_t len,
172                                                 const char *src,
173                                                 unsigned int d_count,
174                                                 struct GNUNET_CREDENTIAL_Delegation *dd,
175                                                 struct GNUNET_CREDENTIAL_Credential *cd)
176 {
177   struct NetworkRecord rec;
178   unsigned int i;
179   size_t off;
180
181   off = 0;
182   for (i=0;i<d_count;i++)
183   {
184     if (off + sizeof (rec) > len)
185       return GNUNET_SYSERR;
186     GNUNET_memcpy (&rec, &src[off], sizeof (rec));
187     dd[i].issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
188     dd[i].issuer_key = rec.issuer_key;
189     dd[i].subject_key = rec.subject_key;
190     off += sizeof (rec);
191     if (off + dd[i].issuer_attribute_len > len)
192       return GNUNET_SYSERR;
193     dd[i].issuer_attribute = &src[off];
194     off += dd[i].issuer_attribute_len;
195     dd[i].subject_attribute_len = ntohl ((uint32_t) rec.subject_attribute_len);
196     if (off + dd[i].subject_attribute_len > len)
197       return GNUNET_SYSERR;
198     dd[i].subject_attribute = &src[off];
199     off += dd[i].subject_attribute_len;
200   }
201   if (off + sizeof (rec) > len)
202     return GNUNET_SYSERR;
203   GNUNET_memcpy (&rec, &src[off], sizeof (rec));
204   cd->issuer_attribute_len = ntohl ((uint32_t) rec.issuer_attribute_len);
205   cd->issuer_key = rec.issuer_key;
206   cd->subject_key = rec.subject_key;
207   off += sizeof (rec);
208   if (off + cd->issuer_attribute_len > len)
209     return GNUNET_SYSERR;
210   cd->issuer_attribute = &src[off];
211   off += cd->issuer_attribute_len;
212   return GNUNET_OK;
213 }
214
215 /* end of credential_serialization.c */