- More heavy refactoring. Probably lots of broken things to see here.
[oweals/gnunet.git] / src / identity-provider / identity_token.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2010-2015 Christian Grothoff (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  * @file identity-token/identity_token.c
23  * @brief helper library to manage identity tokens
24  * @author Martin Schanzenbach
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_signatures.h"
29 #include "identity_token.h"
30 #include <jansson.h>
31
32
33 /**
34  * Crypto helper functions
35  */
36
37 static int
38 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
39                          struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
40                          struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
41 {
42   struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
43
44   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
45                              &new_key_hash_str);
46   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
47   static const char ctx_key[] = "gnuid-aes-ctx-key";
48   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
49                      new_key_hash, sizeof (struct GNUNET_HashCode),
50                      ctx_key, strlen (ctx_key),
51                      NULL, 0);
52   static const char ctx_iv[] = "gnuid-aes-ctx-iv";
53   GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
54                      new_key_hash, sizeof (struct GNUNET_HashCode),
55                      ctx_iv, strlen (ctx_iv),
56                      NULL, 0);
57   return GNUNET_OK;
58 }
59
60
61
62 /**
63  * Decrypts metainfo part from a token code
64  */
65 static int
66 decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
67                    const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key,
68                    const char *cyphertext,
69                    size_t cyphertext_len,
70                    char **result_str)
71 {
72   struct GNUNET_HashCode new_key_hash;
73   struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
74   struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
75
76   char *str_buf = GNUNET_malloc (cyphertext_len);
77   size_t str_size;
78
79   //Calculate symmetric key from ecdh parameters
80   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key,
81                                                         ecdh_key,
82                                                         &new_key_hash));
83
84   create_sym_key_from_ecdh (&new_key_hash,
85                             &enc_key,
86                             &enc_iv);
87
88   str_size = GNUNET_CRYPTO_symmetric_decrypt (cyphertext,
89                                               cyphertext_len,
90                                               &enc_key,
91                                               &enc_iv,
92                                               str_buf);
93   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Decrypted bytes: %d Expected bytes: %d\n", str_size, cyphertext_len);
94   if (-1 == str_size)
95   {
96     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
97     GNUNET_free (str_buf);
98     return GNUNET_SYSERR;
99   }
100   *result_str = GNUNET_malloc (str_size+1);
101   memcpy (*result_str, str_buf, str_size);
102   (*result_str)[str_size] = '\0';
103   GNUNET_free (str_buf);
104   return GNUNET_OK;
105
106 }
107
108 /**
109  * Decrypt string using pubkey and ECDHE
110 */
111 static int
112 decrypt_str_ecdhe2 (const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey,
113                     const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
114                     const char *ciphertext,
115                     size_t ciphertext_len,
116                     char **plaintext)
117 {
118   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
119   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
120   struct GNUNET_HashCode new_key_hash;
121
122   //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
123   *plaintext = GNUNET_malloc (ciphertext_len);
124
125   // Derived key K = H(eB)
126   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey,
127                                                         aud_key,
128                                                         &new_key_hash));
129   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
130   GNUNET_CRYPTO_symmetric_decrypt (ciphertext,
131                                    ciphertext_len,
132                                    &skey, &iv,
133                                    *plaintext);
134   return GNUNET_OK;
135 }
136
137
138 /**
139  * Encrypt string using pubkey and ECDHE
140  * Returns ECDHE pubkey to be used for decryption
141  */
142 static int
143 encrypt_str_ecdhe (const char *plaintext,
144                    const struct GNUNET_CRYPTO_EcdsaPublicKey *pub_key,
145                    char **cyphertext,
146                    struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
147                    struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey)
148 {
149   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
150   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
151   struct GNUNET_HashCode new_key_hash;
152   ssize_t enc_size;
153
154   // ECDH keypair E = eG
155   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
156   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
157                                       ecdh_pubkey);
158
159   //This is true see documentation for GNUNET_CRYPTO_symmetric_encrypt
160   *cyphertext = GNUNET_malloc (strlen (plaintext));
161
162   // Derived key K = H(eB)
163   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
164                                                         pub_key,
165                                                         &new_key_hash));
166   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
167   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypting string %s\n (len=%d)",
168               plaintext,
169               strlen (plaintext));
170   enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext, strlen (plaintext),
171                                               &skey, &iv,
172                                               *cyphertext);
173   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypted (len=%d)", enc_size);
174   return GNUNET_OK;
175 }
176
177
178
179
180 /**
181  * Identity Token API
182  */
183
184
185 /**
186  * Create an Identity Token
187  *
188  * @param type the JSON API resource type
189  * @param id the JSON API resource id
190  * @return a new JSON API resource or NULL on error.
191  */
192 struct IdentityToken*
193 token_create (const struct GNUNET_CRYPTO_EcdsaPublicKey* iss,
194                                        const struct GNUNET_CRYPTO_EcdsaPublicKey* aud)
195 {
196   struct IdentityToken *token;
197   char* audience;
198   char* issuer;
199
200   issuer = GNUNET_STRINGS_data_to_string_alloc (iss,
201                                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
202   audience = GNUNET_STRINGS_data_to_string_alloc (aud,
203                                                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
204
205
206
207   token = GNUNET_malloc (sizeof (struct IdentityToken));
208
209   token->header = json_object();
210   token->payload = json_object();
211
212   json_object_set_new (token->header, "alg", json_string ("ED512"));
213   json_object_set_new (token->header, "typ", json_string ("JWT"));
214
215   json_object_set_new (token->payload, "iss", json_string (issuer));
216   json_object_set_new (token->payload, "aud", json_string (audience));
217   json_object_set_new (token->payload, "sub", json_string (issuer));
218
219   token->aud_key = *aud;
220   GNUNET_free (issuer);
221   GNUNET_free (audience);
222   return token;
223 }
224
225 void
226 token_destroy (struct IdentityToken *token)
227 {
228   json_decref (token->header);
229   json_decref (token->payload);
230   GNUNET_free (token);
231 }
232
233 void
234 token_add_attr (const struct IdentityToken *token,
235                                          const char* key,
236                                          const char* value)
237 {
238   GNUNET_assert (NULL != token);
239   GNUNET_assert (NULL != token->payload);
240
241   json_object_set_new (token->payload, key, json_string (value));
242 }
243
244 void
245 token_add_json (const struct IdentityToken *token,
246                                          const char* key,
247                                          json_t* value)
248 {
249   GNUNET_assert (NULL != token);
250   GNUNET_assert (NULL != token->payload);
251
252   json_object_set_new (token->payload, key, value);
253 }
254
255
256 int
257 token_parse2 (const char* raw_data,
258                                        const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
259                                        const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
260                                        struct IdentityToken **result)
261 {
262   char *enc_token_str;
263   char *tmp_buf;
264   char *token_str;
265   char *enc_token;
266   char *header;
267   char *header_base64;
268   char *payload;
269   char *payload_base64;
270   size_t enc_token_len;
271   json_error_t err_json;
272
273   GNUNET_asprintf (&tmp_buf, "%s", raw_data);
274   strtok (tmp_buf, ",");
275   enc_token_str = strtok (NULL, ",");
276
277   enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
278                                                 strlen (enc_token_str),
279                                                 &enc_token);
280   if (GNUNET_OK != decrypt_str_ecdhe2 (priv_key,
281                                        aud_key,
282                                        enc_token,
283                                        enc_token_len,
284                                        &token_str))
285   {
286     GNUNET_free (tmp_buf);
287     GNUNET_free (enc_token);
288     return GNUNET_SYSERR;
289   }
290
291   header_base64 = strtok (token_str, ".");
292   payload_base64 = strtok (NULL, ".");
293
294   GNUNET_STRINGS_base64_decode (header_base64,
295                                 strlen (header_base64),
296                                 &header);
297   GNUNET_STRINGS_base64_decode (payload_base64,
298                                 strlen (payload_base64),
299                                 &payload);
300   //TODO signature
301
302
303   *result = GNUNET_malloc (sizeof (struct IdentityToken));
304   (*result)->aud_key =  *aud_key;
305   (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
306   (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
307   GNUNET_free (enc_token);
308   GNUNET_free (token_str);
309   GNUNET_free (tmp_buf);
310   GNUNET_free (payload);
311   GNUNET_free (header);
312   return GNUNET_OK;
313 }
314
315 int
316 token_parse (const char* raw_data,
317                                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
318                                       struct IdentityToken **result)
319 {
320   char *ecdh_pubkey_str;
321   char *enc_token_str;
322   char *tmp_buf;
323   char *token_str;
324   char *enc_token;
325   char *header;
326   char *header_base64;
327   char *payload;
328   char *payload_base64;
329   size_t enc_token_len;
330   json_error_t err_json;
331   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
332
333   GNUNET_asprintf (&tmp_buf, "%s", raw_data);
334   ecdh_pubkey_str = strtok (tmp_buf, ",");
335   enc_token_str = strtok (NULL, ",");
336
337   GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
338                                  strlen (ecdh_pubkey_str),
339                                  &ecdh_pubkey,
340                                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
341   enc_token_len = GNUNET_STRINGS_base64_decode (enc_token_str,
342                                                 strlen (enc_token_str),
343                                                 &enc_token);
344   if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
345                                       &ecdh_pubkey,
346                                       enc_token,
347                                       enc_token_len,
348                                       &token_str))
349   {
350     GNUNET_free (tmp_buf);
351     GNUNET_free (enc_token);
352     return GNUNET_SYSERR;
353   }
354
355   header_base64 = strtok (token_str, ".");
356   payload_base64 = strtok (NULL, ".");
357
358   GNUNET_STRINGS_base64_decode (header_base64,
359                                 strlen (header_base64),
360                                 &header);
361   GNUNET_STRINGS_base64_decode (payload_base64,
362                                 strlen (payload_base64),
363                                 &payload);
364   //TODO signature and aud key
365
366
367   *result = GNUNET_malloc (sizeof (struct IdentityToken));
368   (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
369   (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
370   GNUNET_free (enc_token);
371   GNUNET_free (token_str);
372   GNUNET_free (tmp_buf);
373   GNUNET_free (payload);
374   GNUNET_free (header);
375   return GNUNET_OK;
376 }
377
378 int
379 token_to_string (const struct IdentityToken *token,
380                                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
381                                           char **result)
382 {
383   char *payload_str;
384   char *header_str;
385   char *payload_base64;
386   char *header_base64;
387   char *padding;
388   char *signature_target;
389   char *signature_str;
390   struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
391   header_str = json_dumps (token->header, JSON_COMPACT);
392   GNUNET_STRINGS_base64_encode (header_str,
393                                 strlen (header_str),
394                                 &header_base64);
395   //Remove GNUNET padding of base64
396   padding = strtok(header_base64, "=");
397   while (NULL != padding)
398     padding = strtok(NULL, "=");
399
400   payload_str = json_dumps (token->payload, JSON_COMPACT);
401   GNUNET_STRINGS_base64_encode (payload_str,
402                                 strlen (payload_str),
403                                 &payload_base64);
404
405   //Remove GNUNET padding of base64
406   padding = strtok(payload_base64, "=");
407   while (NULL != padding)
408     padding = strtok(NULL, "=");
409
410   GNUNET_asprintf (&signature_target, "%s,%s", header_base64, payload_base64);
411   purpose =
412     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
413                    strlen (signature_target));
414   purpose->size =
415     htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
416   purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
417   memcpy (&purpose[1], signature_target, strlen (signature_target));
418   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
419                                              purpose,
420                                              (struct GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
421   {
422     GNUNET_free (signature_target);
423     GNUNET_free (payload_str);
424     GNUNET_free (header_str);
425     GNUNET_free (payload_base64);
426     GNUNET_free (header_base64);
427     GNUNET_free (purpose);
428     return GNUNET_SYSERR;
429   }
430
431   GNUNET_STRINGS_base64_encode ((const char*)&token->signature,
432                                 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
433                                 &signature_str);
434   GNUNET_asprintf (result, "%s.%s.%s",
435                    header_base64, payload_base64, signature_str);
436   GNUNET_free (signature_target);
437   GNUNET_free (payload_str);
438   GNUNET_free (header_str);
439   GNUNET_free (signature_str);
440   GNUNET_free (payload_base64);
441   GNUNET_free (header_base64);
442   GNUNET_free (purpose);
443   return GNUNET_OK;
444 }
445
446 int
447 token_serialize (const struct IdentityToken *token,
448                                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
449                                           struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
450                                           char **result)
451 {
452   char *token_str;
453   char *enc_token;
454   char *dh_key_str;
455   char *enc_token_base64;
456   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
457
458   GNUNET_assert (GNUNET_OK == token_to_string (token,
459                                                                         priv_key,
460                                                                         &token_str));
461
462   GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
463                                                  &token->aud_key,
464                                                  &enc_token,
465                                                  ecdh_privkey,
466                                                  &ecdh_pubkey));
467   GNUNET_STRINGS_base64_encode (enc_token,
468                                 strlen (token_str),
469                                 &enc_token_base64);
470   dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey,
471                                                     sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
472   GNUNET_asprintf (result, "%s,%s", dh_key_str, enc_token_base64);
473   GNUNET_free (dh_key_str);
474   GNUNET_free (enc_token_base64);
475   GNUNET_free (enc_token);
476   GNUNET_free (token_str);
477   return GNUNET_OK;
478 }
479
480 struct TokenTicketPayload*
481 ticket_payload_create (const char* nonce,
482                                                 const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
483                                                 const char* lbl_str)
484 {
485   struct TokenTicketPayload* payload;
486
487   payload = GNUNET_malloc (sizeof (struct TokenTicketPayload));
488   GNUNET_asprintf (&payload->nonce, nonce, strlen (nonce));
489   payload->identity_key = *identity_pkey;
490   GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
491   return payload;
492 }
493
494 void
495 ticket_payload_destroy (struct TokenTicketPayload* payload)
496 {
497   GNUNET_free (payload->nonce);
498   GNUNET_free (payload->label);
499   GNUNET_free (payload);
500 }
501
502 void
503 ticket_payload_serialize (struct TokenTicketPayload *payload,
504                                                    char **result)
505 {
506   char* identity_key_str;
507
508   identity_key_str = GNUNET_STRINGS_data_to_string_alloc (&payload->identity_key,
509                                                           sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
510
511   GNUNET_asprintf (result, 
512                    "{\"nonce\": \"%u\",\"identity\": \"%s\",\"label\": \"%s\"}",
513                    payload->nonce, identity_key_str, payload->label);
514   GNUNET_free (identity_key_str);
515
516 }
517
518
519 /**
520  * Create the token code
521  * The metadata is encrypted with a share ECDH derived secret using B (aud_key)
522  * and e (ecdh_privkey)
523  * The ticket also contains E (ecdh_pubkey) and a signature over the
524  * metadata and E
525  */
526 struct TokenTicket*
527 ticket_create (const char* nonce_str,
528                                         const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
529                                         const char* lbl_str,
530                                         const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
531 {
532   struct TokenTicket *ticket;
533   struct TokenTicketPayload *code_payload;
534
535   ticket = GNUNET_malloc (sizeof (struct TokenTicket));
536   code_payload = ticket_payload_create (nonce_str,
537                                                                  identity_pkey,
538                                                                  lbl_str);
539   ticket->aud_key = *aud_key;
540   ticket->payload = code_payload;
541
542
543   return ticket;
544 }
545
546 void
547 ticket_destroy (struct TokenTicket *ticket)
548 {
549   ticket_payload_destroy (ticket->payload);
550   GNUNET_free (ticket);
551 }
552
553 int
554 ticket_serialize (struct TokenTicket *ticket,
555                                            const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
556                                            char **result)
557 {
558   char *code_payload_str;
559   char *enc_ticket_payload;
560   char *ticket_payload_str;
561   char *ticket_sig_str;
562   char *ticket_str;
563   char *dh_key_str;
564   char *write_ptr;
565   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
566
567   struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
568
569   ticket_payload_serialize (ticket->payload,
570                                                      &code_payload_str);
571
572   GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (code_payload_str,
573                                                  &ticket->aud_key,
574                                                  &enc_ticket_payload,
575                                                  &ecdhe_privkey,
576                                                  &ticket->ecdh_pubkey));
577
578   GNUNET_free (ecdhe_privkey);
579
580   purpose = 
581     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
582                    sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
583                    strlen (code_payload_str)); // E_K (code_str)
584   purpose->size = 
585     htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
586            sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
587            strlen (code_payload_str));
588   purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
589   write_ptr = (char*) &purpose[1];
590   memcpy (write_ptr,
591           &ticket->ecdh_pubkey,
592           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
593   write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
594   memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
595   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
596                                                         purpose,
597                                                        &ticket->signature));
598   GNUNET_STRINGS_base64_encode (enc_ticket_payload,
599                                 strlen (code_payload_str),
600                                 &ticket_payload_str);
601   ticket_sig_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->signature,
602                                                         sizeof (struct GNUNET_CRYPTO_EcdsaSignature));
603
604   dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
605                                                     sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
606   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
607   GNUNET_asprintf (&ticket_str, "{\"meta\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
608                    ticket_payload_str, dh_key_str, ticket_sig_str);
609   GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
610   GNUNET_free (dh_key_str);
611   GNUNET_free (purpose);
612   GNUNET_free (ticket_str);
613   GNUNET_free (ticket_sig_str);
614   GNUNET_free (code_payload_str);
615   GNUNET_free (enc_ticket_payload);
616   GNUNET_free (ticket_payload_str);
617   return GNUNET_OK;
618 }
619
620 int
621 ticket_payload_parse(const char *raw_data,
622                                               ssize_t data_len,
623                                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
624                                               const struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey,
625                                               struct TokenTicketPayload **result)
626 {
627   const char* label_str;
628   const char* nonce_str;
629   const char* identity_key_str;
630
631   json_t *root;
632   json_t *label_json;
633   json_t *identity_json;
634   json_t *nonce_json;
635   json_error_t err_json;
636   char* meta_str;
637   struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
638
639   if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
640                                       ecdhe_pkey,
641                                       raw_data,
642                                       data_len,
643                                       &meta_str))
644   {
645     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata decryption failed\n");
646     return GNUNET_SYSERR;
647   }
648
649   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata: %s\n", meta_str);
650   root = json_loads (meta_str, JSON_DECODE_ANY, &err_json);
651   if (!root)
652   {
653     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
654                 "Error parsing metadata: %s\n", err_json.text);
655     GNUNET_free (meta_str);
656     return GNUNET_SYSERR;
657   }
658
659   identity_json = json_object_get (root, "identity");
660   if (!json_is_string (identity_json))
661   {
662     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
663                 "Error parsing metadata: %s\n", err_json.text);
664     json_decref (root);
665     GNUNET_free (meta_str);
666     return GNUNET_SYSERR;
667   }
668   identity_key_str = json_string_value (identity_json);
669   GNUNET_STRINGS_string_to_data (identity_key_str,
670                                  strlen (identity_key_str),
671                                  &id_pkey,
672                                  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
673
674
675   label_json = json_object_get (root, "label");
676   if (!json_is_string (label_json))
677   {
678     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
679                 "Error parsing metadata: %s\n", err_json.text);
680     json_decref (root);
681     GNUNET_free (meta_str);
682     return GNUNET_SYSERR;
683   }
684
685   label_str = json_string_value (label_json);
686   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found label: %s\n", label_str);
687
688   nonce_json = json_object_get (root, "nonce");
689   if (!json_is_string (label_json))
690   {
691     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
692                 "Error parsing metadata: %s\n", err_json.text);
693     json_decref (root);
694     GNUNET_free (meta_str);
695     return GNUNET_SYSERR;
696   }
697
698   nonce_str = json_string_value (nonce_json);
699   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found nonce: %s\n", nonce_str);
700
701   *result = ticket_payload_create (nonce_str,
702                                                             (const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
703                                                             label_str);
704   GNUNET_free (meta_str);
705   json_decref (root);
706   return GNUNET_OK;
707
708 }
709
710 int
711 ticket_parse (const char *raw_data,
712                                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
713                                        struct TokenTicket **result)
714 {
715   const char* enc_meta_str;
716   const char* ecdh_enc_str;
717   const char* signature_enc_str;
718
719   json_t *root;
720   json_t *signature_json;
721   json_t *ecdh_json;
722   json_t *enc_meta_json;
723   json_error_t err_json;
724   char* enc_meta;
725   char* ticket_decoded;
726   char* write_ptr;
727   size_t enc_meta_len;
728   struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
729   struct TokenTicket *ticket;
730   struct TokenTicketPayload *ticket_payload;
731
732   ticket_decoded = NULL;
733   GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
734   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Token Code: %s\n", ticket_decoded);
735   root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
736   if (!root)
737   {
738     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
739                 "%s\n", err_json.text);
740     return GNUNET_SYSERR;
741   }
742
743   signature_json = json_object_get (root, "signature");
744   ecdh_json = json_object_get (root, "ecdh");
745   enc_meta_json = json_object_get (root, "meta");
746
747   signature_enc_str = json_string_value (signature_json);
748   ecdh_enc_str = json_string_value (ecdh_json);
749   enc_meta_str = json_string_value (enc_meta_json);
750
751   ticket = GNUNET_malloc (sizeof (struct TokenTicket));
752
753   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str,
754                                                   strlen (ecdh_enc_str),
755                                                   &ticket->ecdh_pubkey,
756                                                   sizeof  (struct GNUNET_CRYPTO_EcdhePublicKey)))
757   {
758     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in metadata\n", ecdh_enc_str);
759     json_decref (root);
760     GNUNET_free (ticket);
761     return GNUNET_SYSERR;
762   }
763   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s for metadata decryption\n", ecdh_enc_str);
764   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
765                                                   strlen (signature_enc_str),
766                                                   &ticket->signature,
767                                                   sizeof (struct GNUNET_CRYPTO_EcdsaSignature)))
768   {
769     json_decref (root);
770     GNUNET_free (ticket_decoded);
771     GNUNET_free (ticket);
772     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in metadata\n");
773     return GNUNET_SYSERR;
774   }
775
776   enc_meta_len = GNUNET_STRINGS_base64_decode (enc_meta_str,
777                                                strlen (enc_meta_str),
778                                                &enc_meta);
779
780
781   ticket_payload_parse (enc_meta,
782                                                  enc_meta_len,
783                                                  priv_key,
784                                                  (const struct GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
785                                                  &ticket_payload);
786
787   ticket->payload = ticket_payload;
788   //TODO: check signature here
789   purpose = 
790     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
791                    sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
792                    enc_meta_len); // E_K (code_str)
793   purpose->size = 
794     htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
795            sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
796            enc_meta_len);
797   purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
798   write_ptr = (char*) &purpose[1];
799   memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
800   write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
801   memcpy (write_ptr, enc_meta, enc_meta_len);
802
803   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
804                                                purpose,
805                                                &ticket->signature,
806                                                &ticket_payload->identity_key))
807   {
808     ticket_destroy (ticket);
809     GNUNET_free (ticket_decoded);
810     json_decref (root);
811     GNUNET_free (purpose);
812     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
813                 "Error verifying signature for token code\n");
814     return GNUNET_SYSERR;
815   }
816   *result = ticket;
817   GNUNET_free (purpose);
818
819   GNUNET_free (enc_meta);
820   GNUNET_free (ticket_decoded);
821   json_decref (root);
822   return GNUNET_OK;
823
824 }
825
826
827
828 /* end of identity_token.c */