aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-02-14 23:02:25 +0100
committerChristian Grothoff <christian@grothoff.org>2022-02-14 23:02:25 +0100
commitbd77bcb52dcad4b761f3db0acaa6b71b112a31c2 (patch)
treef519ebc30bf0917d9f2e91667a20beac71284586 /src
parentf4f40a31efd3028dec36c0b84a49617926b5f9c3 (diff)
-towards fixing the protocol
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-httpd_link.c8
-rw-r--r--src/exchange/taler-exchange-httpd_recoup-refresh.c12
-rw-r--r--src/exchange/taler-exchange-httpd_recoup.c12
-rw-r--r--src/exchange/taler-exchange-httpd_refreshes_reveal.c7
-rw-r--r--src/exchange/taler-exchange-httpd_withdraw.c4
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c10
-rw-r--r--src/include/taler_exchangedb_plugin.h9
-rw-r--r--src/lib/exchange_api_link.c17
-rw-r--r--src/lib/exchange_api_recoup.c19
-rw-r--r--src/lib/exchange_api_recoup_refresh.c21
-rw-r--r--src/util/denom.c6
11 files changed, 120 insertions, 5 deletions
diff --git a/src/exchange/taler-exchange-httpd_link.c b/src/exchange/taler-exchange-httpd_link.c
index de10f8b82..47b803ffa 100644
--- a/src/exchange/taler-exchange-httpd_link.c
+++ b/src/exchange/taler-exchange-httpd_link.c
@@ -91,7 +91,13 @@ handle_link_data (void *cls,
TALER_JSON_pack_exchange_withdraw_values ("ewv",
&pos->alg_values),
GNUNET_JSON_pack_data_auto ("link_sig",
- &pos->orig_coin_link_sig));
+ &pos->orig_coin_link_sig),
+ GNUNET_JSON_pack_allow_null (
+ pos->have_nonce
+ ? GNUNET_JSON_pack_data_auto ("cs_nonce",
+ &pos->nonce)
+ : GNUNET_JSON_pack_string ("cs_nonce",
+ NULL)));
if ( (NULL == obj) ||
(0 !=
json_array_append_new (list,
diff --git a/src/exchange/taler-exchange-httpd_recoup-refresh.c b/src/exchange/taler-exchange-httpd_recoup-refresh.c
index 3e0588940..829e2cbd7 100644
--- a/src/exchange/taler-exchange-httpd_recoup-refresh.c
+++ b/src/exchange/taler-exchange-httpd_recoup-refresh.c
@@ -174,6 +174,7 @@ verify_and_execute_recoup_refresh (
const struct TALER_CoinPublicInfo *coin,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
const union TALER_DenominationBlindingKeyP *coin_bks,
+ const struct TALER_CsNonce *nonce,
const struct TALER_CoinSpendSignatureP *coin_sig)
{
struct RecoupContext pc;
@@ -263,6 +264,9 @@ verify_and_execute_recoup_refresh (
TALER_EC_EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED,
NULL);
}
+ if (TALER_DENOMINATION_CS == blinded_planchet.cipher)
+ blinded_planchet.details.cs_blinded_planchet.nonce
+ = *nonce;
TALER_coin_ev_hash (&blinded_planchet,
&coin->denom_pub_hash,
&h_blind);
@@ -360,6 +364,7 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection,
union TALER_DenominationBlindingKeyP coin_bks;
struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_ExchangeWithdrawValues exchange_vals;
+ struct TALER_CsNonce nonce;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&coin.denom_pub_hash),
@@ -371,12 +376,18 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection,
&coin_bks),
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&coin_sig),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_fixed_auto ("cs_nonce",
+ &nonce)),
GNUNET_JSON_spec_end ()
};
memset (&coin,
0,
sizeof (coin));
+ memset (&nonce,
+ 0,
+ sizeof (nonce));
coin.coin_pub = *coin_pub;
ret = TALER_MHD_parse_json_data (connection,
root,
@@ -392,6 +403,7 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection,
&coin,
&exchange_vals,
&coin_bks,
+ &nonce,
&coin_sig);
GNUNET_JSON_parse_free (spec);
return res;
diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c
index f4e426fbb..c635769c6 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -177,6 +177,7 @@ verify_and_execute_recoup (
const struct TALER_CoinPublicInfo *coin,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
const union TALER_DenominationBlindingKeyP *coin_bks,
+ const struct TALER_CsNonce *nonce,
const struct TALER_CoinSpendSignatureP *coin_sig)
{
struct RecoupContext pc;
@@ -268,6 +269,9 @@ verify_and_execute_recoup (
TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
NULL);
}
+ if (TALER_DENOMINATION_CS == blinded_planchet.cipher)
+ blinded_planchet.details.cs_blinded_planchet.nonce
+ = *nonce;
if (GNUNET_OK !=
TALER_coin_ev_hash (&blinded_planchet,
&coin->denom_pub_hash,
@@ -373,6 +377,7 @@ TEH_handler_recoup (struct MHD_Connection *connection,
union TALER_DenominationBlindingKeyP coin_bks;
struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_ExchangeWithdrawValues exchange_vals;
+ struct TALER_CsNonce nonce;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&coin.denom_pub_hash),
@@ -384,12 +389,18 @@ TEH_handler_recoup (struct MHD_Connection *connection,
&coin_bks),
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&coin_sig),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_fixed_auto ("cs_nonce",
+ &nonce)),
GNUNET_JSON_spec_end ()
};
memset (&coin,
0,
sizeof (coin));
+ memset (&nonce,
+ 0,
+ sizeof (nonce));
coin.coin_pub = *coin_pub;
ret = TALER_MHD_parse_json_data (connection,
root,
@@ -408,6 +419,7 @@ TEH_handler_recoup (struct MHD_Connection *connection,
&coin,
&exchange_vals,
&coin_bks,
+ &nonce,
&coin_sig);
GNUNET_JSON_parse_free (spec);
return res;
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index 0d8f7bf9b..779b9df45 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -634,6 +634,13 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
rrc->blinded_planchet = rcds[i].blinded_planchet;
}
+ // FIXME: in CS-case, we MUST check if signatures
+ // already exist under the given nonce
+ // (TODO: check: refresh session hash OK?), and if so,
+ // we MUST return the existing signatures (c0/c1 may have changed!)
+ // and MUST NOT return the fresh signatures!
+ // => change this to a 'do_refresh_reveal' and
+ // change SQL to return existing signatures (if any)!
qs = TEH_plugin->insert_refresh_reveal (TEH_plugin->cls,
melt_serial_id,
num_fresh_coins,
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
index 7572f85d2..3799187c1 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -535,6 +535,10 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
/* Clean up and send back final response */
GNUNET_JSON_parse_free (spec);
+ // FIXME: in CS-case, we MUST re-transmit any _existing_ signature
+ // (if database had a record matching the nonce)
+ // instead of sending a 'fresh' one back (as c0/c1 may differ in
+ // a client attack!
{
MHD_RESULT ret;
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index dfa18e9e3..ce184f48d 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -1218,6 +1218,7 @@ prepare_statements (struct PostgresClosure *pg)
",rrc.ewv"
",rrc.link_sig"
",rrc.freshcoin_index"
+ ",rrc.coin_ev"
" FROM refresh_commitments"
" JOIN refresh_revealed_coins rrc"
" USING (melt_serial_id)"
@@ -6385,6 +6386,7 @@ add_ldl (void *cls,
pos = GNUNET_new (struct TALER_EXCHANGEDB_LinkList);
{
+ struct TALER_BlindedPlanchet bp;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
&transfer_pub),
@@ -6398,6 +6400,8 @@ add_ldl (void *cls,
&pos->alg_values),
TALER_PQ_result_spec_denom_pub ("denom_pub",
&pos->denom_pub),
+ TALER_PQ_result_spec_blinded_planchet ("coin_ev",
+ &bp),
GNUNET_PQ_result_spec_end
};
@@ -6411,6 +6415,12 @@ add_ldl (void *cls,
ldctx->status = GNUNET_SYSERR;
return;
}
+ if (TALER_DENOMINATION_CS == bp.cipher)
+ {
+ pos->nonce = bp.details.cs_blinded_planchet.nonce;
+ pos->have_nonce = true;
+ }
+ TALER_blinded_planchet_free (&bp);
}
if ( (NULL != ldctx->last) &&
(0 == GNUNET_memcmp (&transfer_pub,
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 844de5853..eea170c19 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -1381,11 +1381,20 @@ struct TALER_EXCHANGEDB_LinkList
struct TALER_CoinSpendSignatureP orig_coin_link_sig;
/**
+ * CS nonce, if cipher is CS.
+ */
+ struct TALER_CsNonce nonce;
+
+ /**
* Offset that generated this coin in the refresh
* operation.
*/
uint32_t coin_refresh_offset;
+ /**
+ * Set to true if @e nonce was initialized.
+ */
+ bool have_nonce;
};
diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c
index 6ebb72271..a44ccdcea 100644
--- a/src/lib/exchange_api_link.c
+++ b/src/lib/exchange_api_link.c
@@ -92,6 +92,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
struct TALER_CoinSpendSignatureP link_sig;
union TALER_DenominationBlindingKeyP bks;
struct TALER_ExchangeWithdrawValues alg_values;
+ struct TALER_CsNonce nonce;
uint32_t coin_idx;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denom_pub ("denom_pub",
@@ -104,6 +105,9 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
&link_sig),
GNUNET_JSON_spec_uint32 ("coin_idx",
&coin_idx),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_fixed_auto ("cs_nonce",
+ &nonce)),
GNUNET_JSON_spec_end ()
};
struct TALER_TransferSecretP secret;
@@ -111,6 +115,9 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
struct TALER_CoinPubHash c_hash;
/* parse reply */
+ memset (&nonce,
+ 0,
+ sizeof (nonce));
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
spec,
@@ -143,6 +150,16 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
+ if (TALER_DENOMINATION_CS == alg_values.cipher)
+ {
+ if (GNUNET_is_zero (&nonce))
+ {
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ return GNUNET_SYSERR;
+ }
+ pd.blinded_planchet.details.cs_blinded_planchet.nonce = nonce;
+ }
/* extract coin and signature */
if (GNUNET_OK !=
TALER_denom_sig_unblind (&lci->sig,
diff --git a/src/lib/exchange_api_recoup.c b/src/lib/exchange_api_recoup.c
index a4ad0ccee..9b7201cd0 100644
--- a/src/lib/exchange_api_recoup.c
+++ b/src/lib/exchange_api_recoup.c
@@ -328,6 +328,25 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
&coin_sig),
GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
&bks));
+ if (TALER_DENOMINATION_CS == denom_sig->cipher)
+ {
+ struct TALER_CsNonce nonce;
+
+ // FIXME: add this to the spec!
+ /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
+ it is not strictly clear that the nonce is needed. Best case would be
+ to find a way to include it more 'naturally' somehow, for example with
+ the variant union version of bks! */
+ TALER_cs_withdraw_nonce_derive (ps,
+ &nonce);
+ GNUNET_assert (
+ 0 ==
+ json_object_set_new (recoup_obj,
+ "cs_nonce",
+ GNUNET_JSON_from_data_auto (
+ &nonce)));
+ }
+
{
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
char *end;
diff --git a/src/lib/exchange_api_recoup_refresh.c b/src/lib/exchange_api_recoup_refresh.c
index 9133e5942..02e994155 100644
--- a/src/lib/exchange_api_recoup_refresh.c
+++ b/src/lib/exchange_api_recoup_refresh.c
@@ -332,6 +332,27 @@ TALER_EXCHANGE_recoup_refresh (
&coin_sig),
GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
&bks));
+
+ if (TALER_DENOMINATION_CS == denom_sig->cipher)
+ {
+ struct TALER_CsNonce nonce;
+
+ // FIXME: add this to the spec!
+ /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
+ it is not strictly clear that the nonce is needed. Best case would be
+ to find a way to include it more 'naturally' somehow, for example with
+ the variant union version of bks! */
+ TALER_cs_refresh_nonce_derive (rms,
+ idx,
+ &nonce);
+ GNUNET_assert (
+ 0 ==
+ json_object_set_new (recoup_obj,
+ "cs_nonce",
+ GNUNET_JSON_from_data_auto (
+ &nonce)));
+ }
+
{
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
char *end;
diff --git a/src/util/denom.c b/src/util/denom.c
index 69e723503..30e8dc9d4 100644
--- a/src/util/denom.c
+++ b/src/util/denom.c
@@ -806,18 +806,16 @@ TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
break;
case TALER_DENOMINATION_CS:
+ // FIMXE: c-values MUST NOT be included in idempotency check
+ // during withdraw/refresh, but right now they are!!!
GNUNET_CRYPTO_hash_context_read (
hash_context,
&blinded_planchet->details.cs_blinded_planchet.c[0],
sizeof (struct GNUNET_CRYPTO_CsC) * 2);
-#if FIXME
- /* Must include this for refresh check, but
- must EXCLUDE this in link signature (see TALER_LinkDataPS!) */
GNUNET_CRYPTO_hash_context_read (
hash_context,
&blinded_planchet->details.cs_blinded_planchet.nonce,
sizeof (struct TALER_CsNonce));
-#endif
break;
default:
GNUNET_break (0);