summaryrefslogtreecommitdiff
path: root/src/exchange
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange')
-rw-r--r--src/exchange/taler-exchange-httpd_keystate.c2
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_link.c9
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_reveal.c109
3 files changed, 110 insertions, 10 deletions
diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c
index 6134faf3..c4e55021 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -39,7 +39,7 @@
* release version, and the format is NOT the same that semantic
* versioning uses either.
*/
-#define TALER_PROTOCOL_VERSION "3:0:0"
+#define TALER_PROTOCOL_VERSION "4:0:0"
/**
diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c b/src/exchange/taler-exchange-httpd_refresh_link.c
index 0ec505a8..04145f48 100644
--- a/src/exchange/taler-exchange-httpd_refresh_link.c
+++ b/src/exchange/taler-exchange-httpd_refresh_link.c
@@ -92,6 +92,9 @@ handle_link_data (void *cls,
json_object_set_new (obj,
"ev_sig",
GNUNET_JSON_from_rsa_signature (pos->ev_sig.rsa_signature));
+ json_object_set_new (obj,
+ "link_sig",
+ GNUNET_JSON_from_data_auto (&pos->orig_coin_link_sig));
if (0 !=
json_array_append_new (list,
obj))
@@ -204,9 +207,9 @@ TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh,
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
"run link",
- &mhd_ret,
- &refresh_link_transaction,
- &ctx))
+ &mhd_ret,
+ &refresh_link_transaction,
+ &ctx))
{
if (NULL != ctx.mlist)
json_decref (ctx.mlist);
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index 6fc8d1c5..2f6d0b14 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -145,6 +145,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.
*/
struct TALER_DenominationSignature *ev_sigs;
@@ -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;i<num_tprivs;i++)
@@ -579,7 +597,9 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
/* Resolve denomination hashes */
{
const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dkis[num_fresh_coins];
+ struct GNUNET_HashCode dki_h[num_fresh_coins];
struct TALER_RefreshCoinData rcds[num_fresh_coins];
+ struct TALER_CoinSpendSignatureP link_sigs[num_fresh_coins];
int res;
/* Resolve denomination hashes */
@@ -596,10 +616,9 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
/* Parse denomination key hashes */
for (unsigned int i=0;i<num_fresh_coins;i++)
{
- struct GNUNET_HashCode dpk_h;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL,
- &dpk_h),
+ &dki_h[i]),
GNUNET_JSON_spec_end ()
};
@@ -614,7 +633,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
}
dkis[i] = TEH_KS_denomination_key_lookup_by_hash (key_state,
- &dpk_h,
+ &dki_h[i],
TEH_KS_DKU_WITHDRAW);
if (NULL == dkis[i])
{
@@ -652,9 +671,85 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
rcd->dk = &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;i<num_fresh_coins;i++)
+ {
+ struct GNUNET_JSON_Specification link_spec[] = {
+ GNUNET_JSON_spec_fixed_auto (NULL, &link_sigs[i]),
+ GNUNET_JSON_spec_end ()
+ };
+ int res;
+
+ res = TEH_PARSE_json_array (connection,
+ link_sigs_json,
+ link_spec,
+ i,
+ -1);
+ if (GNUNET_OK != res)
+ return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+ /* Check link_sigs[i] signature */
+ {
+ struct TALER_LinkDataPS ldp;
+
+ ldp.purpose.size = htonl (sizeof (ldp));
+ ldp.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK);
+ ldp.h_denom_pub = dki_h[i];
+ ldp.old_coin_pub = refresh_melt.session.coin.coin_pub;
+ ldp.transfer_pub = rctx->gamma_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);