From 3a2f72b4aad3c2719e4326d30a97e49e26b5d797 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 26 Jun 2019 15:34:14 +0200 Subject: implement /link signatures --- src/exchange/taler-exchange-httpd_refresh_reveal.c | 109 +++++++++++++++++++-- 1 file changed, 103 insertions(+), 6 deletions(-) (limited to 'src/exchange/taler-exchange-httpd_refresh_reveal.c') diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index 6fc8d1c5e..2f6d0b14e 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -144,6 +144,12 @@ struct RevealContext */ const struct TALER_RefreshCoinData *rcds; + /** + * Signatures over the link data (of type + * #TALER_SIGNATURE_WALLET_COIN_LINK) + */ + const struct TALER_CoinSpendSignatureP *link_sigs; + /** * Envelopes with the signatures to be returned. Initially NULL. */ @@ -491,6 +497,7 @@ refresh_reveal_persist (void *cls, struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i]; rrc->denom_pub = rctx->dkis[i]->denom_pub; + rrc->orig_coin_link_sig = rctx->link_sigs[i]; rrc->coin_ev = rctx->rcds[i].coin_ev; rrc->coin_ev_size = rctx->rcds[i].coin_ev_size; rrc->coin_sig = rctx->ev_sigs[i]; @@ -524,6 +531,7 @@ refresh_reveal_persist (void *cls, * @param rctx context for the operation, partially built at this time * @param transfer_pub transfer public key * @param tp_json private transfer keys in JSON format + * @param link_sigs_json link signatures in JSON format * @param new_denoms_h_json requests for fresh coins to be created * @param coin_evs envelopes of gamma-selected coins to be signed * @return MHD result code @@ -532,12 +540,14 @@ static int handle_refresh_reveal_json (struct MHD_Connection *connection, struct RevealContext *rctx, const json_t *tp_json, + const json_t *link_sigs_json, const json_t *new_denoms_h_json, const json_t *coin_evs) { unsigned int num_fresh_coins = json_array_size (new_denoms_h_json); unsigned int num_tprivs = json_array_size (tp_json); struct TEH_KS_StateHandle *key_state; + struct TALER_EXCHANGEDB_RefreshMelt refresh_melt; GNUNET_assert (num_tprivs == TALER_CNC_KAPPA - 1); if ( (num_fresh_coins >= MAX_FRESH_COINS) || @@ -545,7 +555,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, { GNUNET_break_op (0); return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE, + TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE, "new_denoms"); } @@ -557,6 +567,14 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH, "new_denoms/coin_evs"); } + if (json_array_size (new_denoms_h_json) != + json_array_size (link_sigs_json)) + { + GNUNET_break_op (0); + return TEH_RESPONSE_reply_arg_invalid (connection, + TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH, + "new_denoms/link_sigs"); + } /* Parse transfer private keys array */ for (unsigned int i=0;idk = &dkis[i]->denom_pub; } + /* lookup old_coin_pub in database */ + { + enum GNUNET_DB_QueryStatus qs; + + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + (qs = TEH_plugin->get_melt (TEH_plugin->cls, + NULL, + &rctx->rc, + &refresh_melt))) + { + switch (qs) + { + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + res = TEH_RESPONSE_reply_arg_invalid (connection, + TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN, + "rc"); + break; + case GNUNET_DB_STATUS_HARD_ERROR: + res = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR); + break; + case GNUNET_DB_STATUS_SOFT_ERROR: + default: + GNUNET_break (0); /* should be impossible */ + res = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_INTERNAL_INVARIANT_FAILURE); + break; + } + goto cleanup; + } + } + /* Parse link signatures array */ + for (unsigned int i=0;igamma_tp; + GNUNET_CRYPTO_hash (rcds[i].coin_ev, + rcds[i].coin_ev_size, + &ldp.coin_envelope_hash); + + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK, + &ldp.purpose, + &link_sigs[i].eddsa_signature, + &refresh_melt.session.coin.coin_pub.eddsa_pub)) + { + GNUNET_break_op (0); + res = TEH_RESPONSE_reply_signature_invalid (connection, + TALER_EC_REFRESH_REVEAL_LINK_SIGNATURE_INVALID, + "link_sig"); + goto cleanup; + } + } + } + rctx->num_fresh_coins = num_fresh_coins; rctx->rcds = rcds; rctx->dkis = dkis; + rctx->link_sigs = link_sigs; /* sign _early_ (optimistic!) to keep out of transaction scope! */ rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins, @@ -749,7 +844,6 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, } - /** * Handle a "/refresh/reveal" request. This time, the client reveals * the private transfer keys except for the cut-and-choose value @@ -777,12 +871,14 @@ TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, json_t *root; json_t *coin_evs; json_t *transfer_privs; + json_t *link_sigs; json_t *new_denoms_h; struct RevealContext rctx; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("rc", &rctx.rc), GNUNET_JSON_spec_fixed_auto ("transfer_pub", &rctx.gamma_tp), GNUNET_JSON_spec_json ("transfer_privs", &transfer_privs), + GNUNET_JSON_spec_json ("link_sigs", &link_sigs), GNUNET_JSON_spec_json ("coin_evs", &coin_evs), GNUNET_JSON_spec_json ("new_denoms_h", &new_denoms_h), GNUNET_JSON_spec_end () @@ -819,12 +915,13 @@ TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, GNUNET_JSON_parse_free (spec); GNUNET_break_op (0); return TEH_RESPONSE_reply_arg_invalid (connection, - TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID, + TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID, "transfer_privs"); } res = handle_refresh_reveal_json (connection, &rctx, transfer_privs, + link_sigs, new_denoms_h, coin_evs); GNUNET_JSON_parse_free (spec); -- cgit v1.2.3