From 41e1dd9738a58ffce765d5f837c32962907707df Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 29 Jan 2015 17:34:37 +0100 Subject: [PATCH] finish cleanup of /refresh/commit parsing --- src/include/taler_crypto_lib.h | 12 + src/mint/mint_db.c | 10 +- src/mint/taler-mint-httpd_refresh.c | 472 +++++++++++++++++----------- src/util/crypto.c | 26 ++ 4 files changed, 328 insertions(+), 192 deletions(-) diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 597c85cdd..3b4f0d8c5 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -204,5 +204,17 @@ TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input, const struct TALER_LinkSecret *secret); +/** + * Decode encrypted refresh link information from buffer. + * + * @param buf buffer with refresh link data + * @param buf_len number of bytes in @a buf + * @return NULL on error (@a buf_len too small) + */ +struct TALER_RefreshLinkEncrypted * +TALER_refresh_link_encrypted_decode (const char *buf, + size_t buf_len); + + #endif diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 0e448bf09..5c52948e6 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -1109,14 +1109,8 @@ TALER_MINT_DB_get_refresh_commit_coin (PGconn *db_conn, GNUNET_free (rl_buf); return GNUNET_SYSERR; } - - rl = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + - rl_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); - rl->blinding_key_enc = (const char *) &rl[1]; - rl->blinding_key_enc_size = rl_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey); - memcpy (rl->coin_priv_enc, - rl_buf, - rl_buf_size); + rl = TALER_refresh_link_encrypted_decode (rl_buf, + rl_buf_size); GNUNET_free (rl_buf); cc->refresh_link = rl; cc->coin_ev = c_buf; diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 0abc82eb7..98db2054c 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -242,14 +242,13 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection, struct RefreshMeltConfirmSignRequestBody body; struct MintKeyState *key_state; struct TALER_MINT_DenomKeyIssuePriv *dki; - struct GNUNET_MINT_ParseFieldSpec spec[] = - { - TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub), - TALER_MINT_PARSE_RSA_SIGNATURE ("denom_sig", &sig), - TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &pk), - TALER_MINT_PARSE_FIXED ("confirm_sig", &melt_sig), - TALER_MINT_PARSE_END - }; + struct GNUNET_MINT_ParseFieldSpec spec[] = { + TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub), + TALER_MINT_PARSE_RSA_SIGNATURE ("denom_sig", &sig), + TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &pk), + TALER_MINT_PARSE_FIXED ("confirm_sig", &melt_sig), + TALER_MINT_PARSE_END + }; ret = TALER_MINT_parse_json_data (connection, coin_info, @@ -463,7 +462,237 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, /** - * Handle a "/refresh/commit" request + * Release memory from the @a commit_coin array. + * + * @param commit_coin array to release + * @param kappa size of 1st dimension + * @param num_new_coins size of 2nd dimension + */ +static void +free_commit_coins (struct RefreshCommitCoin **commit_coin, + unsigned int kappa, + unsigned int num_new_coins) +{ + unsigned int i; + unsigned int j; + + for (i=0;i kappa) { GNUNET_break_op (0); - // FIXME: generate error message - return MHD_NO; + json_decref (root); + TALER_MINT_release_parsed_data (spec); + return TALER_MINT_reply_arg_invalid (connection, + "coin_evs"); } - res = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "coin_evs", - JNAV_INDEX, (int) 0, - JNAV_RET_DATA, - JSON_ARRAY, &coin_detail); - if (GNUNET_OK != res) - return res; - num_newcoins = json_array_size (coin_detail); - - res = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "transfer_pubs", - JNAV_RET_TYPED_JSON, JSON_ARRAY, &transfer_pubs); - if (GNUNET_OK != res) - return res; if (json_array_size (transfer_pubs) != kappa) { GNUNET_break_op (0); - // FIXME: generate error message - return MHD_NO; + json_decref (root); + TALER_MINT_release_parsed_data (spec); + return TALER_MINT_reply_arg_invalid (connection, + "transfer_pubs"); } + res = GNUNET_MINT_parse_navigate_json (connection, coin_evs, + JNAV_INDEX, (int) 0, + JNAV_RET_DATA, + JSON_ARRAY, &coin_detail); + if (GNUNET_OK != res) + { + json_decref (root); + TALER_MINT_release_parsed_data (spec); + return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; + } + num_newcoins = json_array_size (coin_detail); res = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, "transfer_pubs", JNAV_INDEX, (int) 0, JNAV_RET_DATA, JSON_ARRAY, &coin_detail); if (GNUNET_OK != res) - return res; - num_oldcoins = json_array_size (coin_detail); - - - - hash_context = GNUNET_CRYPTO_hash_context_start (); - commit_coin = GNUNET_malloc (kappa * - sizeof (struct RefreshCommitCoin *)); - for (i = 0; i < kappa; i++) - { - commit_coin[i] = GNUNET_malloc (num_newcoins * - sizeof (struct RefreshCommitCoin)); - for (j = 0; j < num_newcoins; j++) - { - char *link_enc; - size_t link_enc_size; - - res = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "coin_evs", - JNAV_INDEX, (int) i, - JNAV_INDEX, (int) j, - JNAV_RET_DATA_VAR, - &commit_coin[i][j].coin_ev, - &commit_coin[i][j].coin_ev_size); - - if (GNUNET_OK != res) - { - // FIXME: return 'internal error'? - GNUNET_break (0); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - - GNUNET_CRYPTO_hash_context_read (hash_context, - commit_coin[i][j].coin_ev, - commit_coin[i][j].coin_ev_size); - - res = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "link_encs", - JNAV_INDEX, (int) i, - JNAV_INDEX, (int) j, - JNAV_RET_DATA_VAR, - &link_enc, - &link_enc_size); - if (GNUNET_OK != res) - { - // FIXME: return 'internal error'? - GNUNET_break (0); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - // FIXME: convert link_enc / link_enc_size to - // commit_coin[i][j].refresh_link! - - - GNUNET_CRYPTO_hash_context_read (hash_context, - link_enc, - link_enc_size); - } - } - - commit_link = GNUNET_malloc (kappa * - sizeof (struct RefreshCommitLink *)); - for (i = 0; i < kappa; i++) - { - commit_link[i] = GNUNET_malloc (num_oldcoins * - sizeof (struct RefreshCommitLink)); - for (j = 0; j < num_oldcoins; j++) - { - res = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "transfer_pubs", - JNAV_INDEX, (int) i, - JNAV_INDEX, (int) j, - JNAV_RET_DATA, - &commit_link[i][j].transfer_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - - if (GNUNET_OK != res) - { - GNUNET_break (GNUNET_SYSERR != res); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - - GNUNET_CRYPTO_hash_context_read (hash_context, - &commit_link[i][j].transfer_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); - - res = GNUNET_MINT_parse_navigate_json (connection, root, - JNAV_FIELD, "secret_encs", - JNAV_INDEX, (int) i, - JNAV_INDEX, (int) j, - JNAV_RET_DATA, - &commit_link[i][j].shared_secret_enc, - sizeof (struct GNUNET_HashCode)); - - if (GNUNET_OK != res) - { - GNUNET_break (GNUNET_SYSERR != res); - GNUNET_CRYPTO_hash_context_abort (hash_context); - return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - } - - GNUNET_CRYPTO_hash_context_read (hash_context, - &commit_link[i][j].shared_secret_enc, - sizeof (struct GNUNET_HashCode)); - } - } - GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); - - commit_sig_json = json_object_get (root, "commit_signature"); - if (NULL == commit_sig_json) - { - return TALER_MINT_reply_json_pack (connection, - MHD_HTTP_BAD_REQUEST, - "{s:s}", - "error", - "commit_signature missing"); - } - - body.commit_hash = commit_hash; - body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_COMMIT); - body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody)); - - if (GNUNET_OK != - (res = request_json_check_signature (connection, - commit_sig_json, - &refresh_session_pub, - &body.purpose))) { + json_decref (root); + TALER_MINT_release_parsed_data (spec); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } - - res = TALER_MINT_db_execute_refresh_commit (connection, - &refresh_session_pub, - kappa, - num_oldcoins, - num_newcoins, - commit_coin, - commit_link); - // FIXME: free memory + num_oldcoins = json_array_size (coin_detail); + res = handle_refresh_commit_json (connection, + &refresh_session_pub, + commit_sig_json, + kappa, + num_oldcoins, + transfer_pubs, + secret_encs, + num_newcoins, + coin_evs, + link_encs); + TALER_MINT_release_parsed_data (spec); + json_decref (root); return res; } diff --git a/src/util/crypto.c b/src/util/crypto.c index 12f452085..25f951e86 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -268,6 +268,32 @@ TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input, } +/** + * Decode encrypted refresh link information from buffer. + * + * @param buf buffer with refresh link data + * @param buf_len number of bytes in @a buf + * @return NULL on error (@a buf_len too small) + */ +struct TALER_RefreshLinkEncrypted * +TALER_refresh_link_encrypted_decode (const char *buf, + size_t buf_len) +{ + struct TALER_RefreshLinkEncrypted *rle; + + if (buf_len < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) + return NULL; + rle = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + + buf_len - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); + rle->blinding_key_enc = (const char *) &rle[1]; + rle->blinding_key_enc_size = buf_len - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey); + memcpy (rle->coin_priv_enc, + buf, + buf_len); + return rle; +} + + /** * Check if a coin is valid; that is, whether the denomination key exists, * is not expired, and the signature is correct.