diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/taler_crypto_lib.h | 4 | ||||
-rw-r--r-- | src/include/taler_exchange_service.h | 8 | ||||
-rw-r--r-- | src/lib/exchange_api_melt.c | 51 | ||||
-rw-r--r-- | src/lib/exchange_api_withdraw.c | 5 | ||||
-rw-r--r-- | src/lib/exchange_api_withdraw2.c | 11 | ||||
-rw-r--r-- | src/testing/testing_api_cmd_refresh.c | 103 |
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); } |