-add serialization
[oweals/gnunet.git] / src / util / crypto_abe.c
1 /*
2      This file is part of GNUnet.  Copyright (C) 2001-2014 Christian Grothoff
3      (and other contributing authors)
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 util/crypto_random.c
24  * @brief functions to gather random numbers
25  * @author Christian Grothoff
26  */
27
28
29 #include "platform.h"
30 #include <glib.h>
31 #include <openssl/aes.h>
32 #include <openssl/sha.h>
33 #include <pbc/pbc.h>
34 #include <bswabe.h>
35
36 #include "gnunet_crypto_lib.h"
37
38 struct GNUNET_CRYPTO_AbeMasterKey
39 {
40   GByteArray* pub;
41
42   GByteArray* msk;
43 };
44
45 struct GNUNET_CRYPTO_AbeKey
46 {
47   GByteArray* pub;
48   GByteArray* prv;
49 };
50
51 static void
52 init_aes( element_t k, int enc, AES_KEY* key, unsigned char* iv )
53 {
54   int key_len;
55   unsigned char* key_buf;
56
57   key_len = element_length_in_bytes(k) < 17 ? 17 : element_length_in_bytes(k);
58   key_buf = (unsigned char*) malloc(key_len);
59   element_to_bytes(key_buf, k);
60
61   if( enc )
62     AES_set_encrypt_key(key_buf + 1, 128, key);
63   else
64     AES_set_decrypt_key(key_buf + 1, 128, key);
65   free(key_buf);
66
67   memset(iv, 0, 16);
68 }
69
70 static GByteArray*
71 aes_128_cbc_encrypt( GByteArray* pt, element_t k )
72 {
73   AES_KEY key;
74   unsigned char iv[16];
75   GByteArray* ct;
76   guint8 len[4];
77   guint8 zero;
78
79   init_aes(k, 1, &key, iv);
80
81   /* TODO make less crufty */
82
83   /* stuff in real length (big endian) before padding */
84   len[0] = (pt->len & 0xff000000)>>24;
85   len[1] = (pt->len & 0xff0000)>>16;
86   len[2] = (pt->len & 0xff00)>>8;
87   len[3] = (pt->len & 0xff)>>0;
88   g_byte_array_prepend(pt, len, 4);
89
90   /* pad out to multiple of 128 bit (16 byte) blocks */
91   zero = 0;
92   while( pt->len % 16 )
93     g_byte_array_append(pt, &zero, 1);
94
95   ct = g_byte_array_new();
96   g_byte_array_set_size(ct, pt->len);
97
98   AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT);
99
100   return ct;
101 }
102
103 static GByteArray*
104 aes_128_cbc_decrypt( GByteArray* ct, element_t k )
105 {
106   AES_KEY key;
107   unsigned char iv[16];
108   GByteArray* pt;
109   unsigned int len;
110
111   init_aes(k, 0, &key, iv);
112
113   pt = g_byte_array_new();
114   g_byte_array_set_size(pt, ct->len);
115
116   AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT);
117
118   /* TODO make less crufty */
119   
120   /* get real length */
121   len = 0;
122   len = len
123     | ((pt->data[0])<<24) | ((pt->data[1])<<16)
124     | ((pt->data[2])<<8)  | ((pt->data[3])<<0);
125   g_byte_array_remove_index(pt, 0);
126   g_byte_array_remove_index(pt, 0);
127   g_byte_array_remove_index(pt, 0);
128   g_byte_array_remove_index(pt, 0);
129
130   /* truncate any garbage from the padding */
131   g_byte_array_set_size(pt, len);
132
133   return pt;
134 }
135
136 struct GNUNET_CRYPTO_AbeMasterKey*
137 GNUNET_CRYPTO_cpabe_create_master_key (void)
138 {
139   struct GNUNET_CRYPTO_AbeMasterKey* key;
140   bswabe_msk_t* msk;
141   bswabe_pub_t* pub;
142   bswabe_setup(&pub, &msk);
143   key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
144   key->pub = bswabe_pub_serialize(pub);
145   key->msk = bswabe_msk_serialize(msk);
146   GNUNET_assert (NULL != key->pub);
147   GNUNET_assert (NULL != key->msk);
148   return key;
149 }
150
151 struct GNUNET_CRYPTO_AbeKey*
152 GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *key,
153                              char **attrs)
154 {
155   struct GNUNET_CRYPTO_AbeKey *prv_key;
156   bswabe_pub_t* pub;
157   bswabe_msk_t* msk;
158   bswabe_prv_t* prv;
159   gchar* pub_data;
160   gsize len;
161
162   pub = bswabe_pub_unserialize(key->pub, 0);
163   msk = bswabe_msk_unserialize(pub, key->msk, 0);
164   prv = bswabe_keygen(pub, msk, attrs);
165   prv_key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
166   prv_key->prv = bswabe_prv_serialize(prv);
167   pub_data = g_strndup ((gchar*)key->pub->data,
168                         key->pub->len);
169   len = key->pub->len;
170   prv_key->pub = g_byte_array_new_take ((guint8*)pub_data, len);
171   GNUNET_assert (NULL != prv_key->prv);
172   return prv_key;
173 }
174
175 ssize_t
176 write_cpabe (void **result, GByteArray* cph_buf,
177              int file_len, GByteArray* aes_buf)
178 {
179   char *ptr;
180   int i;
181   ssize_t size;
182   size = aes_buf->len + cph_buf->len + 12;
183   *result = GNUNET_malloc (size);
184   ptr = *result;
185   for(i=3; i >= 0; i--) {
186     *ptr = (file_len & 0xff<<(i*8))>>(i*8);
187     ptr++;
188   }
189   for(i=3; i >= 0; i--) {
190     *ptr = (aes_buf->len & 0xff<<(i*8))>>(i*8);
191     ptr++;
192   }
193   memcpy (ptr, aes_buf->data, aes_buf->len);
194   ptr += aes_buf->len;
195   for(i=3; i >= 0; i--) {
196     *ptr = (cph_buf->len & 0xff<<(i*8))>>(i*8);
197     ptr++;
198   }
199   memcpy (ptr, cph_buf->data, cph_buf->len);
200   return size;
201 }
202
203 ssize_t
204 read_cpabe (const void *data, GByteArray** cph_buf, GByteArray** aes_buf)
205 {
206   int i;
207   ssize_t buf_len;
208   ssize_t tmp_len;
209   char *ptr;
210
211   *cph_buf = g_byte_array_new();
212   *aes_buf = g_byte_array_new();
213   ptr = (char*)data;
214
215   buf_len = 0;
216   for(i=3; i >= 0; i--) {
217     buf_len |= *ptr<<(i*8);
218     ptr++;
219   }
220
221   tmp_len = 0;
222   for(i=3; i >= 0; i--) {
223     tmp_len |= *ptr<<(i*8);
224     ptr++;
225   }
226   g_byte_array_set_size(*aes_buf, tmp_len);
227   memcpy((*aes_buf)->data, ptr, tmp_len);
228   ptr += tmp_len;
229   tmp_len = 0;
230   for(i=3; i >= 0; i--) {
231     tmp_len |= *ptr<<(i*8);
232     ptr++;
233   }
234   g_byte_array_set_size(*cph_buf, tmp_len);
235   memcpy((*cph_buf)->data, ptr, tmp_len);
236
237   return buf_len;
238 }
239
240 ssize_t
241 GNUNET_CRYPTO_cpabe_encrypt (const void *block,
242                              size_t size,
243                              char *policy,
244                              const struct GNUNET_CRYPTO_AbeMasterKey *key,
245                              void **result)
246 {
247   bswabe_pub_t* pub;
248   bswabe_cph_t* cph;
249   GByteArray* plt;
250   GByteArray* cph_buf;
251   GByteArray* aes_buf;
252   guint8 *data;
253   element_t m;
254   size_t payload_len;
255   ssize_t result_len;
256   pub = bswabe_pub_unserialize(key->pub, 0);
257   if( !(cph = bswabe_enc(pub, m, policy)) )
258     return GNUNET_SYSERR;
259   cph_buf = bswabe_cph_serialize(cph);
260   bswabe_cph_free(cph);
261   data = g_memdup (block, size);
262   plt = g_byte_array_new_take (data, size);
263   payload_len = plt->len;
264   aes_buf = aes_128_cbc_encrypt(plt, m);
265   g_byte_array_free(plt, 1);
266   element_clear(m);
267   result_len = write_cpabe(result, cph_buf, payload_len, aes_buf);
268   g_byte_array_free(cph_buf, 1);
269   g_byte_array_free(aes_buf, 1);
270   return result_len;
271 }
272
273 ssize_t
274 GNUNET_CRYPTO_cpabe_decrypt (const void *block,
275                        size_t size,
276                        const struct GNUNET_CRYPTO_AbeKey *key,
277                        void **result)
278 {
279   bswabe_pub_t* pub;
280   bswabe_prv_t* prv;
281   GByteArray* aes_buf;
282   GByteArray* plt;
283   GByteArray* cph_buf;
284   bswabe_cph_t* cph;
285   element_t m;
286   ssize_t pt_size;
287
288   pub = bswabe_pub_unserialize(key->pub, 0);
289   prv = bswabe_prv_unserialize(pub, key->prv, 0);
290   pt_size = read_cpabe(block, &cph_buf, &aes_buf);
291   cph = bswabe_cph_unserialize(pub, cph_buf, 0);
292   if( !bswabe_dec(pub, prv, cph, m) ) {
293     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
294                 "%s\n", bswabe_error());
295     return GNUNET_SYSERR;
296   }
297   bswabe_cph_free(cph);
298   plt = aes_128_cbc_decrypt(aes_buf, m);
299   g_byte_array_set_size(plt, size);
300   g_byte_array_free(aes_buf, 1);
301   *result = GNUNET_malloc (plt->len);
302   GNUNET_memcpy (*result, plt->data, plt->len);
303   
304   return pt_size;
305 }
306
307 ssize_t
308 GNUNET_CRYPTO_cpabe_serialize_key (struct GNUNET_CRYPTO_AbeKey *key,
309                                    void **result)
310 {
311   ssize_t len;
312
313   len = key->pub->len + key->prv->len + 12;
314   write_cpabe (result, key->pub, len, key->prv);
315
316   return len;
317 }
318
319 struct GNUNET_CRYPTO_AbeKey*
320 GNUNET_CRYPTO_cpabe_deserialize_key (void *data,
321                                      size_t len)
322 {
323   struct GNUNET_CRYPTO_AbeKey *key;
324
325   key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
326   read_cpabe (data, &key->pub, &key->prv);
327
328   return key;
329 }
330
331 ssize_t
332 GNUNET_CRYPTO_cpabe_serialize_master_key (struct GNUNET_CRYPTO_AbeMasterKey *key,
333                                           void **result)
334 {
335   ssize_t len;
336
337   len = key->pub->len + key->msk->len + 12;
338   write_cpabe (result, key->pub, len, key->msk);
339
340   return len;
341 }
342
343 struct GNUNET_CRYPTO_AbeMasterKey*
344 GNUNET_CRYPTO_cpabe_deserialize_master_key (void *data,
345                                             size_t len)
346 {
347   struct GNUNET_CRYPTO_AbeMasterKey *key;
348
349   key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey);
350   read_cpabe (data, &key->pub, &key->msk);
351
352   return key;
353 }