Merge branch 'credentials' of git+ssh://gnunet.org/gnunet into credentials
[oweals/gnunet.git] / src / identity-provider / identity_token.c
index 1974df6a57f7b0c715ae2c7634f41e1013f00a8d..31249840b0ff989ac4b5375601549336adf9b4fe 100644 (file)
@@ -1,6 +1,6 @@
 /*
       This file is part of GNUnet
-      Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
+      Copyright (C) 2010-2015 GNUnet e.V.
 
       GNUnet is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
@@ -19,7 +19,7 @@
  */
 
 /**
- * @file identity-token/identity_token.c
+ * @file identity-provider/identity_token.c
  * @brief helper library to manage identity tokens
  * @author Martin Schanzenbach
  */
@@ -28,6 +28,7 @@
 #include "gnunet_signatures.h"
 #include "identity_token.h"
 #include <jansson.h>
+#include <inttypes.h>
 
 #define JWT_ALG "alg"
 
@@ -50,7 +51,7 @@ create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
 
   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
                              &new_key_hash_str);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
   static const char ctx_key[] = "gnuid-aes-ctx-key";
   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
                      new_key_hash, sizeof (struct GNUNET_HashCode),
@@ -67,7 +68,7 @@ create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
 
 
 /**
- * Decrypts metainfo part from a token code
+ * Decrypts data part from a token code
  */
 static int
 decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
@@ -97,7 +98,10 @@ decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
                                               &enc_key,
                                               &enc_iv,
                                               str_buf);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Decrypted bytes: %d Expected bytes: %d\n", str_size, cyphertext_len);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Decrypted bytes: %zd Expected bytes: %zd\n",
+              str_size,
+              cyphertext_len);
   if (-1 == str_size)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
@@ -105,7 +109,7 @@ decrypt_str_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
     return GNUNET_SYSERR;
   }
   *result_str = GNUNET_malloc (str_size+1);
-  memcpy (*result_str, str_buf, str_size);
+  GNUNET_memcpy (*result_str, str_buf, str_size);
   (*result_str)[str_size] = '\0';
   GNUNET_free (str_buf);
   return GNUNET_OK;
@@ -171,14 +175,14 @@ encrypt_str_ecdhe (const char *plaintext,
                                                         pub_key,
                                                         &new_key_hash));
   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypting string %s\n (len=%d)",
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting string %s\n (len=%zd)",
               plaintext,
               strlen (plaintext));
   enc_size = GNUNET_CRYPTO_symmetric_encrypt (plaintext,
                                               strlen (plaintext),
                                               &skey, &iv,
                                               *cyphertext);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypted (len=%d)", enc_size);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted (len=%zd)", enc_size);
   return GNUNET_OK;
 }
 
@@ -420,6 +424,9 @@ token_parse (const char* raw_data,
   GNUNET_asprintf (&tmp_buf, "%s", raw_data);
   ecdh_pubkey_str = strtok (tmp_buf, ",");
   enc_token_str = strtok (NULL, ",");
+  
+  GNUNET_assert (NULL != ecdh_pubkey_str);
+  GNUNET_assert (NULL != enc_token_str);
 
   GNUNET_STRINGS_string_to_data (ecdh_pubkey_str,
                                  strlen (ecdh_pubkey_str),
@@ -535,7 +542,7 @@ token_to_string (const struct IdentityToken *token,
   purpose->size =
     htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
   purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN);
-  memcpy (&purpose[1], signature_target, strlen (signature_target));
+  GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target));
   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key,
                                              purpose,
                                              (struct GNUNET_CRYPTO_EcdsaSignature *)&token->signature))
@@ -543,6 +550,7 @@ token_to_string (const struct IdentityToken *token,
     GNUNET_free (signature_target);
     GNUNET_free (payload_str);
     GNUNET_free (payload_base64);
+    GNUNET_free (header_base64);
     GNUNET_free (purpose);
     return GNUNET_SYSERR;
   }
@@ -597,14 +605,14 @@ token_serialize (const struct IdentityToken *token,
 }
 
 struct TokenTicketPayload*
-ticket_payload_create (const char* nonce,
+ticket_payload_create (uint64_t nonce,
                        const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
                        const char* lbl_str)
 {
   struct TokenTicketPayload* payload;
 
   payload = GNUNET_malloc (sizeof (struct TokenTicketPayload));
-  GNUNET_asprintf (&payload->nonce, nonce, strlen (nonce));
+  payload->nonce = nonce;
   payload->identity_key = *identity_pkey;
   GNUNET_asprintf (&payload->label, lbl_str, strlen (lbl_str));
   return payload;
@@ -613,8 +621,6 @@ ticket_payload_create (const char* nonce,
 void
 ticket_payload_destroy (struct TokenTicketPayload* payload)
 {
-  if (NULL != payload->nonce)
-    GNUNET_free (payload->nonce);
   if (NULL != payload->label)
     GNUNET_free (payload->label);
   GNUNET_free (payload);
@@ -630,7 +636,7 @@ ticket_payload_serialize (struct TokenTicketPayload *payload,
                                                           sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
 
   GNUNET_asprintf (result, 
-                   "{\"nonce\": \"%u\",\"identity\": \"%s\",\"label\": \"%s\"}",
+                   "{\"nonce\": \"%"SCNu64"\",\"identity\": \"%s\",\"label\": \"%s\"}",
                    payload->nonce, identity_key_str, payload->label);
   GNUNET_free (identity_key_str);
 
@@ -639,13 +645,13 @@ ticket_payload_serialize (struct TokenTicketPayload *payload,
 
 /**
  * Create the token code
- * The metadata is encrypted with a share ECDH derived secret using B (aud_key)
+ * The data is encrypted with a share ECDH derived secret using B (aud_key)
  * and e (ecdh_privkey)
  * The ticket also contains E (ecdh_pubkey) and a signature over the
- * metadata and E
+ * data and E
  */
 struct TokenTicket*
-ticket_create (const char* nonce_str,
+ticket_create (uint64_t nonce,
                const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
                const char* lbl_str,
                const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key)
@@ -654,7 +660,7 @@ ticket_create (const char* nonce_str,
   struct TokenTicketPayload *code_payload;
 
   ticket = GNUNET_malloc (sizeof (struct TokenTicket));
-  code_payload = ticket_payload_create (nonce_str,
+  code_payload = ticket_payload_create (nonce,
                                         identity_pkey,
                                         lbl_str);
   ticket->aud_key = *aud_key;
@@ -708,11 +714,11 @@ ticket_serialize (struct TokenTicket *ticket,
            strlen (code_payload_str));
   purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
   write_ptr = (char*) &purpose[1];
-  memcpy (write_ptr,
+  GNUNET_memcpy (write_ptr,
           &ticket->ecdh_pubkey,
           sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
   write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
-  memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
+  GNUNET_memcpy (write_ptr, enc_ticket_payload, strlen (code_payload_str));
   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (priv_key,
                                                         purpose,
                                                         &ticket->signature));
@@ -724,8 +730,8 @@ ticket_serialize (struct TokenTicket *ticket,
 
   dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->ecdh_pubkey,
                                                     sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
-  GNUNET_asprintf (&ticket_str, "{\"meta\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
+  GNUNET_asprintf (&ticket_str, "{\"data\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
                    ticket_payload_str, dh_key_str, ticket_sig_str);
   GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
   GNUNET_free (dh_key_str);
@@ -754,26 +760,27 @@ ticket_payload_parse(const char *raw_data,
   json_t *identity_json;
   json_t *nonce_json;
   json_error_t err_json;
-  char* meta_str;
+  char* data_str;
+  uint64_t nonce;
   struct GNUNET_CRYPTO_EcdsaPublicKey id_pkey;
 
   if (GNUNET_OK != decrypt_str_ecdhe (priv_key,
                                       ecdhe_pkey,
                                       raw_data,
                                       data_len,
-                                      &meta_str))
+                                      &data_str))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata decryption failed\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Data decryption failed\n");
     return GNUNET_SYSERR;
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata: %s\n", meta_str);
-  root = json_loads (meta_str, JSON_DECODE_ANY, &err_json);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data: %s\n", data_str);
+  root = json_loads (data_str, JSON_DECODE_ANY, &err_json);
   if (!root)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
-    GNUNET_free (meta_str);
+                "Error parsing data: %s\n", err_json.text);
+    GNUNET_free (data_str);
     return GNUNET_SYSERR;
   }
 
@@ -781,9 +788,9 @@ ticket_payload_parse(const char *raw_data,
   if (!json_is_string (identity_json))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
+                "Error parsing data: %s\n", err_json.text);
     json_decref (root);
-    GNUNET_free (meta_str);
+    GNUNET_free (data_str);
     return GNUNET_SYSERR;
   }
   identity_key_str = json_string_value (identity_json);
@@ -797,32 +804,34 @@ ticket_payload_parse(const char *raw_data,
   if (!json_is_string (label_json))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
+                "Error parsing data: %s\n", err_json.text);
     json_decref (root);
-    GNUNET_free (meta_str);
+    GNUNET_free (data_str);
     return GNUNET_SYSERR;
   }
 
   label_str = json_string_value (label_json);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found label: %s\n", label_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found label: %s\n", label_str);
 
   nonce_json = json_object_get (root, "nonce");
   if (!json_is_string (label_json))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error parsing metadata: %s\n", err_json.text);
+                "Error parsing data: %s\n", err_json.text);
     json_decref (root);
-    GNUNET_free (meta_str);
+    GNUNET_free (data_str);
     return GNUNET_SYSERR;
   }
 
   nonce_str = json_string_value (nonce_json);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found nonce: %s\n", nonce_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found nonce: %s\n", nonce_str);
+  
+  GNUNET_assert (0 != sscanf (nonce_str, "%"SCNu64, &nonce));
 
-  *result = ticket_payload_create (nonce_str,
+  *result = ticket_payload_create (nonce,
                                    (const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
                                    label_str);
-  GNUNET_free (meta_str);
+  GNUNET_free (data_str);
   json_decref (root);
   return GNUNET_OK;
 
@@ -833,26 +842,26 @@ ticket_parse (const char *raw_data,
               const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
               struct TokenTicket **result)
 {
-  const char* enc_meta_str;
+  const char* enc_data_str;
   const char* ecdh_enc_str;
   const char* signature_enc_str;
 
   json_t *root;
   json_t *signature_json;
   json_t *ecdh_json;
-  json_t *enc_meta_json;
+  json_t *enc_data_json;
   json_error_t err_json;
-  char* enc_meta;
+  char* enc_data;
   char* ticket_decoded;
   char* write_ptr;
-  size_t enc_meta_len;
+  size_t enc_data_len;
   struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
   struct TokenTicket *ticket;
   struct TokenTicketPayload *ticket_payload;
 
   ticket_decoded = NULL;
   GNUNET_STRINGS_base64_decode (raw_data, strlen (raw_data), &ticket_decoded);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Token Code: %s\n", ticket_decoded);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket: %s\n", ticket_decoded);
   root = json_loads (ticket_decoded, JSON_DECODE_ANY, &err_json);
   if (!root)
   {
@@ -863,11 +872,11 @@ ticket_parse (const char *raw_data,
 
   signature_json = json_object_get (root, "signature");
   ecdh_json = json_object_get (root, "ecdh");
-  enc_meta_json = json_object_get (root, "meta");
+  enc_data_json = json_object_get (root, "data");
 
   signature_enc_str = json_string_value (signature_json);
   ecdh_enc_str = json_string_value (ecdh_json);
-  enc_meta_str = json_string_value (enc_meta_json);
+  enc_data_str = json_string_value (enc_data_json);
 
   ticket = GNUNET_malloc (sizeof (struct TokenTicket));
 
@@ -876,12 +885,12 @@ ticket_parse (const char *raw_data,
                                                   &ticket->ecdh_pubkey,
                                                   sizeof  (struct GNUNET_CRYPTO_EcdhePublicKey)))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in metadata\n", ecdh_enc_str);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in data\n", ecdh_enc_str);
     json_decref (root);
     GNUNET_free (ticket);
     return GNUNET_SYSERR;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s for metadata decryption\n", ecdh_enc_str);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s for data decryption\n", ecdh_enc_str);
   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
                                                   strlen (signature_enc_str),
                                                   &ticket->signature,
@@ -890,43 +899,42 @@ ticket_parse (const char *raw_data,
     json_decref (root);
     GNUNET_free (ticket_decoded);
     GNUNET_free (ticket);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in metadata\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in data\n");
     return GNUNET_SYSERR;
   }
 
-  enc_meta_len = GNUNET_STRINGS_base64_decode (enc_meta_str,
-                                               strlen (enc_meta_str),
-                                               &enc_meta);
+  enc_data_len = GNUNET_STRINGS_base64_decode (enc_data_str,
+                                               strlen (enc_data_str),
+                                               &enc_data);
 
 
-  if (GNUNET_OK != ticket_payload_parse (enc_meta,
-                                         enc_meta_len,
+  if (GNUNET_OK != ticket_payload_parse (enc_data,
+                                         enc_data_len,
                                          priv_key,
                                          (const struct GNUNET_CRYPTO_EcdhePublicKey*)&ticket->ecdh_pubkey,
                                          &ticket_payload))
   {
     json_decref (root);
-    GNUNET_free (enc_meta);
+    GNUNET_free (enc_data);
     GNUNET_free (ticket_decoded);
     GNUNET_free (ticket);
     return GNUNET_SYSERR;
   }
 
   ticket->payload = ticket_payload;
-  //TODO: check signature here
   purpose = 
     GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + 
                    sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E
-                   enc_meta_len); // E_K (code_str)
+                   enc_data_len); // E_K (code_str)
   purpose->size = 
     htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
            sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
-           enc_meta_len);
+           enc_data_len);
   purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET);
   write_ptr = (char*) &purpose[1];
-  memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_memcpy (write_ptr, &ticket->ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
   write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
-  memcpy (write_ptr, enc_meta, enc_meta_len);
+  GNUNET_memcpy (write_ptr, enc_data, enc_data_len);
 
   if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNUID_TICKET,
                                                purpose,
@@ -938,13 +946,13 @@ ticket_parse (const char *raw_data,
     json_decref (root);
     GNUNET_free (purpose);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error verifying signature for token code\n");
+                "Error verifying signature for ticket\n");
     return GNUNET_SYSERR;
   }
   *result = ticket;
   GNUNET_free (purpose);
 
-  GNUNET_free (enc_meta);
+  GNUNET_free (enc_data);
   GNUNET_free (ticket_decoded);
   json_decref (root);
   return GNUNET_OK;