-fixes to tests, and half-baked fixes for CS-/link (still fails)

This commit is contained in:
Christian Grothoff 2022-02-10 23:39:00 +01:00
parent d58d89dcab
commit 532d4ad0dc
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
15 changed files with 354 additions and 23 deletions

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2019 Taler Systems SA Copyright (C) 2014-2019, 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -86,6 +86,10 @@ handle_link_data (void *cls,
&pos->denom_pub), &pos->denom_pub),
TALER_JSON_pack_blinded_denom_sig ("ev_sig", TALER_JSON_pack_blinded_denom_sig ("ev_sig",
&pos->ev_sig), &pos->ev_sig),
GNUNET_JSON_pack_uint64 ("coin_idx",
pos->coin_refresh_offset),
TALER_JSON_pack_exchange_withdraw_values ("ewv",
&pos->alg_values),
GNUNET_JSON_pack_data_auto ("link_sig", GNUNET_JSON_pack_data_auto ("link_sig",
&pos->orig_coin_link_sig)); &pos->orig_coin_link_sig));
if ( (NULL == obj) || if ( (NULL == obj) ||

View File

@ -105,7 +105,10 @@ struct RevealContext
/** /**
* Array of information about fresh coins being revealed. * Array of information about fresh coins being revealed.
*/ */
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs; /* FIXME: const would be nicer here, but we initalize
the 'alg_values' in the verification
routine; suboptimal to be fixed... */
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs;
/** /**
* Envelopes to be signed. * Envelopes to be signed.
@ -141,7 +144,6 @@ check_commitment (struct RevealContext *rctx,
struct MHD_Connection *connection, struct MHD_Connection *connection,
MHD_RESULT *mhd_ret) MHD_RESULT *mhd_ret)
{ {
struct TALER_ExchangeWithdrawValues alg_values[rctx->num_fresh_coins];
struct TALER_CsNonce nonces[rctx->num_fresh_coins]; struct TALER_CsNonce nonces[rctx->num_fresh_coins];
unsigned int aoff = 0; unsigned int aoff = 0;
@ -184,8 +186,10 @@ check_commitment (struct RevealContext *rctx,
for (unsigned int j = 0; j<rctx->num_fresh_coins; j++) for (unsigned int j = 0; j<rctx->num_fresh_coins; j++)
{ {
const struct TALER_DenominationPublicKey *dk = &rctx->dks[j]->denom_pub; const struct TALER_DenominationPublicKey *dk = &rctx->dks[j]->denom_pub;
struct TALER_ExchangeWithdrawValues *alg_values
= &rctx->rrcs[j].exchange_vals;
alg_values[j].cipher = dk->cipher; alg_values->cipher = dk->cipher;
switch (dk->cipher) switch (dk->cipher)
{ {
case TALER_DENOMINATION_INVALID: case TALER_DENOMINATION_INVALID:
@ -200,7 +204,7 @@ check_commitment (struct RevealContext *rctx,
ec = TEH_keys_denomination_cs_r_pub ( ec = TEH_keys_denomination_cs_r_pub (
&rctx->rrcs[j].h_denom_pub, &rctx->rrcs[j].h_denom_pub,
&nonces[aoff], &nonces[aoff],
&alg_values[j].details.cs_values.r_pub_pair); &alg_values->details.cs_values.r_pub_pair);
if (TALER_EC_NONE != ec) if (TALER_EC_NONE != ec)
{ {
*mhd_ret = TALER_MHD_reply_with_error (connection, *mhd_ret = TALER_MHD_reply_with_error (connection,
@ -251,12 +255,13 @@ check_commitment (struct RevealContext *rctx,
aoff = 0; aoff = 0;
for (unsigned int j = 0; j<rctx->num_fresh_coins; j++) for (unsigned int j = 0; j<rctx->num_fresh_coins; j++)
{ {
const struct TALER_DenominationPublicKey *dk = const struct TALER_DenominationPublicKey *dk
&rctx->dks[j]->denom_pub; = &rctx->dks[j]->denom_pub;
struct TALER_RefreshCoinData *rcd = &rce->new_coins[j]; struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
struct TALER_CoinSpendPrivateKeyP coin_priv; struct TALER_CoinSpendPrivateKeyP coin_priv;
union TALER_DenominationBlindingKeyP bks; union TALER_DenominationBlindingKeyP bks;
const struct TALER_ExchangeWithdrawValues *alg_value = &alg_values[j]; const struct TALER_ExchangeWithdrawValues *alg_value
= &rctx->rrcs[j].exchange_vals;
struct TALER_PlanchetDetail pd; struct TALER_PlanchetDetail pd;
struct TALER_CoinPubHash c_hash; struct TALER_CoinPubHash c_hash;
struct TALER_PlanchetSecretsP ps; struct TALER_PlanchetSecretsP ps;

View File

@ -377,6 +377,7 @@ CREATE TABLE IF NOT EXISTS refresh_revealed_coins
,coin_ev BYTEA NOT NULL -- UNIQUE ,coin_ev BYTEA NOT NULL -- UNIQUE
,h_coin_ev BYTEA NOT NULL CHECK(LENGTH(h_coin_ev)=64) -- UNIQUE ,h_coin_ev BYTEA NOT NULL CHECK(LENGTH(h_coin_ev)=64) -- UNIQUE
,ev_sig BYTEA NOT NULL ,ev_sig BYTEA NOT NULL
,ewv BYTEA NOT NULL
-- ,PRIMARY KEY (melt_serial_id, freshcoin_index) -- done per shard -- ,PRIMARY KEY (melt_serial_id, freshcoin_index) -- done per shard
) )
PARTITION BY HASH (melt_serial_id); PARTITION BY HASH (melt_serial_id);
@ -390,6 +391,8 @@ COMMENT ON COLUMN refresh_revealed_coins.freshcoin_index
IS 'index of the fresh coin being created (one melt operation may result in multiple fresh coins)'; IS 'index of the fresh coin being created (one melt operation may result in multiple fresh coins)';
COMMENT ON COLUMN refresh_revealed_coins.coin_ev COMMENT ON COLUMN refresh_revealed_coins.coin_ev
IS 'envelope of the new coin to be signed'; IS 'envelope of the new coin to be signed';
COMMENT ON COLUMN refresh_revealed_coins.ewv
IS 'exchange contributed values in the creation of the fresh coin (see /csr)';
COMMENT ON COLUMN refresh_revealed_coins.h_coin_ev COMMENT ON COLUMN refresh_revealed_coins.h_coin_ev
IS 'hash of the envelope of the new coin to be signed (for lookups)'; IS 'hash of the envelope of the new coin to be signed (for lookups)';
COMMENT ON COLUMN refresh_revealed_coins.ev_sig COMMENT ON COLUMN refresh_revealed_coins.ev_sig

View File

@ -440,6 +440,8 @@ irbt_cb_table_refresh_revealed_coins (
GNUNET_PQ_query_param_auto_from_type (&h_coin_ev), GNUNET_PQ_query_param_auto_from_type (&h_coin_ev),
TALER_PQ_query_param_blinded_denom_sig ( TALER_PQ_query_param_blinded_denom_sig (
&td->details.refresh_revealed_coins.ev_sig), &td->details.refresh_revealed_coins.ev_sig),
TALER_PQ_query_param_exchange_withdraw_values (
&td->details.refresh_revealed_coins.ewv),
GNUNET_PQ_query_param_uint64 ( GNUNET_PQ_query_param_uint64 (
&td->details.refresh_revealed_coins.denominations_serial), &td->details.refresh_revealed_coins.denominations_serial),
GNUNET_PQ_query_param_uint64 ( GNUNET_PQ_query_param_uint64 (

View File

@ -790,6 +790,9 @@ lrbt_cb_table_refresh_revealed_coins (void *cls,
TALER_PQ_result_spec_blinded_denom_sig ( TALER_PQ_result_spec_blinded_denom_sig (
"ev_sig", "ev_sig",
&td.details.refresh_revealed_coins.ev_sig), &td.details.refresh_revealed_coins.ev_sig),
TALER_PQ_result_spec_exchange_withdraw_values (
"ewv",
&td.details.refresh_revealed_coins.ewv),
GNUNET_PQ_result_spec_uint64 ( GNUNET_PQ_result_spec_uint64 (
"denominations_serial", "denominations_serial",
&td.details.refresh_revealed_coins.denominations_serial), &td.details.refresh_revealed_coins.denominations_serial),

View File

@ -891,13 +891,14 @@ prepare_statements (struct PostgresClosure *pg)
",link_sig " ",link_sig "
",denominations_serial " ",denominations_serial "
",coin_ev" ",coin_ev"
",ewv"
",h_coin_ev" ",h_coin_ev"
",ev_sig" ",ev_sig"
") SELECT $1, $2, $3, " ") SELECT $1, $2, $3, "
" denominations_serial, $5, $6, $7" " denominations_serial, $5, $6, $7, $8"
" FROM denominations" " FROM denominations"
" WHERE denom_pub_hash=$4;", " WHERE denom_pub_hash=$4;",
7), 8),
/* Obtain information about the coins created in a refresh /* Obtain information about the coins created in a refresh
operation, used in #postgres_get_refresh_reveal() */ operation, used in #postgres_get_refresh_reveal() */
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
@ -908,6 +909,7 @@ prepare_statements (struct PostgresClosure *pg)
",rrc.h_coin_ev" ",rrc.h_coin_ev"
",rrc.link_sig" ",rrc.link_sig"
",rrc.coin_ev" ",rrc.coin_ev"
",rrc.ewv"
",rrc.ev_sig" ",rrc.ev_sig"
" FROM refresh_commitments" " FROM refresh_commitments"
" JOIN refresh_revealed_coins rrc" " JOIN refresh_revealed_coins rrc"
@ -1213,7 +1215,9 @@ prepare_statements (struct PostgresClosure *pg)
" tp.transfer_pub" " tp.transfer_pub"
",denoms.denom_pub" ",denoms.denom_pub"
",rrc.ev_sig" ",rrc.ev_sig"
",rrc.ewv"
",rrc.link_sig" ",rrc.link_sig"
",rrc.freshcoin_index"
" FROM refresh_commitments" " FROM refresh_commitments"
" JOIN refresh_revealed_coins rrc" " JOIN refresh_revealed_coins rrc"
" USING (melt_serial_id)" " USING (melt_serial_id)"
@ -2241,6 +2245,7 @@ prepare_statements (struct PostgresClosure *pg)
",link_sig" ",link_sig"
",coin_ev" ",coin_ev"
",ev_sig" ",ev_sig"
",ewv"
",denominations_serial" ",denominations_serial"
",melt_serial_id" ",melt_serial_id"
" FROM refresh_revealed_coins" " FROM refresh_revealed_coins"
@ -2532,11 +2537,12 @@ prepare_statements (struct PostgresClosure *pg)
",coin_ev" ",coin_ev"
",h_coin_ev" ",h_coin_ev"
",ev_sig" ",ev_sig"
",ewv"
",denominations_serial" ",denominations_serial"
",melt_serial_id" ",melt_serial_id"
") VALUES " ") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8);", "($1, $2, $3, $4, $5, $6, $7, $8, $9);",
8), 9),
GNUNET_PQ_make_prepare ( GNUNET_PQ_make_prepare (
"insert_into_table_refresh_transfer_keys", "insert_into_table_refresh_transfer_keys",
"INSERT INTO refresh_transfer_keys" "INSERT INTO refresh_transfer_keys"
@ -6095,6 +6101,8 @@ postgres_insert_refresh_reveal (
GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig), GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub), GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet), TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
// FIXME: needed? review link protocol!
TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals),
GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash), GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig), TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
@ -6203,6 +6211,9 @@ add_revealed_coins (void *cls,
&rrc->coin_envelope_hash), &rrc->coin_envelope_hash),
TALER_PQ_result_spec_blinded_planchet ("coin_ev", TALER_PQ_result_spec_blinded_planchet ("coin_ev",
&rrc->blinded_planchet), &rrc->blinded_planchet),
// FIXME: needed? review link protocol!
TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
&rrc->exchange_vals),
TALER_PQ_result_spec_blinded_denom_sig ("ev_sig", TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
&rrc->coin_sig), &rrc->coin_sig),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
@ -6384,6 +6395,11 @@ add_ldl (void *cls,
&pos->orig_coin_link_sig), &pos->orig_coin_link_sig),
TALER_PQ_result_spec_blinded_denom_sig ("ev_sig", TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
&pos->ev_sig), &pos->ev_sig),
GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
&pos->coin_refresh_offset),
// FIXME: needed? review link protocol!
TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
&pos->alg_values),
TALER_PQ_result_spec_denom_pub ("denom_pub", TALER_PQ_result_spec_denom_pub ("denom_pub",
&pos->denom_pub), &pos->denom_pub),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end

View File

@ -1565,6 +1565,8 @@ run (void *cls)
TALER_denom_sig_unblind (&ds, TALER_denom_sig_unblind (&ds,
&cbc2.sig, &cbc2.sig,
&bks, &bks,
&c_hash,
&alg_values,
&dkp->pub)); &dkp->pub));
FAILIF (GNUNET_OK != FAILIF (GNUNET_OK !=
TALER_denom_pub_verify (&dkp->pub, TALER_denom_pub_verify (&dkp->pub,
@ -1582,6 +1584,8 @@ run (void *cls)
TALER_denom_sig_unblind (&deposit.coin.denom_sig, TALER_denom_sig_unblind (&deposit.coin.denom_sig,
&cbc.sig, &cbc.sig,
&bks, &bks,
&c_hash,
&alg_values,
&dkp->pub)); &dkp->pub));
deadline = GNUNET_TIME_timestamp_get (); deadline = GNUNET_TIME_timestamp_get ();
{ {
@ -1760,6 +1764,7 @@ run (void *cls)
rp->blinded_msg_size); rp->blinded_msg_size);
TALER_denom_pub_hash (&new_dkp[cnt]->pub, TALER_denom_pub_hash (&new_dkp[cnt]->pub,
&ccoin->h_denom_pub); &ccoin->h_denom_pub);
ccoin->exchange_vals = alg_values;
TALER_coin_ev_hash (bp, TALER_coin_ev_hash (bp,
&ccoin->h_denom_pub, &ccoin->h_denom_pub,
&ccoin->coin_envelope_hash); &ccoin->coin_envelope_hash);
@ -2167,6 +2172,8 @@ run (void *cls)
TALER_denom_sig_unblind (&deposit.coin.denom_sig, TALER_denom_sig_unblind (&deposit.coin.denom_sig,
&cbc.sig, &cbc.sig,
&bks, &bks,
&c_hash,
&alg_values,
&dkp->pub)); &dkp->pub));
RND_BLK (&deposit.csig); RND_BLK (&deposit.csig);
RND_BLK (&deposit.merchant_pub); RND_BLK (&deposit.merchant_pub);

View File

@ -317,6 +317,7 @@ struct TALER_EXCHANGEDB_TableData
uint64_t denominations_serial; uint64_t denominations_serial;
void *coin_ev; void *coin_ev;
size_t coin_ev_size; size_t coin_ev_size;
struct TALER_ExchangeWithdrawValues ewv;
// h_coin_ev omitted, to be recomputed! // h_coin_ev omitted, to be recomputed!
struct TALER_BlindedDenominationSignature ev_sig; struct TALER_BlindedDenominationSignature ev_sig;
} refresh_revealed_coins; } refresh_revealed_coins;
@ -1368,12 +1369,23 @@ struct TALER_EXCHANGEDB_LinkList
*/ */
struct TALER_BlindedDenominationSignature ev_sig; struct TALER_BlindedDenominationSignature ev_sig;
/**
* Exchange-provided values during the coin generation.
*/
struct TALER_ExchangeWithdrawValues alg_values;
/** /**
* Signature of the original coin being refreshed over the * Signature of the original coin being refreshed over the
* link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK * link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK
*/ */
struct TALER_CoinSpendSignatureP orig_coin_link_sig; struct TALER_CoinSpendSignatureP orig_coin_link_sig;
/**
* Offset that generated this coin in the refresh
* operation.
*/
uint32_t coin_refresh_offset;
}; };
@ -1645,6 +1657,12 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin
*/ */
struct TALER_BlindedDenominationSignature coin_sig; struct TALER_BlindedDenominationSignature coin_sig;
/**
* Values contributed from the exchange to the
* coin generation (see /csr).
*/
struct TALER_ExchangeWithdrawValues exchange_vals;
/** /**
* Blinded message to be signed (in envelope). * Blinded message to be signed (in envelope).
*/ */

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015, 2016 Taler Systems SA Copyright (C) 2014-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the 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 terms of the GNU General Public License as published by the Free Software
@ -102,6 +102,18 @@ TALER_PQ_query_param_blinded_denom_sig (
const struct TALER_BlindedDenominationSignature *denom_sig); const struct TALER_BlindedDenominationSignature *denom_sig);
/**
* Generate query parameter for the exchange's contribution during a
* withdraw. Internally, the various attributes of the @a alg_values will be
* serialized into on variable-size BLOB.
*
* @param x pointer to the query parameter to pass
*/
struct GNUNET_PQ_QueryParam
TALER_PQ_query_param_exchange_withdraw_values (
const struct TALER_ExchangeWithdrawValues *alg_values);
/** /**
* Generate query parameter for a JSON object (stored as a string * Generate query parameter for a JSON object (stored as a string
* in the DB). Note that @a x must really be a JSON object or array, * in the DB). Note that @a x must really be a JSON object or array,
@ -179,6 +191,19 @@ TALER_PQ_result_spec_blinded_denom_sig (
struct TALER_BlindedDenominationSignature *denom_sig); struct TALER_BlindedDenominationSignature *denom_sig);
/**
* Exchange withdraw values expected.
*
* @param name name of the field in the table
* @param[out] ewv where to store the exchange values
* @return array entry for the result specification to use
*/
struct GNUNET_PQ_ResultSpec
TALER_PQ_result_spec_exchange_withdraw_values (
const char *name,
struct TALER_ExchangeWithdrawValues *ewv);
/** /**
* Blinded planchet expected. * Blinded planchet expected.
* *

View File

@ -95,18 +95,25 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
struct TALER_DenominationPublicKey rpub; struct TALER_DenominationPublicKey rpub;
struct TALER_CoinSpendSignatureP link_sig; struct TALER_CoinSpendSignatureP link_sig;
union TALER_DenominationBlindingKeyP bks; union TALER_DenominationBlindingKeyP bks;
struct TALER_ExchangeWithdrawValues alg_values;
uint32_t coin_idx;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denom_pub ("denom_pub", TALER_JSON_spec_denom_pub ("denom_pub",
&rpub), &rpub),
TALER_JSON_spec_blinded_denom_sig ("ev_sig", TALER_JSON_spec_blinded_denom_sig ("ev_sig",
&bsig), &bsig),
// FIXME: add to spec!
TALER_JSON_spec_exchange_withdraw_values ("ewv",
&alg_values),
GNUNET_JSON_spec_fixed_auto ("link_sig", GNUNET_JSON_spec_fixed_auto ("link_sig",
&link_sig), &link_sig),
// FIXME: add to spec!
GNUNET_JSON_spec_uint32 ("coin_idx",
&coin_idx),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct TALER_TransferSecretP secret; struct TALER_TransferSecretP secret;
struct TALER_PlanchetSecretsP ps; struct TALER_PlanchetSecretsP ps;
struct TALER_ExchangeWithdrawValues alg_values;
struct TALER_PlanchetDetail pd; struct TALER_PlanchetDetail pd;
struct TALER_CoinPubHash c_hash; struct TALER_CoinPubHash c_hash;
@ -125,9 +132,6 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
TALER_transfer_secret_to_planchet_secret (&secret, TALER_transfer_secret_to_planchet_secret (&secret,
coin_num, coin_num,
&ps); &ps);
// TODO: implement cipher handling
alg_values.cipher = TALER_DENOMINATION_RSA;
TALER_planchet_setup_coin_priv (&ps, TALER_planchet_setup_coin_priv (&ps,
&alg_values, &alg_values,
coin_priv); coin_priv);
@ -165,6 +169,20 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
GNUNET_CRYPTO_eddsa_key_get_public (&lh->coin_priv.eddsa_priv, GNUNET_CRYPTO_eddsa_key_get_public (&lh->coin_priv.eddsa_priv,
&old_coin_pub.eddsa_pub); &old_coin_pub.eddsa_pub);
// FIXME-NEXT: this is probably the wrong 'ps'!
// However, the 'right' PS is not something the
// exchange could even give us. So probably we
// really need to change the derivation structure
// during refresh to derive the nonces differently
// and make /link possible!
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Link using PS(%u)=%s\n",
(unsigned int) coin_idx,
TALER_B2S (&ps));
TALER_cs_refresh_nonce_derive (
&ps,
coin_idx,
&pd.blinded_planchet.details.cs_blinded_planchet.nonce);
TALER_coin_ev_hash (&pd.blinded_planchet, TALER_coin_ev_hash (&pd.blinded_planchet,
&pd.denom_pub_hash, &pd.denom_pub_hash,
&coin_envelope_hash); &coin_envelope_hash);

View File

@ -150,6 +150,10 @@ TALER_EXCHANGE_get_melt_data_ (
so this computation is redundant, and here additionally so this computation is redundant, and here additionally
repeated KAPPA times. Could be avoided with slightly repeated KAPPA times. Could be avoided with slightly
more bookkeeping in the future */ more bookkeeping in the future */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Refresh using PS(%u)=%s\n",
j,
TALER_B2S (&ps));
TALER_cs_refresh_nonce_derive ( TALER_cs_refresh_nonce_derive (
ps, ps,
j, j,

View File

@ -527,6 +527,94 @@ TALER_PQ_query_param_blinded_planchet (
} }
/**
* Function called to convert input argument into SQL parameters.
*
* @param cls closure
* @param data pointer to input argument
* @param data_len number of bytes in @a data (if applicable)
* @param[out] param_values SQL data to set
* @param[out] param_lengths SQL length data to set
* @param[out] param_formats SQL format data to set
* @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
* @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
* @param scratch_length number of entries left in @a scratch
* @return -1 on error, number of offsets used in @a scratch otherwise
*/
static int
qconv_exchange_withdraw_values (void *cls,
const void *data,
size_t data_len,
void *param_values[],
int param_lengths[],
int param_formats[],
unsigned int param_length,
void *scratch[],
unsigned int scratch_length)
{
const struct TALER_ExchangeWithdrawValues *alg_values = data;
size_t tlen;
size_t len;
uint32_t be[2];
char *buf;
(void) cls;
(void) data_len;
GNUNET_assert (1 == param_length);
GNUNET_assert (scratch_length > 0);
GNUNET_break (NULL == cls);
be[0] = htonl ((uint32_t) alg_values->cipher);
be[1] = htonl (0x010000); /* magic marker: EWV */
switch (alg_values->cipher)
{
case TALER_DENOMINATION_RSA:
tlen = 0;
break;
case TALER_DENOMINATION_CS:
tlen = sizeof (struct TALER_ExchangeWithdrawCsValues);
break;
default:
GNUNET_assert (0);
}
len = tlen + sizeof (be);
buf = GNUNET_malloc (len);
memcpy (buf,
&be,
sizeof (be));
switch (alg_values->cipher)
{
case TALER_DENOMINATION_RSA:
break;
case TALER_DENOMINATION_CS:
memcpy (&buf[sizeof (be)],
&alg_values->details.cs_values,
tlen);
break;
default:
GNUNET_assert (0);
}
scratch[0] = buf;
param_values[0] = (void *) buf;
param_lengths[0] = len;
param_formats[0] = 1;
return 1;
}
struct GNUNET_PQ_QueryParam
TALER_PQ_query_param_exchange_withdraw_values (
const struct TALER_ExchangeWithdrawValues *alg_values)
{
struct GNUNET_PQ_QueryParam res = {
.conv = &qconv_exchange_withdraw_values,
.data = alg_values,
.num_params = 1
};
return res;
}
/** /**
* Function called to convert input argument into SQL parameters. * Function called to convert input argument into SQL parameters.
* *

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015, 2016, 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 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 terms of the GNU General Public License as published by the Free Software
@ -855,4 +855,110 @@ TALER_PQ_result_spec_blinded_planchet (
} }
/**
* Extract data from a Postgres database @a result at row @a row.
*
* @param cls closure
* @param result where to extract data from
* @param int row to extract data from
* @param fname name (or prefix) of the fields to extract from
* @param[in,out] dst_size where to store size of result, may be NULL
* @param[out] dst where to store the result
* @return
* #GNUNET_YES if all results could be extracted
* #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
*/
static enum GNUNET_GenericReturnValue
extract_exchange_withdraw_values (void *cls,
PGresult *result,
int row,
const char *fname,
size_t *dst_size,
void *dst)
{
struct TALER_ExchangeWithdrawValues *alg_values = dst;
size_t len;
const char *res;
int fnum;
uint32_t be[2];
(void) cls;
(void) dst_size;
fnum = PQfnumber (result,
fname);
if (fnum < 0)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
if (PQgetisnull (result,
row,
fnum))
return GNUNET_NO;
/* if a field is null, continue but
* remember that we now return a different result */
len = PQgetlength (result,
row,
fnum);
res = PQgetvalue (result,
row,
fnum);
if (len < sizeof (be))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
memcpy (&be,
res,
sizeof (be));
if (0x010000 != ntohl (be[1])) /* magic marker: EWV */
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
res += sizeof (be);
len -= sizeof (be);
alg_values->cipher = ntohl (be[0]);
switch (alg_values->cipher)
{
case TALER_DENOMINATION_RSA:
if (0 != len)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
case TALER_DENOMINATION_CS:
if (sizeof (struct TALER_ExchangeWithdrawCsValues) != len)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
memcpy (&alg_values->details.cs_values,
res,
len);
return GNUNET_OK;
default:
GNUNET_break (0);
}
return GNUNET_SYSERR;
}
struct GNUNET_PQ_ResultSpec
TALER_PQ_result_spec_exchange_withdraw_values (
const char *name,
struct TALER_ExchangeWithdrawValues *ewv)
{
struct GNUNET_PQ_ResultSpec res = {
.conv = &extract_exchange_withdraw_values,
.dst = (void *) ewv,
.fname = name
};
return res;
}
/* end of pq_result_helper.c */ /* end of pq_result_helper.c */

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014--2020 Taler Systems SA Copyright (C) 2014--2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as it under the terms of the GNU General Public License as
@ -41,9 +41,12 @@
*/ */
static char *config_file; static char *config_file;
/**
* Special configuration file to use when we want reserves
* to expire 'immediately'.
*/
static char *config_file_expire_reserve_now; static char *config_file_expire_reserve_now;
/** /**
* Exchange configuration data. * Exchange configuration data.
*/ */
@ -54,6 +57,14 @@ static struct TALER_TESTING_ExchangeConfiguration ec;
*/ */
static struct TALER_TESTING_BankConfiguration bc; static struct TALER_TESTING_BankConfiguration bc;
/**
* Some tests behave differently when using CS as we cannot
* re-use the coin private key for different denominations
* due to the derivation of it with the /csr values. Hence
* some tests behave differently in CS mode, hence this
* flag.
*/
static bool uses_cs;
/** /**
* Execute the taler-exchange-wirewatch command with * Execute the taler-exchange-wirewatch command with
@ -142,6 +153,11 @@ run (void *cls,
/** /**
* Withdraw EUR:1 using the SAME private coin key as for the previous coin * Withdraw EUR:1 using the SAME private coin key as for the previous coin
* (in violation of the specification, to be detected on spending!). * (in violation of the specification, to be detected on spending!).
* However, note that this does NOT work with 'CS', as for a different
* denomination we get different R0/R1 values from the exchange, and
* thus will generate a different coin private key as R0/R1 are hashed
* into the coin priv. So here, we fail to 'reuse' the key due to the
* cryptographic construction!
*/ */
TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x", TALER_TESTING_cmd_withdraw_amount_reuse_key ("withdraw-coin-1x",
"create-reserve-1", "create-reserve-1",
@ -180,6 +196,13 @@ run (void *cls,
TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay", TALER_TESTING_cmd_deposit_replay ("deposit-simple-replay",
"deposit-simple", "deposit-simple",
MHD_HTTP_OK), MHD_HTTP_OK),
/* This creates a conflict, as we have the same coin public key (reuse!),
but different denomination public keys (which is not allowed).
However, note that this does NOT work with 'CS', as for a different
denomination we get different R0/R1 values from the exchange, and
thus will generate a different coin private key as R0/R1 are hashed
into the coin priv. So here, we fail to 'reuse' the key due to the
cryptographic construction! */
TALER_TESTING_cmd_deposit ("deposit-reused-coin-key-failure", TALER_TESTING_cmd_deposit ("deposit-reused-coin-key-failure",
"withdraw-coin-1x", "withdraw-coin-1x",
0, 0,
@ -187,7 +210,9 @@ run (void *cls,
"{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
GNUNET_TIME_UNIT_ZERO, GNUNET_TIME_UNIT_ZERO,
"EUR:1", "EUR:1",
MHD_HTTP_CONFLICT), uses_cs
? MHD_HTTP_OK
: MHD_HTTP_CONFLICT),
/** /**
* Try to double spend using different wire details. * Try to double spend using different wire details.
*/ */
@ -230,7 +255,10 @@ run (void *cls,
struct TALER_TESTING_Command refresh[] = { struct TALER_TESTING_Command refresh[] = {
/** /**
* Try to melt the coin that shared the private key with another * Try to melt the coin that shared the private key with another
* coin (should fail). */ * coin (should fail). Note that in the CS-case, we fail also
* with MHD_HTTP_CONFLICT, but for a different reason: here it
* is not a denomination conflict, but a double-spending conflict.
*/
TALER_TESTING_cmd_melt ("refresh-melt-reused-coin-key-failure", TALER_TESTING_cmd_melt ("refresh-melt-reused-coin-key-failure",
"withdraw-coin-1x", "withdraw-coin-1x",
MHD_HTTP_CONFLICT, MHD_HTTP_CONFLICT,
@ -839,7 +867,9 @@ run (void *cls,
config_file), config_file),
/* Check recoup is failing for the coin with the reused coin key */ /* Check recoup is failing for the coin with the reused coin key */
TALER_TESTING_cmd_recoup ("recoup-2x", TALER_TESTING_cmd_recoup ("recoup-2x",
MHD_HTTP_CONFLICT, uses_cs
? MHD_HTTP_OK
: MHD_HTTP_CONFLICT,
"withdraw-coin-1x", "withdraw-coin-1x",
"EUR:1"), "EUR:1"),
TALER_TESTING_cmd_recoup ("recoup-2", TALER_TESTING_cmd_recoup ("recoup-2",
@ -988,6 +1018,7 @@ main (int argc,
NULL); NULL);
cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]); cipher = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
GNUNET_assert (NULL != cipher); GNUNET_assert (NULL != cipher);
uses_cs = (0 == strcmp (cipher, "cs"));
GNUNET_asprintf (&config_file, GNUNET_asprintf (&config_file,
"test_exchange_api-%s.conf", "test_exchange_api-%s.conf",
cipher); cipher);

View File

@ -277,6 +277,7 @@ TALER_planchet_blinding_secret_create (
} }
// FIXME: move to denom.c?
void void
TALER_planchet_setup_coin_priv ( TALER_planchet_setup_coin_priv (
const struct TALER_PlanchetSecretsP *ps, const struct TALER_PlanchetSecretsP *ps,