diff options
-rw-r--r-- | src/exchange-lib/exchange_api_refresh.c | 4 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_db.c | 172 |
2 files changed, 154 insertions, 22 deletions
diff --git a/src/exchange-lib/exchange_api_refresh.c b/src/exchange-lib/exchange_api_refresh.c index 09e1a09bb..6d12a718c 100644 --- a/src/exchange-lib/exchange_api_refresh.c +++ b/src/exchange-lib/exchange_api_refresh.c @@ -794,8 +794,8 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr return NULL; } - - /* now compute melt session hash */ + /* next, add all of the hashes from the denomination keys to the + hash_context */ for (i=0;i<fresh_pks_len;i++) { char *buf; diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 9847a7ba3..edee7da7c 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -1166,6 +1166,8 @@ send_melt_commitment_error (struct MHD_Connection *connection, * @param melt information about the melted coin * @param num_newcoins number of newcoins being generated * @param denom_pubs array of @a num_newcoins keys for the new coins + * @param hash_context hash context to update by hashing in the data + * from this offset * @return #GNUNET_OK if the committment was honest, * #GNUNET_NO if there was a problem and we generated an error message * #GNUNET_SYSERR if we could not even generate an error message @@ -1178,7 +1180,8 @@ check_commitment (struct MHD_Connection *connection, const struct TALER_TransferPrivateKeyP *transfer_priv, const struct TALER_EXCHANGEDB_RefreshMelt *melt, unsigned int num_newcoins, - const struct TALER_DenominationPublicKey *denom_pubs) + const struct TALER_DenominationPublicKey *denom_pubs, + struct GNUNET_HashContext *hash_context) { struct TALER_TransferPublicKeyP transfer_pub; struct TALER_TransferSecretP transfer_secret; @@ -1187,6 +1190,8 @@ check_commitment (struct MHD_Connection *connection, unsigned int j; int ret; + /* FIXME: instead of consulting DB, reconstruct everything + from transfer_priv here! */ if (GNUNET_OK != TMH_plugin->get_refresh_transfer_public_key (TMH_plugin->cls, session, @@ -1206,8 +1211,7 @@ check_commitment (struct MHD_Connection *connection, &transfer_pub, sizeof (struct TALER_TransferPublicKeyP))) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "transfer keys do not match\n"); + GNUNET_break_op (0); return send_melt_commitment_error (connection, session, session_hash, @@ -1275,6 +1279,7 @@ check_commitment (struct MHD_Connection *connection, commit_coins[j].coin_ev, buf_len)) ) { + GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "blind envelope does not match for k=%u, old=%d\n", off, @@ -1289,6 +1294,9 @@ check_commitment (struct MHD_Connection *connection, "envelope"); goto cleanup; } + GNUNET_CRYPTO_hash_context_read (hash_context, + commit_coins[j].coin_ev, + commit_coins[j].coin_ev_size); GNUNET_free (buf); } ret = GNUNET_OK; @@ -1391,17 +1399,6 @@ execute_refresh_reveal_transaction (struct MHD_Connection *connection, int ret; START_TRANSACTION (session, connection); - if (GNUNET_OK != - TMH_plugin->get_refresh_commit_coins (TMH_plugin->cls, - session, - session_hash, - refresh_session->noreveal_index, - refresh_session->num_newcoins, - commit_coins)) - { - GNUNET_break (0); - return TMH_RESPONSE_reply_internal_db_error (connection); - } key_state = TMH_KS_acquire (); for (j=0;j<refresh_session->num_newcoins;j++) { @@ -1456,6 +1453,8 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, unsigned int i; unsigned int j; unsigned int off; + struct GNUNET_HashContext *hash_context; + struct GNUNET_HashCode sh_check; if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls))) { @@ -1489,34 +1488,167 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, ? GNUNET_NO : GNUNET_SYSERR; } + hash_context = GNUNET_CRYPTO_hash_context_start (); + /* first, iterate over transfer public keys for hash_context */ + off = 0; + for (i=0;i<TALER_CNC_KAPPA;i++) + { + struct TALER_TransferPublicKeyP tp; + if (i == refresh_session.noreveal_index) + { + off = 1; + /* obtain tp from db */ + if (GNUNET_OK != + TMH_plugin->get_refresh_transfer_public_key (TMH_plugin->cls, + session, + session_hash, + i, + &tp)) + { + GNUNET_break (0); + GNUNET_free (denom_pubs); + GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); + GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); + GNUNET_CRYPTO_hash_context_abort (hash_context); + return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection)) + ? GNUNET_NO : GNUNET_SYSERR; + } + } + else + { + /* compute tp from private key */ + GNUNET_CRYPTO_ecdhe_key_get_public (&transfer_privs[i - off].ecdhe_priv, + &tp.ecdhe_pub); + } + GNUNET_CRYPTO_hash_context_read (hash_context, + &tp, + sizeof (struct TALER_TransferPublicKeyP)); + } + + /* next, add all of the hashes from the denomination keys to the + hash_context */ + { + struct TALER_DenominationPublicKey denom_pubs[refresh_session.num_newcoins]; + + if (GNUNET_OK != + TMH_plugin->get_refresh_order (TMH_plugin->cls, + session, + session_hash, + refresh_session.num_newcoins, + denom_pubs)) + { + GNUNET_break (0); + GNUNET_free (denom_pubs); + GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); + GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); + GNUNET_CRYPTO_hash_context_abort (hash_context); + return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection)) + ? GNUNET_NO : GNUNET_SYSERR; + } + for (i=0;i<refresh_session.num_newcoins;i++) + { + char *buf; + size_t buf_size; + + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs[i].rsa_public_key, + &buf); + GNUNET_CRYPTO_hash_context_read (hash_context, + buf, + buf_size); + GNUNET_free (buf); + GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[i].rsa_public_key); + } + } + + /* next, add public key of coin and amount being refreshed */ + { + struct TALER_AmountNBO melt_amountn; + + GNUNET_CRYPTO_hash_context_read (hash_context, + &refresh_session.melt.coin.coin_pub, + sizeof (struct TALER_CoinSpendPublicKeyP)); + TALER_amount_hton (&melt_amountn, + &refresh_session.melt.amount_with_fee); + GNUNET_CRYPTO_hash_context_read (hash_context, + &melt_amountn, + sizeof (struct TALER_AmountNBO)); + } + + commit_coins = GNUNET_new_array (refresh_session.num_newcoins, + struct TALER_EXCHANGEDB_RefreshCommitCoin); off = 0; - for (i=0;i<TALER_CNC_KAPPA - 1;i++) + for (i=0;i<TALER_CNC_KAPPA;i++) { if (i == refresh_session.noreveal_index) + { off = 1; + /* obtain commit_coins for the selected gamma value from DB */ + if (GNUNET_OK != + TMH_plugin->get_refresh_commit_coins (TMH_plugin->cls, + session, + session_hash, + i, + refresh_session.num_newcoins, + commit_coins)) + { + GNUNET_break (0); + GNUNET_free (denom_pubs); + GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); + GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); + GNUNET_CRYPTO_hash_context_abort (hash_context); + return TMH_RESPONSE_reply_internal_db_error (connection); + } + /* add envelopes to hash_context */ + for (j=0;j<refresh_session.num_newcoins;j++) + { + GNUNET_CRYPTO_hash_context_read (hash_context, + commit_coins[j].coin_ev, + commit_coins[j].coin_ev_size); + } + continue; + } if (GNUNET_OK != (res = check_commitment (connection, session, session_hash, - i + off, - &transfer_privs[i], + i, + &transfer_privs[i - off], &refresh_session.melt, refresh_session.num_newcoins, - denom_pubs))) + denom_pubs, + hash_context))) { + GNUNET_break_op (0); for (j=0;j<refresh_session.num_newcoins;j++) GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key); GNUNET_free (denom_pubs); GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); + GNUNET_CRYPTO_hash_context_abort (hash_context); return (GNUNET_NO == res) ? MHD_YES : MHD_NO; } } + /* Check session hash matches */ + GNUNET_CRYPTO_hash_context_finish (hash_context, + &sh_check); + if (0 != memcmp (&sh_check, + session_hash, + sizeof (struct GNUNET_HashCode))) + { + GNUNET_break_op (0); + for (j=0;j<refresh_session.num_newcoins;j++) + GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key); + GNUNET_free (denom_pubs); + GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature); + GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key); + return (MHD_YES == TMH_RESPONSE_reply_external_error (connection, + "session hash does not match")) + ? GNUNET_NO : GNUNET_SYSERR; + } + /* Client request OK, start transaction */ - commit_coins = GNUNET_new_array (refresh_session.num_newcoins, - struct TALER_EXCHANGEDB_RefreshCommitCoin); ev_sigs = GNUNET_new_array (refresh_session.num_newcoins, struct TALER_DenominationSignature); res = execute_refresh_reveal_transaction (connection, |