From ded7f9ca189d8abbfcb6eb874d68bdc1a644da8f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 28 Jun 2022 20:25:45 +0200 Subject: -fix issue with missing signature over denomination and age restriction hash in purse deposit --- src/auditor/taler-helper-auditor-coins.c | 2 + src/auditor/taler-helper-auditor-reserves.c | 50 +++++++++++----------- src/exchange/taler-exchange-httpd_purses_create.c | 47 ++++++++++++++------ src/exchange/taler-exchange-httpd_purses_deposit.c | 46 ++++++++++++++------ src/exchange/taler-exchange-httpd_responses.c | 7 +++ src/exchangedb/plugin_exchangedb_postgres.c | 16 +++++++ src/include/taler_crypto_lib.h | 8 ++++ src/include/taler_exchangedb_plugin.h | 17 +++++--- src/lib/exchange_api_common.c | 19 ++++++++ src/lib/exchange_api_common.h | 4 ++ src/lib/exchange_api_purse_create_with_deposit.c | 30 +++++++++++-- src/lib/exchange_api_purse_deposit.c | 46 +++++++++++++++----- src/util/wallet_signatures.c | 23 ++++++++-- 13 files changed, 240 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c index 56afdeb90..6940369f9 100644 --- a/src/auditor/taler-helper-auditor-coins.c +++ b/src/auditor/taler-helper-auditor-coins.c @@ -2414,6 +2414,8 @@ purse_deposit_cb ( : TALER_ARL_exchange_url, &deposit->purse_pub, &deposit->amount, + &dh, + &deposit->h_age_commitment, &deposit->coin_pub, &deposit->coin_sig)) { diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c index f0c92c260..54d3db7c3 100644 --- a/src/auditor/taler-helper-auditor-reserves.c +++ b/src/auditor/taler-helper-auditor-reserves.c @@ -1289,38 +1289,15 @@ handle_purse_deposits ( struct TALER_Amount amount_minus_fee; struct TALER_Amount new_balance; struct ReserveSummary *rs; + struct TALER_DenominationHashP h_denom_pub; /* should be monotonically increasing */ GNUNET_assert (rowid >= ppr.last_purse_deposits_serial_id); ppr.last_purse_deposits_serial_id = rowid + 1; - if (GNUNET_OK != - TALER_wallet_purse_deposit_verify (base_url, - &deposit->purse_pub, - &deposit->amount, - &deposit->coin_pub, - &deposit->coin_sig)) - { - TALER_ARL_report (report_bad_sig_losses, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("operation", - "purse-deposit"), - GNUNET_JSON_pack_uint64 ("row", - rowid), - TALER_JSON_pack_amount ("loss", - &deposit->amount), - GNUNET_JSON_pack_data_auto ("key_pub", - &deposit->coin_pub))); - TALER_ARL_amount_add (&total_bad_sig_loss, - &total_bad_sig_loss, - &deposit->amount); - return GNUNET_OK; - } - { const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue; enum GNUNET_DB_QueryStatus qs; - struct TALER_DenominationHashP h_denom_pub; qs = TALER_ARL_get_denomination_info (denom_pub, &issue, @@ -1349,6 +1326,31 @@ handle_purse_deposits ( &issue->fees.deposit); } + if (GNUNET_OK != + TALER_wallet_purse_deposit_verify (base_url, + &deposit->purse_pub, + &deposit->amount, + &h_denom_pub, + &deposit->h_age_commitment, + &deposit->coin_pub, + &deposit->coin_sig)) + { + TALER_ARL_report (report_bad_sig_losses, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("operation", + "purse-deposit"), + GNUNET_JSON_pack_uint64 ("row", + rowid), + TALER_JSON_pack_amount ("loss", + &deposit->amount), + GNUNET_JSON_pack_data_auto ("key_pub", + &deposit->coin_pub))); + TALER_ARL_amount_add (&total_bad_sig_loss, + &total_bad_sig_loss, + &deposit->amount); + return GNUNET_OK; + } + TALER_ARL_amount_add (&new_balance, auditor_balance, &amount_minus_fee); diff --git a/src/exchange/taler-exchange-httpd_purses_create.c b/src/exchange/taler-exchange-httpd_purses_create.c index 2c8032342..b016aeee4 100644 --- a/src/exchange/taler-exchange-httpd_purses_create.c +++ b/src/exchange/taler-exchange-httpd_purses_create.c @@ -335,6 +335,8 @@ create_transaction (void *cls, struct TALER_Amount amount; struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_DenominationHashP h_denom_pub; + struct TALER_AgeCommitmentHash phac; char *partner_url = NULL; TEH_plugin->rollback (TEH_plugin->cls); @@ -342,6 +344,8 @@ create_transaction (void *cls, pcc->purse_pub, &coin->cpi.coin_pub, &amount, + &h_denom_pub, + &phac, &coin_sig, &partner_url); if (qs < 0) @@ -366,6 +370,10 @@ create_transaction (void *cls, &coin_pub), GNUNET_JSON_pack_data_auto ("coin_sig", &coin_sig), + GNUNET_JSON_pack_data_auto ("h_denom_pub", + &h_denom_pub), + GNUNET_JSON_pack_data_auto ("h_age_restrictions", + &phac), GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("partner_url", partner_url)), @@ -493,22 +501,33 @@ parse_coin (struct MHD_Connection *connection, return res; } - if (GNUNET_OK != - TALER_wallet_purse_deposit_verify (TEH_base_url, - pcc->purse_pub, - &coin->amount, - &coin->cpi.coin_pub, - &coin->coin_sig)) { - TALER_LOG_WARNING ( - "Invalid coin signature on /purses/$PID/create request\n"); - GNUNET_JSON_parse_free (spec); - return (MHD_YES == - TALER_MHD_reply_with_error (connection, - MHD_HTTP_FORBIDDEN, - TALER_EC_EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID, - TEH_base_url)) + struct TALER_AgeCommitmentHash h_age; + + if (no_age_commitment) + memset (&h_age, 0, sizeof (h_age)); + else + TALER_age_commitment_hash (&age_commitment, + &h_age); + if (GNUNET_OK != + TALER_wallet_purse_deposit_verify (TEH_base_url, + pcc->purse_pub, + &coin->amount, + &coin->cpi.denom_pub_hash, + &h_age, + &coin->cpi.coin_pub, + &coin->coin_sig)) + { + TALER_LOG_WARNING ( + "Invalid coin signature on /purses/$PID/create request\n"); + GNUNET_JSON_parse_free (spec); + return (MHD_YES == + TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_EXCHANGE_PURSE_CREATE_COIN_SIGNATURE_INVALID, + TEH_base_url)) ? GNUNET_NO : GNUNET_SYSERR; + } } /* check denomination exists and is valid */ { diff --git a/src/exchange/taler-exchange-httpd_purses_deposit.c b/src/exchange/taler-exchange-httpd_purses_deposit.c index af7200f12..4158b2936 100644 --- a/src/exchange/taler-exchange-httpd_purses_deposit.c +++ b/src/exchange/taler-exchange-httpd_purses_deposit.c @@ -239,6 +239,8 @@ deposit_transaction (void *cls, struct TALER_Amount amount; struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_DenominationHashP h_denom_pub; + struct TALER_AgeCommitmentHash phac; char *partner_url = NULL; TEH_plugin->rollback (TEH_plugin->cls); @@ -246,6 +248,8 @@ deposit_transaction (void *cls, pcc->purse_pub, &coin->cpi.coin_pub, &amount, + &h_denom_pub, + &phac, &coin_sig, &partner_url); if (qs < 0) @@ -268,6 +272,10 @@ deposit_transaction (void *cls, TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA), GNUNET_JSON_pack_data_auto ("coin_pub", &coin_pub), + GNUNET_JSON_pack_data_auto ("h_denom_pub", + &h_denom_pub), + GNUNET_JSON_pack_data_auto ("h_age_commitment", + &phac), GNUNET_JSON_pack_data_auto ("coin_sig", &coin_sig), GNUNET_JSON_pack_allow_null ( @@ -336,21 +344,33 @@ parse_coin (struct MHD_Connection *connection, if (GNUNET_OK != res) return res; } - if (GNUNET_OK != - TALER_wallet_purse_deposit_verify (TEH_base_url, - pcc->purse_pub, - &coin->amount, - &coin->cpi.coin_pub, - &coin->coin_sig)) { - TALER_LOG_WARNING ("Invalid signature on /purses/$PID/deposit request\n"); - GNUNET_JSON_parse_free (spec); - return (MHD_YES == - TALER_MHD_reply_with_error (connection, - MHD_HTTP_FORBIDDEN, - TALER_EC_EXCHANGE_PURSE_DEPOSIT_COIN_SIGNATURE_INVALID, - TEH_base_url)) + struct TALER_AgeCommitmentHash h_age; + + if (no_age_commitment) + memset (&h_age, 0, sizeof (h_age)); + else + TALER_age_commitment_hash (&age_commitment, + &h_age); + + if (GNUNET_OK != + TALER_wallet_purse_deposit_verify (TEH_base_url, + pcc->purse_pub, + &coin->amount, + &coin->cpi.denom_pub_hash, + &h_age, + &coin->cpi.coin_pub, + &coin->coin_sig)) + { + TALER_LOG_WARNING ("Invalid signature on /purses/$PID/deposit request\n"); + GNUNET_JSON_parse_free (spec); + return (MHD_YES == + TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_EXCHANGE_PURSE_DEPOSIT_COIN_SIGNATURE_INVALID, + TEH_base_url)) ? GNUNET_NO : GNUNET_SYSERR; + } } /* check denomination exists and is valid */ { diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 429647e16..92c585b4d 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -391,6 +391,10 @@ TEH_RESPONSE_compile_transaction_history ( { struct TALER_EXCHANGEDB_PurseDepositListEntry *pd = pos->details.purse_deposit; + const struct TALER_AgeCommitmentHash *phac = NULL; + + if (! pd->no_age_commitment) + phac = &pd->h_age_commitment; if (0 != json_array_append_new ( @@ -404,6 +408,9 @@ TEH_RESPONSE_compile_transaction_history ( NULL == pd->exchange_base_url ? TEH_base_url : pd->exchange_base_url), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_data_auto ("h_age_commitment", + phac)), GNUNET_JSON_pack_data_auto ("purse_pub", &pd->purse_pub), GNUNET_JSON_pack_bool ("refunded", diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index d3bbb4d6a..5985fa95d 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -1275,6 +1275,7 @@ prepare_statements (struct PostgresClosure *pg) ",denoms.fee_deposit_val" ",denoms.fee_deposit_frac" ",pd.purse_pub" + ",kc.age_commitment_hash" ",pd.coin_sig" ",pd.purse_deposit_serial_id" ",pr.refunded" @@ -4199,9 +4200,13 @@ prepare_statements (struct PostgresClosure *pg) " coin_sig" ",amount_with_fee_val" ",amount_with_fee_frac" + ",denom_pub_hash" + ",age_commitment_hash" ",partner_base_url" " FROM purse_deposits" " LEFT JOIN partners USING (partner_serial_id)" + " JOIN known_coins kc USING (coin_pub)" + " JOIN denominations USING (denominations_serial)" " WHERE coin_pub=$2" " AND purse_pub=$1;", 2), @@ -8571,6 +8576,8 @@ add_coin_purse_deposit (void *cls, NULL), GNUNET_PQ_result_spec_auto_from_type ("coin_sig", &deposit->coin_sig), + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + &deposit->h_age_commitment), GNUNET_PQ_result_spec_bool ("refunded", &deposit->refunded), GNUNET_PQ_result_spec_end @@ -8586,6 +8593,7 @@ add_coin_purse_deposit (void *cls, chc->failed = true; return; } + deposit->no_age_commitment = GNUNET_is_zero (&deposit->h_age_commitment); } tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList); tl->next = chc->head; @@ -15623,6 +15631,8 @@ postgres_set_purse_balance ( * @param purse_pub purse to credit * @param coin_pub coin to deposit (debit) * @param[out] amount set fraction of the coin's value that was deposited (with fee) + * @param[out] h_denom_pub set to hash of denomination of the coin + * @param[out] phac set to hash of age restriction on the coin * @param[out] coin_sig set to signature affirming the operation * @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller * @return transaction status code @@ -15633,6 +15643,8 @@ postgres_get_purse_deposit ( const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_Amount *amount, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHash *phac, struct TALER_CoinSpendSignatureP *coin_sig, char **partner_url) { @@ -15644,6 +15656,10 @@ postgres_get_purse_deposit ( }; bool is_null; struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", + h_denom_pub), + GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", + phac), GNUNET_PQ_result_spec_auto_from_type ("coin_sig", coin_sig), TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 274a18deb..fa13a29ca 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -2887,6 +2887,8 @@ TALER_wallet_purse_status_verify ( * @param exchange_base_url URL of the exchange hosting the purse * @param purse_pub purse’s public key * @param amount amount of the coin's value to transfer to the purse + * @param h_denom_pub hash of the coin's denomination + * @param h_age_commitment hash of the coin's age commitment * @param coin_priv key identifying the coin to be deposited * @param[out] coin_sig resulting signature */ @@ -2895,6 +2897,8 @@ TALER_wallet_purse_deposit_sign ( const char *exchange_base_url, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig); @@ -2905,6 +2909,8 @@ TALER_wallet_purse_deposit_sign ( * @param exchange_base_url URL of the exchange hosting the purse * @param purse_pub purse’s public key * @param amount amount of the coin's value to transfer to the purse + * @param h_denom_pub hash of the coin's denomination + * @param h_age_commitment hash of the coin's age commitment * @param coin_pub key identifying the coin that is being deposited * @param[out] coin_sig resulting signature * @return #GNUNET_OK if the signature is valid @@ -2914,6 +2920,8 @@ TALER_wallet_purse_deposit_verify ( const char *exchange_base_url, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 42a6795f9..4ec2b6c78 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1687,20 +1687,21 @@ struct TALER_EXCHANGEDB_PurseDepositListEntry struct TALER_CoinSpendSignatureP coin_sig; /** - * FIXME-Oec: probably needed here, not yet used - * anywhere! - * * Hash of the age commitment used to sign the coin, if age restriction was - * applicable to the denomination. May be all zeroes if no age restriction - * applies. + * applicable to the denomination. */ - struct TALER_AgeCommitmentHash h_age_commitment_FIXME; + struct TALER_AgeCommitmentHash h_age_commitment; /** * Set to true if the coin was refunded. */ bool refunded; + /** + * Set to true if there was no age commitment. + */ + bool no_age_commitment; + }; @@ -5349,6 +5350,8 @@ struct TALER_EXCHANGEDB_Plugin * @param purse_pub purse to credit * @param coin_pub coin to deposit (debit) * @param[out] amount set fraction of the coin's value that was deposited (with fee) + * @param[out] h_denom_pub set to hash of denomination of the coin + * @param[out] phac set to hash of age restriction on the coin * @param[out] coin_sig set to signature affirming the operation * @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller * @return transaction status code @@ -5359,6 +5362,8 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_Amount *amount, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHash *phac, struct TALER_CoinSpendSignatureP *coin_sig, char **partner_url); diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index 4b36aa932..26ddb3c06 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -1170,13 +1170,22 @@ help_purse_deposit (struct CoinHistoryParseContext *pc, struct TALER_CoinSpendSignatureP coin_sig; const char *exchange_base_url; bool refunded; + struct TALER_AgeCommitmentHash phac = { 0 }; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("purse_pub", &purse_pub), GNUNET_JSON_spec_fixed_auto ("coin_sig", &coin_sig), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_fixed_auto ("h_age_commitment", + &coin_sig), + NULL), GNUNET_JSON_spec_string ("exchange_base_url", &exchange_base_url), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_fixed_auto ("h_age_commitment", + &phac), + NULL), GNUNET_JSON_spec_bool ("refunded", &refunded), GNUNET_JSON_spec_end () @@ -1195,6 +1204,8 @@ help_purse_deposit (struct CoinHistoryParseContext *pc, exchange_base_url, &purse_pub, amount, + &pc->dk->h_key, + &phac, pc->coin_pub, &coin_sig)) { @@ -1560,12 +1571,18 @@ TALER_EXCHANGE_check_purse_coin_conflict_ ( const struct TALER_PurseContractPublicKeyP *purse_pub, const char *exchange_url, const json_t *proof, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHash *phac, struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_CoinSpendSignatureP *coin_sig) { const char *partner_url = NULL; struct TALER_Amount amount; struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("h_denom_pub", + h_denom_pub), + GNUNET_JSON_spec_fixed_auto ("h_age_commitment", + phac), GNUNET_JSON_spec_fixed_auto ("coin_sig", coin_sig), GNUNET_JSON_spec_fixed_auto ("coin_pub", @@ -1594,6 +1611,8 @@ TALER_EXCHANGE_check_purse_coin_conflict_ ( partner_url, purse_pub, &amount, + h_denom_pub, + phac, coin_pub, coin_sig)) { diff --git a/src/lib/exchange_api_common.h b/src/lib/exchange_api_common.h index 5721b376c..f4737ca98 100644 --- a/src/lib/exchange_api_common.h +++ b/src/lib/exchange_api_common.h @@ -75,6 +75,8 @@ TALER_EXCHANGE_check_purse_merge_conflict_ ( * @param purse_pub the public key of the purse * @param exchange_url base URL of our exchange * @param proof the proof to check + * @param[out] h_denom_pub hash of the coin's denomination + * @param[out] phac age commitment hash of the coin * @param[out] coin_pub set to the conflicting coin * @param[out] coin_sig set to the conflicting signature * @return #GNUNET_OK if the @a proof is OK for @a purse_pub and showing that @a coin_pub was spent using @a coin_sig. @@ -84,6 +86,8 @@ TALER_EXCHANGE_check_purse_coin_conflict_ ( const struct TALER_PurseContractPublicKeyP *purse_pub, const char *exchange_url, const json_t *proof, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHash *phac, struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_CoinSpendSignatureP *coin_sig); diff --git a/src/lib/exchange_api_purse_create_with_deposit.c b/src/lib/exchange_api_purse_create_with_deposit.c index fa1de60b3..3a5b7df59 100644 --- a/src/lib/exchange_api_purse_create_with_deposit.c +++ b/src/lib/exchange_api_purse_create_with_deposit.c @@ -54,6 +54,11 @@ struct Deposit */ struct TALER_DenominationHashP h_denom_pub; + /** + * Age restriction hash for the coin. + */ + struct TALER_AgeCommitmentHash ahac; + /** * How much did we say the coin contributed. */ @@ -375,6 +380,8 @@ handle_purse_create_deposit_finished (void *cls, { struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_DenominationHashP h_denom_pub; + struct TALER_AgeCommitmentHash phac; bool found = false; if (GNUNET_OK != @@ -382,6 +389,8 @@ handle_purse_create_deposit_finished (void *cls, &pch->purse_pub, pch->exchange->url, j, + &h_denom_pub, + &phac, &coin_pub, &coin_sig)) { @@ -398,6 +407,20 @@ handle_purse_create_deposit_finished (void *cls, GNUNET_memcmp (&coin_pub, &deposit->coin_pub)) continue; + if (0 != + GNUNET_memcmp (&deposit->h_denom_pub, + &h_denom_pub)) + { + found = true; + break; + } + if (0 != + GNUNET_memcmp (&deposit->ahac, + &phac)) + { + found = true; + break; + } if (0 == GNUNET_memcmp (&coin_sig, &deposit->coin_sig)) @@ -571,7 +594,6 @@ TALER_EXCHANGE_purse_create_with_deposit ( const struct TALER_AgeCommitmentProof *acp = deposit->age_commitment_proof; struct Deposit *d = &pch->deposits[i]; json_t *jdeposit; - struct TALER_AgeCommitmentHash agh; struct TALER_AgeCommitmentHash *aghp = NULL; struct TALER_AgeAttestation attest; struct TALER_AgeAttestation *attestp = NULL; @@ -579,8 +601,8 @@ TALER_EXCHANGE_purse_create_with_deposit ( if (NULL != acp) { TALER_age_commitment_hash (&acp->commitment, - &agh); - aghp = &agh; + &d->ahac); + aghp = &d->ahac; if (GNUNET_OK != TALER_age_commitment_attest (acp, min_age, @@ -601,6 +623,8 @@ TALER_EXCHANGE_purse_create_with_deposit ( url, &pch->purse_pub, &deposit->amount, + &d->h_denom_pub, + &d->ahac, &deposit->coin_priv, &d->coin_sig); jdeposit = GNUNET_JSON_PACK ( diff --git a/src/lib/exchange_api_purse_deposit.c b/src/lib/exchange_api_purse_deposit.c index 836183bbe..922251012 100644 --- a/src/lib/exchange_api_purse_deposit.c +++ b/src/lib/exchange_api_purse_deposit.c @@ -54,6 +54,11 @@ struct Coin */ struct TALER_DenominationHashP h_denom_pub; + /** + * Age restriction hash for the coin. + */ + struct TALER_AgeCommitmentHash ahac; + /** * How much did we say the coin contributed. */ @@ -234,6 +239,8 @@ handle_purse_deposit_finished (void *cls, { struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_DenominationHashP h_denom_pub; + struct TALER_AgeCommitmentHash phac; bool found = false; if (GNUNET_OK != @@ -241,6 +248,8 @@ handle_purse_deposit_finished (void *cls, &pch->purse_pub, pch->base_url, j, + &h_denom_pub, + &phac, &coin_pub, &coin_sig)) { @@ -251,18 +260,32 @@ handle_purse_deposit_finished (void *cls, } for (unsigned int i = 0; inum_deposits; i++) { - if (0 == GNUNET_memcmp (&coin_pub, - &pch->coins[i].coin_pub)) + struct Coin *coin = &pch->coins[i]; + if (0 != GNUNET_memcmp (&coin_pub, + &coin->coin_pub)) + continue; + if (0 != + GNUNET_memcmp (&coin->h_denom_pub, + &h_denom_pub)) + { + found = true; + break; + } + if (0 != + GNUNET_memcmp (&coin->ahac, + &phac)) { - if (0 == GNUNET_memcmp (&coin_sig, - &pch->coins[i].coin_sig)) - { - /* identical signature => not a conflict */ - continue; - } found = true; break; } + if (0 == GNUNET_memcmp (&coin_sig, + &coin->coin_sig)) + { + /* identical signature => not a conflict */ + continue; + } + found = true; + break; } if (! found) { @@ -488,7 +511,6 @@ TALER_EXCHANGE_purse_deposit ( const struct TALER_AgeCommitmentProof *acp = deposit->age_commitment_proof; struct Coin *coin = &pch->coins[i]; json_t *jdeposit; - struct TALER_AgeCommitmentHash ach; struct TALER_AgeCommitmentHash *achp = NULL; struct TALER_AgeAttestation attest; struct TALER_AgeAttestation *attestp = NULL; @@ -496,8 +518,8 @@ TALER_EXCHANGE_purse_deposit ( if (NULL != acp) { TALER_age_commitment_hash (&acp->commitment, - &ach); - achp = &ach; + &coin->ahac); + achp = &coin->ahac; if (GNUNET_OK != TALER_age_commitment_attest (acp, min_age, @@ -520,6 +542,8 @@ TALER_EXCHANGE_purse_deposit ( pch->base_url, &pch->purse_pub, &deposit->amount, + &coin->h_denom_pub, + &coin->ahac, &deposit->coin_priv, &coin->coin_sig); jdeposit = GNUNET_JSON_PACK ( diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c index 1b8015628..f4efb2719 100644 --- a/src/util/wallet_signatures.c +++ b/src/util/wallet_signatures.c @@ -898,9 +898,16 @@ struct TALER_PurseDepositPS */ struct TALER_AmountNBO coin_amount; - // FIXME-CG: also sign over age commitment hash AND - // denomination hash, needed for proper known-coin - // conflict proofs! + /** + * Hash over the denomination public key used to sign the coin. + */ + struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED; + + /** + * Hash over the age commitment that went into the coin. Maybe all zero, if + * age commitment isn't applicable to the denomination. + */ + struct TALER_AgeCommitmentHash h_age_commitment GNUNET_PACKED; /** * Purse to deposit funds into. @@ -911,7 +918,7 @@ struct TALER_PurseDepositPS * Hash of the base URL of the exchange hosting the * @e purse_pub. */ - struct GNUNET_HashCode h_exchange_base_url; + struct GNUNET_HashCode h_exchange_base_url GNUNET_PACKED; }; @@ -920,6 +927,8 @@ TALER_wallet_purse_deposit_sign ( const char *exchange_base_url, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig) { @@ -927,6 +936,8 @@ TALER_wallet_purse_deposit_sign ( .purpose.size = htonl (sizeof (pm)), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT), .purse_pub = *purse_pub, + .h_denom_pub = *h_denom_pub, + .h_age_commitment = *h_age_commitment }; GNUNET_CRYPTO_hash (exchange_base_url, @@ -945,6 +956,8 @@ TALER_wallet_purse_deposit_verify ( const char *exchange_base_url, const struct TALER_PurseContractPublicKeyP *purse_pub, const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig) { @@ -952,6 +965,8 @@ TALER_wallet_purse_deposit_verify ( .purpose.size = htonl (sizeof (pm)), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT), .purse_pub = *purse_pub, + .h_denom_pub = *h_denom_pub, + .h_age_commitment = *h_age_commitment }; GNUNET_CRYPTO_hash (exchange_base_url, -- cgit v1.2.3