#include "identity_token.h"
#include <jansson.h>
+#define JWT_ALG "alg"
+
+#define JWT_ALG_VALUE "ED512"
+
+#define JWT_TYP "typ"
+
+#define JWT_TYP_VALUE "jwt"
/**
* Crypto helper functions
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),
&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: %d Expected bytes: %d\n", str_size, cyphertext_len);
if (-1 == str_size)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH invalid\n");
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=%d)",
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=%d)", enc_size);
return GNUNET_OK;
}
-
-
/**
* Identity Token API
*/
audience = GNUNET_STRINGS_data_to_string_alloc (aud,
sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
-
-
token = GNUNET_malloc (sizeof (struct IdentityToken));
-
- token->header = json_object();
- token->payload = json_object();
-
- json_object_set_new (token->header, "alg", json_string ("ED512"));
- json_object_set_new (token->header, "typ", json_string ("JWT"));
-
- json_object_set_new (token->payload, "iss", json_string (issuer));
- json_object_set_new (token->payload, "aud", json_string (audience));
- json_object_set_new (token->payload, "sub", json_string (issuer));
-
+ token_add_attr (token, "iss", issuer);
+ token_add_attr (token, "aud", audience);
+ token_add_attr (token, "sub", issuer);
token->aud_key = *aud;
GNUNET_free (issuer);
GNUNET_free (audience);
void
token_destroy (struct IdentityToken *token)
{
- json_decref (token->header);
- json_decref (token->payload);
+ struct TokenAttr *attr;
+ struct TokenAttr *tmp_attr;
+ struct TokenAttrValue *val;
+ struct TokenAttrValue *tmp_val;
+
+ for (attr = token->attr_head; NULL != attr;)
+ {
+ tmp_attr = attr->next;
+ GNUNET_CONTAINER_DLL_remove (token->attr_head,
+ token->attr_tail,
+ attr);
+ for (val = attr->val_head; NULL != val;)
+ {
+ tmp_val = val->next;
+ GNUNET_CONTAINER_DLL_remove (attr->val_head,
+ attr->val_tail,
+ val);
+ if (NULL != val->value)
+ GNUNET_free (val->value);
+ GNUNET_free (val);
+ val = tmp_val;
+ }
+ GNUNET_free (attr->name);
+ GNUNET_free (attr);
+ attr = tmp_attr;
+ }
+
+
GNUNET_free (token);
}
void
-token_add_attr (const struct IdentityToken *token,
- const char* key,
- const char* value)
+token_add_attr (struct IdentityToken *token,
+ const char* key,
+ const char* value)
{
+ struct TokenAttr *attr;
+ struct TokenAttrValue *new_val;
GNUNET_assert (NULL != token);
- GNUNET_assert (NULL != token->payload);
- json_object_set_new (token->payload, key, json_string (value));
+ new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
+ new_val->value = GNUNET_strdup (value);
+ for (attr = token->attr_head; NULL != attr; attr = attr->next)
+ {
+ if (0 == strcmp (key, attr->name))
+ break;
+ }
+
+ if (NULL == attr)
+ {
+ attr = GNUNET_malloc (sizeof (struct TokenAttr));
+ attr->name = GNUNET_strdup (key);
+ GNUNET_CONTAINER_DLL_insert (token->attr_head,
+ token->attr_tail,
+ attr);
+ }
+
+ GNUNET_CONTAINER_DLL_insert (attr->val_head,
+ attr->val_tail,
+ new_val);
}
void
-token_add_json (const struct IdentityToken *token,
- const char* key,
- json_t* value)
+token_add_attr_int (struct IdentityToken *token,
+ const char* key,
+ uint64_t value)
{
+ struct TokenAttr *attr;
+ struct TokenAttrValue *new_val;
GNUNET_assert (NULL != token);
- GNUNET_assert (NULL != token->payload);
- json_object_set_new (token->payload, key, value);
+ new_val = GNUNET_malloc (sizeof (struct TokenAttrValue));
+ new_val->int_value = value;
+ for (attr = token->attr_head; NULL != attr; attr = attr->next)
+ {
+ if (0 == strcmp (key, attr->name))
+ break;
+ }
+
+ if (NULL == attr)
+ {
+ attr = GNUNET_malloc (sizeof (struct TokenAttr));
+ attr->name = GNUNET_strdup (key);
+ GNUNET_CONTAINER_DLL_insert (token->attr_head,
+ token->attr_tail,
+ attr);
+ }
+
+ GNUNET_CONTAINER_DLL_insert (attr->val_head,
+ attr->val_tail,
+ new_val);
}
+static void
+parse_json_payload(const char* payload_base64,
+ struct IdentityToken *token)
+{
+ const char *key;
+ const json_t *value;
+ const json_t *arr_value;
+ char *payload;
+ int idx;
+ json_t *payload_json;
+ json_error_t err_json;
+
+ GNUNET_STRINGS_base64_decode (payload_base64,
+ strlen (payload_base64),
+ &payload);
+ //TODO signature and aud key
+ payload_json = json_loads (payload, JSON_DECODE_ANY, &err_json);
+
+ json_object_foreach (payload_json, key, value)
+ {
+ if (json_is_array (value))
+ {
+ json_array_foreach (value, idx, arr_value)
+ {
+ if (json_is_integer (arr_value))
+ token_add_attr_int (token, key,
+ json_integer_value (arr_value));
+ else
+ token_add_attr (token,
+ key,
+ json_string_value (arr_value));
+ }
+ } else {
+ if (json_is_integer (value))
+ token_add_attr_int (token, key,
+ json_integer_value (value));
+ else
+ token_add_attr (token, key, json_string_value (value));
+ }
+ }
+
+ json_decref (payload_json);
+ GNUNET_free (payload);
+}
int
token_parse2 (const char* raw_data,
- const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
- const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
- struct IdentityToken **result)
+ const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key,
+ const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+ struct IdentityToken **result)
{
char *enc_token_str;
char *tmp_buf;
char *token_str;
char *enc_token;
- char *header;
- char *header_base64;
- char *payload;
char *payload_base64;
size_t enc_token_len;
- json_error_t err_json;
GNUNET_asprintf (&tmp_buf, "%s", raw_data);
strtok (tmp_buf, ",");
return GNUNET_SYSERR;
}
- header_base64 = strtok (token_str, ".");
+ GNUNET_assert (NULL != strtok (token_str, "."));
payload_base64 = strtok (NULL, ".");
- GNUNET_STRINGS_base64_decode (header_base64,
- strlen (header_base64),
- &header);
- GNUNET_STRINGS_base64_decode (payload_base64,
- strlen (payload_base64),
- &payload);
- //TODO signature
-
-
*result = GNUNET_malloc (sizeof (struct IdentityToken));
+ parse_json_payload (payload_base64, *result);
+
(*result)->aud_key = *aud_key;
- (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
- (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
GNUNET_free (enc_token);
GNUNET_free (token_str);
GNUNET_free (tmp_buf);
- GNUNET_free (payload);
- GNUNET_free (header);
return GNUNET_OK;
}
int
token_parse (const char* raw_data,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct IdentityToken **result)
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ struct IdentityToken **result)
{
char *ecdh_pubkey_str;
char *enc_token_str;
char *tmp_buf;
char *token_str;
char *enc_token;
- char *header;
- char *header_base64;
- char *payload;
char *payload_base64;
size_t enc_token_len;
- json_error_t err_json;
struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
GNUNET_asprintf (&tmp_buf, "%s", raw_data);
return GNUNET_SYSERR;
}
- header_base64 = strtok (token_str, ".");
+ GNUNET_assert (NULL != strtok (token_str, "."));
payload_base64 = strtok (NULL, ".");
- GNUNET_STRINGS_base64_decode (header_base64,
- strlen (header_base64),
- &header);
- GNUNET_STRINGS_base64_decode (payload_base64,
- strlen (payload_base64),
- &payload);
- //TODO signature and aud key
-
-
*result = GNUNET_malloc (sizeof (struct IdentityToken));
- (*result)->header = json_loads (header, JSON_DECODE_ANY, &err_json);
- (*result)->payload = json_loads (payload, JSON_DECODE_ANY, &err_json);
+ parse_json_payload (payload_base64, *result);
+
GNUNET_free (enc_token);
GNUNET_free (token_str);
GNUNET_free (tmp_buf);
- GNUNET_free (payload);
- GNUNET_free (header);
return GNUNET_OK;
}
+static char*
+create_json_payload (const struct IdentityToken *token)
+{
+ struct TokenAttr *attr;
+ struct TokenAttrValue *val;
+ json_t *root;
+ char *json_str;
+
+ root = json_object();
+ for (attr = token->attr_head; NULL != attr; attr = attr->next)
+ {
+ for (val = attr->val_head; NULL != val; val = val->next)
+ {
+ if (NULL != val->value)
+ {
+ json_object_set_new (root,
+ attr->name,
+ json_string (val->value));
+ } else {
+ json_object_set_new (root,
+ attr->name,
+ json_integer (val->int_value));
+ }
+ }
+ }
+ json_str = json_dumps (root, JSON_INDENT(1));
+ json_decref (root);
+ return json_str;
+}
+
+static char*
+create_json_header(void)
+{
+ json_t *root;
+ char *json_str;
+
+ root = json_object ();
+ json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE));
+ json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
+
+ json_str = json_dumps (root, JSON_INDENT(1));
+ json_decref (root);
+ return json_str;
+}
+
int
token_to_string (const struct IdentityToken *token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- char **result)
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ char **result)
{
char *payload_str;
char *header_str;
char *signature_target;
char *signature_str;
struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
- header_str = json_dumps (token->header, JSON_COMPACT);
+ header_str = create_json_header();
GNUNET_STRINGS_base64_encode (header_str,
strlen (header_str),
&header_base64);
while (NULL != padding)
padding = strtok(NULL, "=");
- payload_str = json_dumps (token->payload, JSON_COMPACT);
+ payload_str = create_json_payload (token);
GNUNET_STRINGS_base64_encode (payload_str,
strlen (payload_str),
&payload_base64);
{
GNUNET_free (signature_target);
GNUNET_free (payload_str);
- GNUNET_free (header_str);
GNUNET_free (payload_base64);
- GNUNET_free (header_base64);
GNUNET_free (purpose);
return GNUNET_SYSERR;
}
int
token_serialize (const struct IdentityToken *token,
- const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
- struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
- char **result)
+ const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key,
+ struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
+ char **result)
{
char *token_str;
char *enc_token;
struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
GNUNET_assert (GNUNET_OK == token_to_string (token,
- priv_key,
- &token_str));
+ priv_key,
+ &token_str));
GNUNET_assert (GNUNET_OK == encrypt_str_ecdhe (token_str,
&token->aud_key,
struct TokenTicketPayload*
ticket_payload_create (const char* nonce,
- const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
- const char* lbl_str)
+ const struct GNUNET_CRYPTO_EcdsaPublicKey* identity_pkey,
+ const char* lbl_str)
{
struct TokenTicketPayload* payload;
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_log (GNUNET_ERROR_TYPE_DEBUG, "Using ECDH pubkey %s to encrypt\n", dh_key_str);
GNUNET_asprintf (&ticket_str, "{\"meta\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}",
ticket_payload_str, dh_key_str, ticket_sig_str);
GNUNET_STRINGS_base64_encode (ticket_str, strlen (ticket_str), result);
return GNUNET_SYSERR;
}
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata: %s\n", meta_str);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Metadata: %s\n", meta_str);
root = json_loads (meta_str, JSON_DECODE_ANY, &err_json);
if (!root)
{
}
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))
}
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);
*result = ticket_payload_create (nonce_str,
(const struct GNUNET_CRYPTO_EcdsaPublicKey*)&id_pkey,
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)
{
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 metadata decryption\n", ecdh_enc_str);
if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str,
strlen (signature_enc_str),
&ticket->signature,
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;