summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/taler_crypto_lib.h4
-rw-r--r--src/include/taler_exchange_service.h8
-rw-r--r--src/lib/exchange_api_melt.c51
-rw-r--r--src/lib/exchange_api_withdraw.c5
-rw-r--r--src/lib/exchange_api_withdraw2.c11
-rw-r--r--src/testing/testing_api_cmd_refresh.c103
6 files changed, 123 insertions, 59 deletions
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index 8be76aef8..e74d49f6d 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1479,10 +1479,10 @@ TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
/**
- * Setup information for a fresh coin.
+ * Setup information for fresh coins to be withdrawn
+ * or refreshed.
*
* @param[out] ps value to initialize
- * @oaram alg_values WitdrawValues containing cipher
*/
void
TALER_planchet_setup_random (
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 328c074a0..a6b847bbe 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -1412,6 +1412,12 @@ struct TALER_EXCHANGE_WithdrawResponse
struct TALER_CoinSpendPrivateKeyP coin_priv;
/**
+ * Value used to blind the key for the signature.
+ * Needed for recoup operations.
+ */
+ union TALER_DenominationBlindingKeyP bks;
+
+ /**
* Signature over the coin.
*/
struct TALER_DenominationSignature sig;
@@ -1634,6 +1640,7 @@ struct TALER_EXCHANGE_MeltHandle;
* @param hr HTTP response data
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, 0 if the operation failed
* @param alg_values array @a num_coins of exchange values contributed to the refresh operation
+ * @param bks array of @a num_coins blinding keys used to blind the fresh coins
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
* UINT32_MAX on error
* @param sign_key exchange key used to sign @a full_response, or NULL
@@ -1644,6 +1651,7 @@ typedef void
const struct TALER_EXCHANGE_HttpResponse *hr,
unsigned int num_coins,
const struct TALER_ExchangeWithdrawValues *alg_values,
+ const union TALER_DenominationBlindingKeyP *bks,
uint32_t noreveal_index,
const struct TALER_ExchangePublicKeyP *sign_key);
diff --git a/src/lib/exchange_api_melt.c b/src/lib/exchange_api_melt.c
index da0c904ba..10086ed5c 100644
--- a/src/lib/exchange_api_melt.c
+++ b/src/lib/exchange_api_melt.c
@@ -92,6 +92,12 @@ struct TALER_EXCHANGE_MeltHandle
struct TALER_ExchangeWithdrawValues *alg_values;
/**
+ * Array of `num_fresh_coins` blinding secrets
+ * used for blinding the coins.
+ */
+ union TALER_DenominationBlindingKeyP *bks;
+
+ /**
* Handle for the preflight request, or NULL.
*/
struct TALER_EXCHANGE_CsRHandle *csr;
@@ -135,7 +141,6 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
noreveal_index),
GNUNET_JSON_spec_end ()
};
- struct TALER_RefreshMeltConfirmationPS confirm;
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@@ -145,7 +150,6 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
-
/* check that exchange signing key is permitted */
key_state = TALER_EXCHANGE_get_keys (mh->exchange);
if (GNUNET_OK !=
@@ -163,20 +167,24 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
return GNUNET_SYSERR;
}
- /* verify signature by exchange */
- confirm.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT);
- confirm.purpose.size
- = htonl (sizeof (struct TALER_RefreshMeltConfirmationPS));
- confirm.rc = mh->md.rc;
- confirm.noreveal_index = htonl (*noreveal_index);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
- &confirm,
- &exchange_sig.eddsa_signature,
- &exchange_pub->eddsa_pub))
+ /* verify signature by exchange -- FIXME: move to util! */
{
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
+ struct TALER_RefreshMeltConfirmationPS confirm = {
+ .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
+ .purpose.size = htonl (sizeof (confirm)),
+ .rc = mh->md.rc,
+ .noreveal_index = htonl (*noreveal_index)
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
+ &confirm,
+ &exchange_sig.eddsa_signature,
+ &exchange_pub->eddsa_pub))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
}
return GNUNET_OK;
}
@@ -368,6 +376,9 @@ handle_melt_finished (void *cls,
(0 == hr.http_status)
? NULL
: mh->alg_values,
+ (0 == hr.http_status)
+ ? NULL
+ : mh->bks,
noreveal_index,
(0 == hr.http_status)
? NULL
@@ -451,6 +462,7 @@ handle_melt_finished (void *cls,
&hr,
0,
NULL,
+ NULL,
UINT32_MAX,
NULL);
TALER_EXCHANGE_melt_cancel (mh);
@@ -561,6 +573,7 @@ fail_mh (struct TALER_EXCHANGE_MeltHandle *mh)
NULL,
0,
NULL,
+ NULL,
UINT32_MAX,
NULL);
TALER_EXCHANGE_melt_cancel (mh);
@@ -591,8 +604,7 @@ csr_cb (void *cls,
{
case TALER_DENOMINATION_INVALID:
GNUNET_break (0);
- // FIXME:
- // fail_mh (mh).
+ fail_mh (mh);
return;
case TALER_DENOMINATION_RSA:
GNUNET_assert (TALER_DENOMINATION_RSA == wv->cipher);
@@ -640,6 +652,8 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
mh->melt_cb_cls = melt_cb_cls;
mh->alg_values = GNUNET_new_array (rd->fresh_pks_len,
struct TALER_ExchangeWithdrawValues);
+ mh->bks = GNUNET_new_array (rd->fresh_pks_len,
+ union TALER_DenominationBlindingKeyP);
for (unsigned int i = 0; i<rd->fresh_pks_len; i++)
{
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_pks[i];
@@ -650,6 +664,7 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
case TALER_DENOMINATION_INVALID:
GNUNET_break (0);
GNUNET_free (mh->alg_values);
+ GNUNET_free (mh->bks);
GNUNET_free (mh);
return NULL;
case TALER_DENOMINATION_RSA:
@@ -705,6 +720,8 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh)
mh->csr = NULL;
}
TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */
+ GNUNET_free (mh->alg_values);
+ GNUNET_free (mh->bks);
GNUNET_free (mh->url);
TALER_curl_easy_post_finished (&mh->ctx);
GNUNET_free (mh);
diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c
index 94c6007d7..774f8c1ad 100644
--- a/src/lib/exchange_api_withdraw.c
+++ b/src/lib/exchange_api_withdraw.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2021 Taler Systems SA
+ Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -145,7 +145,10 @@ handle_reserve_withdraw_finished (
wr.hr.ec = TALER_EC_EXCHANGE_WITHDRAW_UNBLIND_FAILURE;
break;
}
+ wr.details.success.coin_priv = wh->priv;
+ wr.details.success.bks = wh->bks;
wr.details.success.sig = fc.sig;
+ wr.details.success.exchange_vals = wh->alg_values;
break;
}
case MHD_HTTP_ACCEPTED:
diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c
index c5a3a66ac..1b3985552 100644
--- a/src/lib/exchange_api_withdraw2.c
+++ b/src/lib/exchange_api_withdraw2.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2021 Taler Systems SA
+ Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -152,7 +152,8 @@ reserve_withdraw_payment_required (
json_t *history;
size_t len;
struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount_any ("balance", &balance),
+ TALER_JSON_spec_amount_any ("balance",
+ &balance),
GNUNET_JSON_spec_end ()
};
@@ -182,9 +183,9 @@ reserve_withdraw_payment_required (
not fit on the stack. Use "GNUNET_malloc_large" as a malicious
exchange may theoretically try to crash us by giving a history
that does not fit into our memory. */
- rhistory = GNUNET_malloc_large (sizeof (struct
- TALER_EXCHANGE_ReserveHistory)
- * len);
+ rhistory = GNUNET_malloc_large (
+ sizeof (struct TALER_EXCHANGE_ReserveHistory)
+ * len);
if (NULL == rhistory)
{
GNUNET_break (0);
diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c
index 9f49b354a..7593a5a7a 100644
--- a/src/testing/testing_api_cmd_refresh.c
+++ b/src/testing/testing_api_cmd_refresh.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2018-2020 Taler Systems SA
+ Copyright (C) 2018-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
@@ -91,9 +91,9 @@ struct RefreshMeltState
const char *coin_reference;
/**
- * "Crypto data" used in the refresh operation.
+ * Data used in the refresh operation.
*/
- json_t *refresh_data;
+ struct TALER_EXCHANGE_RefreshData refresh_data;
/**
* Reference to a previous melt command.
@@ -117,6 +117,16 @@ struct RefreshMeltState
struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
/**
+ * Array of @a num_fresh_coins of exchange values contributed to the refresh operation
+ */
+ struct TALER_ExchangeWithdrawValues *alg_values;
+
+ /**
+ * Entropy seed for the refresh-melt operation.
+ */
+ struct TALER_PlanchetSecretsP ps;
+
+ /**
* Private key of the dirty coin being melted.
*/
const struct TALER_CoinSpendPrivateKeyP *melt_priv;
@@ -337,7 +347,7 @@ static void
reveal_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
unsigned int num_coins,
- const struct TALER_PlanchetSecretsP *coin_privs,
+ const struct TALER_CoinSpendPrivateKeyP *coin_privs,
const struct TALER_DenominationSignature *sigs)
{
struct RefreshRevealState *rrs = cls;
@@ -402,6 +412,7 @@ reveal_cb (void *cls,
for (unsigned int i = 0; i<num_coins; i++)
{
struct TALER_TESTING_FreshCoinData *fc = &rrs->fresh_coins[i];
+ const union TALER_DenominationBlindingKeyP *bks;
if (GNUNET_OK !=
TALER_TESTING_get_trait_denom_pub (melt_cmd,
@@ -412,8 +423,17 @@ reveal_cb (void *cls,
TALER_TESTING_interpreter_fail (rrs->is);
return;
}
- fc->coin_priv = coin_privs[i].coin_priv;
- fc->blinding_key = coin_privs[i].blinding_key;
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_blinding_key (melt_cmd,
+ i,
+ &bks))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (rrs->is);
+ return;
+ }
+ fc->coin_priv = coin_privs[i];
+ fc->blinding_key = *bks;
TALER_denom_sig_deep_copy (&fc->sig,
&sigs[i]);
}
@@ -461,9 +481,13 @@ refresh_reveal_run (void *cls,
TALER_TESTING_interpreter_fail (rrs->is);
return;
}
+ // FIXME: use trait for 'rms'!
rms = melt_cmd->cls;
rrs->rrh = TALER_EXCHANGE_refreshes_reveal (is->exchange,
- rms->refresh_data,
+ &rms->ps,
+ &rms->refresh_data,
+ rms->num_fresh_coins,
+ rms->alg_values,
rms->noreveal_index,
&reveal_cb,
rrs);
@@ -763,6 +787,7 @@ refresh_link_run (void *cls,
/* find reserve_withdraw command */
{
+ // FIXME: use trait!
rms = melt_cmd->cls;
coin_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
rms->coin_reference);
@@ -856,11 +881,6 @@ do_melt_retry (void *cls)
rms->retry_task = NULL;
rms->is->commands[rms->is->ip].last_req_time
= GNUNET_TIME_absolute_get ();
- if (NULL != rms->refresh_data)
- {
- json_decref (rms->refresh_data);
- rms->refresh_data = NULL;
- }
melt_run (rms,
NULL,
rms->is);
@@ -874,6 +894,9 @@ do_melt_retry (void *cls)
*
* @param cls closure.
* @param hr HTTP response details
+ * @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, 0 if the operation failed
+ * @param alg_values array @a num_coins of exchange values contributed to the refresh operation
+ * @param bks array of @a num_coins blinding keys used to blind the fresh coins
* @param noreveal_index choice by the exchange in the
* cut-and-choose protocol, UINT16_MAX on error.
* @param exchange_pub public key the exchange used for signing.
@@ -881,6 +904,9 @@ do_melt_retry (void *cls)
static void
melt_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
+ unsigned int num_coins,
+ const struct TALER_ExchangeWithdrawValues *alg_values,
+ const union TALER_DenominationBlindingKeyP *bks,
uint32_t noreveal_index,
const struct TALER_ExchangePublicKeyP *exchange_pub)
{
@@ -929,7 +955,22 @@ melt_cb (void *cls,
TALER_TESTING_interpreter_fail (rms->is);
return;
}
- rms->noreveal_index = noreveal_index;
+ if (MHD_HTTP_OK == hr->http_status)
+ {
+ rms->noreveal_index = noreveal_index;
+ if (num_coins != rms->num_fresh_coins)
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (rms->is);
+ return;
+ }
+ GNUNET_free (rms->alg_values);
+ rms->alg_values = GNUNET_new_array (num_coins,
+ struct TALER_ExchangeWithdrawValues);
+ memcpy (rms->alg_values,
+ alg_values,
+ num_coins * sizeof (struct TALER_ExchangeWithdrawValues));
+ }
if (0 != rms->total_backoff.rel_value_us)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -943,7 +984,8 @@ melt_cb (void *cls,
TALER_LOG_DEBUG ("Doubling the melt (%s)\n",
rms->is->commands[rms->is->ip].label);
rms->rmh = TALER_EXCHANGE_melt (rms->is->exchange,
- rms->refresh_data,
+ &rms->ps,
+ &rms->refresh_data,
&melt_cb,
rms);
rms->double_melt = GNUNET_NO;
@@ -978,6 +1020,7 @@ melt_run (void *cls,
melt_fresh_amounts = default_melt_fresh_amounts;
rms->is = is;
rms->noreveal_index = UINT16_MAX;
+ TALER_planchet_setup_random (&rms->ps);
for (num_fresh_coins = 0;
NULL != melt_fresh_amounts[num_fresh_coins];
num_fresh_coins++)
@@ -994,8 +1037,9 @@ melt_run (void *cls,
const struct TALER_TESTING_Command *coin_command;
if (NULL == (coin_command
- = TALER_TESTING_interpreter_lookup_command
- (is, rms->coin_reference)))
+ = TALER_TESTING_interpreter_lookup_command (
+ is,
+ rms->coin_reference)))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (rms->is);
@@ -1070,22 +1114,15 @@ melt_run (void *cls,
TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key,
&fresh_pk->key);
} /* end for */
- GNUNET_assert (NULL == rms->refresh_data);
- rms->refresh_data
- = TALER_EXCHANGE_refresh_prepare (rms->melt_priv,
- &melt_amount,
- melt_sig,
- melt_denom_pub,
- num_fresh_coins,
- rms->fresh_pks);
- if (NULL == rms->refresh_data)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
+ rms->refresh_data.melt_priv = *rms->melt_priv;
+ rms->refresh_data.melt_amount = melt_amount;
+ rms->refresh_data.melt_sig = *melt_sig;
+ rms->refresh_data.melt_pk = *melt_denom_pub;
+ rms->refresh_data.fresh_pks = rms->fresh_pks;
+ rms->refresh_data.fresh_pks_len = num_fresh_coins;
rms->rmh = TALER_EXCHANGE_melt (is->exchange,
- rms->refresh_data,
+ &rms->ps,
+ &rms->refresh_data,
&melt_cb,
rms);
@@ -1132,9 +1169,7 @@ melt_cleanup (void *cls,
TALER_denom_pub_free (&rms->fresh_pks[i].key);
}
GNUNET_free (rms->fresh_pks);
- rms->fresh_pks = NULL;
- json_decref (rms->refresh_data);
- rms->refresh_data = NULL;
+ GNUNET_free (rms->alg_values);
GNUNET_free (rms->melt_fresh_amounts);
GNUNET_free (rms);
}