From 6ea5858d3276378dd3636ecc36ed312a0ccaee61 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 8 Aug 2015 21:32:09 +0200 Subject: implementing verify_refresh_melt_signature_forbidden --- src/mint-lib/mint_api_refresh.c | 141 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 2 deletions(-) (limited to 'src/mint-lib/mint_api_refresh.c') diff --git a/src/mint-lib/mint_api_refresh.c b/src/mint-lib/mint_api_refresh.c index dad0ec16b..ede95af5b 100644 --- a/src/mint-lib/mint_api_refresh.c +++ b/src/mint-lib/mint_api_refresh.c @@ -25,6 +25,7 @@ #include /* just for HTTP status codes */ #include #include "taler_mint_service.h" +#include "mint_api_common.h" #include "mint_api_json.h" #include "mint_api_context.h" #include "mint_api_handle.h" @@ -58,6 +59,11 @@ struct MeltedCoinP */ struct TALER_AmountNBO fee_melt; + /** + * The original value of the coin. + */ + struct TALER_AmountNBO original_value; + /** * Transfer private keys for each cut-and-choose dimension. */ @@ -169,6 +175,11 @@ struct MeltedCoin */ struct TALER_Amount fee_melt; + /** + * The original value of the coin. + */ + struct TALER_Amount original_value; + /** * Transfer private keys for each cut-and-choose dimension. */ @@ -381,9 +392,10 @@ serialize_melted_coin (const struct MeltedCoin *mc, mcp.coin_priv = mc->coin_priv; TALER_amount_hton (&mcp.melt_amount_with_fee, &mc->melt_amount_with_fee); - TALER_amount_hton (&mcp.fee_melt, &mc->fee_melt); + TALER_amount_hton (&mcp.original_value, + &mc->original_value); for (i=0;itransfer_priv[i]; mcp.deposit_valid_until = GNUNET_TIME_absolute_hton (mc->deposit_valid_until); @@ -464,6 +476,8 @@ deserialize_melted_coin (struct MeltedCoin *mc, &mcp.melt_amount_with_fee); TALER_amount_ntoh (&mc->fee_melt, &mcp.fee_melt); + TALER_amount_ntoh (&mc->original_value, + &mcp.original_value); for (i=0;itransfer_priv[i] = mcp.transfer_priv[i]; mc->deposit_valid_until = GNUNET_TIME_absolute_ntoh (mcp.deposit_valid_until); @@ -868,6 +882,7 @@ TALER_MINT_refresh_prepare (unsigned int num_melts, md.melted_coins[i].coin_priv = melt_privs[i]; md.melted_coins[i].melt_amount_with_fee = melt_amounts[i]; md.melted_coins[i].fee_melt = melt_pks[i].fee_refresh; + md.melted_coins[i].original_value = melt_pks[i].value; for (j=0;jmd->num_melted_coins;i++) + { + if (0 == TALER_amount_cmp (&melt_value_with_fee, + &rmh->md->melted_coins[i].melt_amount_with_fee)) + { + struct TALER_CoinSpendPublicKeyP mc_pub; + + GNUNET_CRYPTO_eddsa_key_get_public (&rmh->md->melted_coins[i].coin_priv.eddsa_priv, + &mc_pub.eddsa_pub); + if (0 == memcmp (&mc_pub, + &coin_pub, + sizeof (struct TALER_CoinSpendPublicKeyP))) + { + mc = &rmh->md->melted_coins[i]; + break; + } + } + } + if (NULL == mc) + { + /* coin not found in our original request */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + /* check basic coin properties */ + if (0 != TALER_amount_cmp (&original_value, + &mc->original_value)) + { + /* We disagree on the value of the coin */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (0 != TALER_amount_cmp (&melt_value_with_fee, + &mc->melt_amount_with_fee)) + { + /* We disagree on the value of the coin */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + /* verify coin history */ + history = json_object_get (json, + "history"); + if (GNUNET_OK != + TALER_MINT_verify_coin_history_ (original_value.currency, + &coin_pub, + history, + &total)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + /* check if melt operation was really too expensive given history */ + if (GNUNET_OK != + TALER_amount_add (&total, + &total, + &melt_value_with_fee)) + { + /* clearly not OK if our transaction would have caused + the overflow... */ + return GNUNET_OK; + } + + if (0 >= TALER_amount_cmp (&total, + &original_value)) + { + /* transaction should have still fit */ + GNUNET_break (0); + return GNUNET_SYSERR; + } + + /* everything OK, valid proof of double-spending was provided */ + return GNUNET_OK; +} + + /** * Function called when we're done processing the * HTTP /refresh/melt request. @@ -1138,7 +1269,13 @@ handle_refresh_melt_finished (void *cls, break; case MHD_HTTP_FORBIDDEN: /* Double spending; check signatures on transaction history */ - GNUNET_break (0); // FIXME: NOT implemented! + if (GNUNET_OK != + verify_refresh_melt_signature_forbidden (rmh, + json)) + { + GNUNET_break_op (0); + response_code = 0; + } break; case MHD_HTTP_UNAUTHORIZED: /* Nothing really to verify, mint says one of the signatures is -- cgit v1.2.3